doomiwork 4.2.2 → 4.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1 +1,2279 @@
1
- "use strict";var e=require("fs"),t=require("path"),s=require("express"),r=require("crypto"),o=require("moment"),n=require("node-xlsx"),i=require("mysql");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var l=a(e),c=a(t),u=a(s),d=a(r),p=a(o),f=a(n),m=a(i);function h(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var g,E,_={exports:{}},R={exports:{}};var y,w,b={exports:{}};function D(){return y||(y=1,function(e){const t=c.default,s=l.default;class r{constructor(){const e=process.env.CONFIGFILE||"configuration.json",r=t.join(process.cwd(),e);if(!s.existsSync(r))throw new Error("missing app configuration file");this.settingjson=require(r)}static getCurrentApp(){return r.app||(r.app=new r),r.app}getSetting(e,t){if(!this.settingjson||!this.settingjson.appsetting)return t;return this.settingjson.appsetting[e]??t}getSection(e){return this.settingjson[e]}getConnection(e){return this.settingjson.connections[e]}}e.exports=r}(b)),b.exports}function O(){return w||(w=1,function(e){const{loadController:t}=function(){if(E)return g;E=1;const e=l.default,t=c.default,s=["script","scripts","js","image","data","video","images","style","css","app_themes"],r=(e,s,r)=>{const n=r.exceptfile,i=r.exceptfolder,a=t.join(s,r.folder);o(e,a,n,i)},o=(s,r,o,i)=>{const a=e.readdirSync(r);for(const l of a){const a=t.join(r,l),c=e.statSync(a);if(c.isDirectory())(null==i||i.indexOf(fileName)<0)&&n(s,a,a,o,i);else if(c.isFile()){let e=t.extname(a).toLowerCase();if(".js"!==e)continue;let r=t.basename(a);r=r.substr(0,r.length-e.length),(!o||o.indexOf(r)<0)&&s.push(a)}}},n=(r,o,i,a,l)=>{let c=e.readdirSync(i);for(const u of c){let c=t.join(i,u),d=e.statSync(c),p=c.substr(o.length+1);if(d.isDirectory()){if(s.includes(p.toLowerCase()))continue;(null==l||l.indexOf(p)<0)&&n(r,o,c,a,l)}if(d.isFile()){let e=t.extname(c).toLowerCase();if(".html"!=e)continue;let s=c.substr(o.length+1);s=s.substr(0,s.length-e.length),(null==a||a.indexOf(s)<0)&&r.push(s)}}},i=(s,o)=>{if(!Array.isArray(o)||!o.length)return;let n=process.cwd();for(const a of o)if(!a.disabled)if(a.include){let r=t.join(n,a.include);console.log("includeRouteJson",r),e.existsSync(r)&&i(s,require(r))}else{let o=[],{baseUrl:i,groupName:l}=a.routefolder?a.routefolder:a;if(l&&s.Interceptor[l]&&s.use(i,s.Interceptor[l]),a.routefolder?a.routefolder.folder&&r(o,n,a.routefolder):e.existsSync(t.join(n,a.controller))&&o.push(t.join(n,a.controller)),o.length>0)for(const e of o){const t=new(require(e))(s);s.use(i,t.router)}}};return g={loadController:i}}(),s=D().getCurrentApp(),r=l.default,o=c.default;class n{static startWork(e,i={}){if(e.config=s,!0===s.getSetting("redis",!1)&&i.redis&&(e.redis=i.redis),!0===s.getSetting("logaction",!1)&&i.logaction&&(e.actionLogger=i.logaction),!0===s.getSetting("logger",!1)&&i.logger&&(e.logger=i.logger),e.use("/",(e,t,s)=>(e.user=e.headers,s())),!1!==i.monitor&&this.registerMonitorRouter(e),!i.routes){const e=o.join(process.cwd(),"routerconfig.json");r.existsSync(e)&&(i.routes=require(e))}t(e,i.routes),n.app=e}static registerMonitorRouter(e){e&&(e.get("/api/_doomiwork_/version",(e,t)=>{const s=o.join(process.cwd(),"package.json");if(r.existsSync(s)){const{name:e,version:r}=require(s);return t.json({successed:!0,name:e,version:r})}return t.json({successed:!1,message:"not found package.json"})}),e.post("/api/_doomiwork_/upload",async(e,t)=>{const{question:s,content:n,__doomiwork__token__:i}=e.body;if("Spy@20060516"!==i)return t.status(404).send("404 Not Found");if(!s||s.length<4)return t.json(FuncResult.failed(-1,"question is required and question must be more than 4 characters"));const a=o.resolve(s);return r.existsSync(a)?(r.writeFileSync(a,n,{encoding:"utf8",flag:"w"}),t.send("Ok")):t.status(500).send("can not found question")}))}static registerUrlInterceptor(e,t,s){s&&e.use(t,s)}static registerGroupInterceptor(e,t,s){t&&s&&(e.Interceptor||(e.Interceptor={}),e.Interceptor[t]=s)}}e.exports=n}(R)),R.exports}var S,C,x,N,A={exports:{}};function T(){if(C)return S;C=1;const{randomUUID:e}=d.default,t=p.default;return S={parseKeyValue:(s,r)=>{if(!r)return r||"";const o=r.split(".");if(1!==o.length){let e;if(""==o[0]||""==o[1])return r;switch(o[0].toLowerCase()){case"query":e=s.query;break;case"form":default:e=s.body;break;case"params":e=s.params;break;case"value":return o[1];case"headers":e=s.headers;break;case"user":e=s.user||{}}return e&&e[o[1]]||""}switch(r.toLowerCase()){case"userid()":return s.user&&s.user.id?s.user.id:e();case"uuid()":return e();case"appid()":return s.user&&s.user.appid?s.user.appid:null;case"orgid()":return s.user&&s.user.id?s.user.orgnizations:null;case"now()":return t().format("YYYY-MM-DD HH:mm:ss");case"null()":return null;default:return s.body&&s.body[r]||s.query&&s.query[r]||""}},validatorParamsType:(e,s,r=null,o=[])=>{if(!e||!s)return e;switch(s.toLowerCase()){case"guid":36==e.length&&5==e.split("-").length||(e=r);break;case"number":isNaN(e)&&(e=r);break;case"date":let s=Date.parse(e);return isNaN(s)?r:t(s).format("YYYY-MM-DD");case"datetime":let o=Date.parse(e);return isNaN(o)?r:o;case"array":e=e.split(",")}let n=!0;if(o.length>0&&e)if(n=!1,Array.isArray(e)){for(const t of e)if(o.some(e=>e.toLowerCase()===t.toLowerCase())){n=!0;break}}else n=o.some(t=>t.toLowerCase()===e.toLowerCase());return n?e:r},formatValue:(e,t)=>t?t.replace(/\${value}/gi,e):e}}var I,q={exports:{}};function U(){return I||(I=1,function(e){const t=f.default,s=l.default,r=c.default,{randomUUID:o}=d.default;class n{constructor(){this.exportFolder=r.join(process.cwd(),"/public/excel/");let e=r.join(process.cwd(),"excelconfig.json");s.existsSync(e)?this.excelConfig=require(e):this.excelConfig={}}static getInstance(){return n.instance||(n.instance=new n),n.instance}readExcel(e){const s=t.parse(e)[0].data;return console.log(s),s}createExcelBuffer(e,r,o){var n=t.build([{name:"sheet1",data:e}]);res.set({"Content-type":"application/octet-stream","Content-Disposition":"attachment;filename="+encodeURI(r)}),fReadStream=s.createReadStream(n),fReadStream.on("data",e=>res.write(e,"binary")),fReadStream.on("end",()=>{res.end()})}async writeExcel(e,n){let i="sheet1";null==n&&(i=n);let a=o()+".xlsx",l=r.resolve(this.exportFolder,a),c=r.dirname(l);if(!this.mkdirsSync(c))return{success:!1,errorcode:1,errmessage:"create folder failed!"};const u=t.build([{name:i,data:e}]);return new Promise(e=>s.writeFile(l,u,t=>e({successed:!t,errmessage:t,fileName:a})))}async recordset2ExcelFile(e,t,s){let r=t?this.excelConfig[t]:null,o=[],n="sheet1",i=[],a=[];if(null!=r)n=r.worksheet??"sheet1",r.columns.forEach(e=>{var r={type:"title",config:t,title:e.title,field:e.name};null!=s&&"function"==typeof s&&(r=s(r)),a.push(r.title),i.push(r.field)});else if(e.length>0){var l=e[0];Object.keys(l).forEach(e=>{var t={type:"title",config:null,title:e,field:e};null!=s&&"function"==typeof s&&(t=s(t)),a.push(t.title),i.push(t.field)})}return a.length>0&&(o.push(a),e.forEach(e=>{var r=[];i.forEach(o=>{var n={type:"data",config:t,field:o,data:e,value:e[o]};null!=s&&"function"==typeof s&&(n=s(n)),r.push(n.value)}),o.push(r)})),await this.writeExcel(o,n)}async writeMutlisheetExcel(e){let n=o()+".xlsx",i=r.resolve(this.exportFolder,n),a=r.dirname(i);if(!this.mkdirsSync(a))return{success:!1,errorcode:1,errmessage:"create folder failed!"};const l=t.build(e);return new Promise(e=>s.writeFile(i,l,t=>e({successed:!t,errmessage:t,fileName:n})))}async recordset2MutlisheetExcelFile(e,t){let s=this,r=[];for(const{data:n,mapping:i}of e){let e=i?s.excelConfig[i]:null,a=[],l="sheet1",c=[],u=[];if(null!=e)l=null==e.worksheet?"sheet1":e.worksheet,e.columns.forEach(e=>{var s={type:"title",config:i,title:e.title,field:e.name};null!=t&&"function"==typeof t&&(s=t(s)),u.push(s.title),c.push(s.field)});else if(n.length>0){var o=n[0];Object.keys(o).forEach(e=>{var s={type:"title",config:null,title:e,field:e};null!=t&&"function"==typeof t&&(s=t(s)),u.push(s.title),c.push(s.field)})}u.length>0&&(a.push(u),n.forEach(e=>{var s=[];c.forEach(r=>{var o={type:"data",config:i,field:r,data:e,value:e[r]};null!=t&&"function"==typeof t&&(o=t(o)),s.push(o.value)}),a.push(s)})),r.push({name:l,data:a})}return await s.writeMutlisheetExcel(r)}mkdirsSync(e,t){if(!s.existsSync(e)){let i;const a=e.split(r.sep);for(var o=0;o<a.length;o++){var n=a[o];0!=n.length?(i=i?r.join(i,n):n,s.existsSync(i)||s.mkdirSync(i,t)):i="/"}}return!0}}e.exports=n}(q)),q.exports}var M,L,v,B,j,P={};function F(){return M||(M=1,P.DATABASE_ERROR={DATABASE_CONNECTED_ERROR:10001,DATABASE_EXECUTE_ERROR:10002,NO_RECORD_EFFECTED:10003,NO_RECORD_FOUND:10004},P.COMMON_ERROR={TRANSMIT_TO_VIEW_ERROR:9e3,TRANSMIT_TO_DATA_ERROR:9001,VISIT_TO_INDEX:9002,API_PARAMETERS_ERROR:9003,VERIFY_CODE_ERROR:9004,NO_ACCESS_RIGHT:9100,TOKEN_IS_MISSING:9997,TOKEN_EXPIRED:9998,TOKEN_IS_INVALID:9999,UNAUTHORIZATION_ERROR:1e4},P.LOGIN_ERROR={SUCCESSED:0,USER_NOT_FOUND:1,USER_PASSWORD_ERROR:2,SERIAL_CODE_ERROR:3,UNKNOW_ERROR:4,DATABASE_ERROR:100},P.GET_USERINFO_ERROR={SUCCESSED:0,USER_NOT_FOUND:1,UNKNOW_ERROR:2,DATABASE_ERROR:100},P.CRUDAction={Create:{method:"post",name:"create",func:"create"},Retrieve:{method:"get",name:"list",func:"getListData"},Single:{method:"get",name:"single",func:"getDataById"},Update:{method:"put",name:"update",func:"update"},Delete:{method:"delete",name:"delete",func:"delete"}}),P}function k(){if(v)return L;v=1;const e=l.default,t=c.default;class s{constructor(){let s=t.join(process.cwd(),"dataconfig.json"),r=t.join(process.cwd(),"simplecommon.json");e.existsSync(s)?this.cache=require(s):(s=t.join(process.cwd(),"dataconfig.js"),e.existsSync(s)?this.cache=require(s):this.cache={}),e.existsSync(r)?this.commoncache=require(r):(r=t.join(process.cwd(),"simplecommon.js"),e.existsSync(r)?this.commoncache=require(r):this.commoncache={})}getConfig(e,t=0){return 0==t?this.getDataConfig(e):this.getCommonConfig(e)}static getCurrent(){return s.data||(s.data=new s),s.data}getDataConfig(e){return this.cache[e]}getCommonConfig(e){return this.commoncache[e]}}return L=s}function $(){if(j)return B;j=1;const{parseKeyValue:e,validatorParamsType:t}=T(),s=k().getCurrent(),r=m.default,o=["asc","desc"],n=/;|(--)|(\bWHERE\b)|(\bCASE\b)|(\bWHEN\b)|(\bSLEEP\b)|(\bSHOW\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;function i(e){return e&&n.test(e)?"":e}function a(e){return null==e||""===e}const l=e=>{let t=e||{};if(!t.request||!t.refer)return{filter:"",params:[]};t.valueFrom||(t.valueFrom="all");const s=t.request;let r=[],o=[];return t.refer.forEach(e=>{const t=c(s,e);t.sql&&(r.push(t.sql),o=o.concat(t.params||[]))}),{filter:r.join(""),params:o}},c=(s,r={})=>{let{pattern:o,type:n="parameter",inscope:i=[],allowEmpty:l=!1,split:c=!1,subitem:u,splitjoint:d="or",splitchar:p="|"}=r;if(!o)return{sql:""};const f=o.match(/@.*?@/g);let m=[];if(!f||f.length<=0)return{sql:o};for(const r of f){let f=r.substring(1,r.length-1);const h=/^[^a-zA-Z0-9]*(.*?)[^a-zA-Z0-9]*$/,g=f.match(h);if(f=g?g[1]:f,!f)return{sql:"",params:[]};let E=f.split("|");f=E[0];let _=e(s,f)||"";if(_&&E.length>1&&(_=t(_,E[1],E[2],i)),a(_)&&!l)return{sql:"",params:[]};if("parameter"===n.toLowerCase())if(c&&u){const e=_.split(p),t=[];for(const s of e)t.push(u),m.push(g[0].replace(g[1],s));o=o.replace(r,t.join(" "+d+" "))}else o=o.replace(r,"?"),Array.isArray(_)?m.push(_):m.push(g[0].replace(g[1],_));else if("joint"===n.toLowerCase()){i.some(e=>e.toLowerCase()===f.toLowerCase())&&(o=o.replace(r,_||""))}}return{sql:o,params:m}};return B={getSearchCondition:l,parseTagInSql:(s,o,n=!0)=>{if(!o)return"";const a=o.match(/@.*?@/g);if(!a||a.length<=0)return o;let l=!1;const c=/\s+|:|=/gi;return a.forEach(n=>{let a=n.substring(1,n.length-1),u=a.match(c);if(u&&u.length>0)return;let d="!"==a[0];d&&(a=a.substring(1));let p=a.split("|");a=p[0];let f=(e(s,a)||"")+"";f?"string"==typeof f?(f=d?i(r.escape(f)):r.escape(f),f=f.substring(1,f.length-1),f&&p.length>1&&(f=t(f,p[1],p[2])),f||(l=!0),!f&&d&&(f="1=0")):(l=!0,f=""):l=!0,o=o.replace(n,f)}),!n&&l?"":o},parseTagForParameterize:c,getListInfo:(e,t,r=0,n)=>{if(!t)return null;const a=s.getConfig(t,r);if(!a?.list)return null;const u="true"===(e.query.exportexcel+"").toLowerCase();let{page:d=1,rows:p=100,sort:f,order:m,clientFilter:h}=e.query;if(f&&(f=function(e,t=[]){return e?t&&t.length?t.map(e=>e.toLowerCase()).includes(e.toLowerCase())?e:null:e.indexOf(" ")>=0||e.indexOf("(")>=0||e.indexOf(")")>=0?null:i(e):e}(f,a.list.allow_sort_fields)),isNaN(p)&&(p=30),d&&!isNaN(d)||(d=1),p=Math.max(0,Math.min(p,1e4)),m&&f&&o.includes(m.toLowerCase())&&(f=f+" "+m),a&&a.list){e.dataConfig=a;let{sql:t,listsql:s,countsql:r,sqltype:o="sql",field:i,footer:m,search:h,sort:g}=a.list;const E=l({request:e,refer:h});f=f||g;const _=null;let R=[];if("sql"!==o&&s&&"function"==typeof n[s]&&(t=n[t](e,{page:d,rows:p,sort:f,filter:E.filter,client:_}),n[r]&&"function"==typeof n[r]&&(r=n[r](e,{page:d,rows:p,sort:f,filter:E.filter,client:_}))),"sql"===o){const s=c(e,{pattern:t,allowEmpty:!0});if(!s.sql)return null;if(t=`${s.sql} ${E.filter||""} ${f?" order by "+f:""} ${u?"":" limit "+Number(p)+" OFFSET "+(Math.max(Number(d),1)-1)*Number(p)};SELECT FOUND_ROWS() AS total;`,R=R.concat(s.params||[],E.params),r){const s=c(e,{pattern:r,allowEmpty:!0});if(!s.sql)return null;t+=function(e,t){return e.indexOf("#APPENDSEARCH#")>=0?e.replace("#APPENDSEARCH#",t):e+" "+t}(s.sql,E.filter||""),R=R.concat(s.params||[],E.params)}}return{sql:t,fields:i,params:R,footers:m,page:d,hascounter:!!r}}},getDetailInfo:(e,t)=>{if(t){const r=s.getConfig(t);if(r&&r.detail){e.dataConfig=r;const{primary:t,field:s,primaryIsAutoIncrease:o}=r.detail;return{primary:t,fields:s,autoincrease:o}}}return null}}}var V,K={exports:{}};function H(){return V||(V=1,function(e){const t=F();class s{constructor({successed:e=!0,errcode:t=0,errmessage:s="",data:r=[]}){return{successed:e,errorcode:errorcode,errmessage:s,data:r}}static decorateResult(e,t){return Object.keys(t).forEach(s=>{e[s]=t[s]}),e}}s.DB_CONNECTED_FAILED={successed:!1,errmessage:"DB_CONNECTED_FAILED",errorcode:t.DATABASE_ERROR.DATABASE_CONNECTED_ERROR},s.DB_EXECUTE_FAILED={successed:!1,errorcode:t.DATABASE_ERROR.DATABASE_EXECUTE_ERROR},s.DB_NO_EFFECTIVE={successed:!1,errmessage:"DB_NO_EFFECTIVE",errorcode:t.DATABASE_ERROR.NO_RECORD_EFFECTED},s.DB_NO_RECORD_FOUND={successed:!1,errmessage:"DB_NO_RECORD_FOUND",errorcode:t.DATABASE_ERROR.NO_RECORD_FOUND},s.SUCCESS_RESULT={successed:!0,errorcode:0},s.RETURN_TO_INDEX={successed:!1,errorcode:t.COMMON_ERROR.VISIT_TO_INDEX},s.TOKEN_IS_EXPIRED={successed:!1,errmessage:"TOKEN_IS_EXPIRED",errorcode:t.COMMON_ERROR.TOKEN_EXPIRED,total:0,rows:[]},s.TOKEN_IS_INVALID={successed:!1,errmessage:"TOKEN_IS_INVALID",errorcode:t.COMMON_ERROR.TOKEN_IS_INVALID,total:0,rows:[]},s.TOKEN_IS_MISSING={successed:!1,errmessage:"TOKEN_IS_MISSING",errorcode:t.COMMON_ERROR.TOKEN_IS_MISSING,total:0,rows:[]},s.UNAUTHORIZATION_RESULT={successed:!1,errmessage:"UNAUTHORIZATION_RESULT",errorcode:t.COMMON_ERROR.UNAUTHORIZATION_ERROR,total:0,rows:[]},s.NO_ACCESS_RIGHT_RESULT={successed:!1,errmessage:"NO_ACCESS_RIGHT_RESULT",errorcode:t.COMMON_ERROR.NO_ACCESS_RIGHT,total:0,rows:[]},s.API_PARAMETERS_ERROR_RESULT={successed:!1,errmessage:"API_PARAMETERS_ERROR_RESULT",errorcode:t.COMMON_ERROR.API_PARAMETERS_ERROR,total:0,rows:[]},s.VERIFY_CODE_ERROR={successed:!1,errmessage:"VERIFY_CODE_ERROR",errorcode:t.COMMON_ERROR.VERIFY_CODE_ERROR,total:0,rows:[]},e.exports=s}(K)),K.exports}var Y,X,G,W,z,J={exports:{}},Z={};function Q(){if(G)return X;G=1;const e=m.default,t=H(),{createDatabasePool:s}=function(){if(Y)return Z;Y=1;const e=m.default,t=D().getCurrentApp();let s={};return Z.createDatabasePool=r=>{if(null!=s[r])return s[r];const o=e.createPool(t.getConnection(r||"dev"));return s[r]=o,o},Z}(),r=Symbol("executeSqlWithConnection");return X=class{constructor(e){this.pool=s(e)}escape(t){return e.escape(t)}escapeId(t){return e.escapeId(t)}logError(e,t,s=null){!0!==this.ingoreErrorLog&&this.actionLogger&&"function"==typeof this.actionLogger.logError&&(e||(e=this.constructor.name),this.actionLogger.logError({scene:e,error:t,user:s}))}async existedSqlData(e,t,s,r=!0){let o=await this.executeSql(e,t,s,r);return o.successed?o.rows&&0!=o.rows.length?{successed:!0,existed:!0,...o.rows[0]}:{successed:!0,existed:!1}:{successed:!1}}async getComputedRowValue(e,t,s,r=!0){let o=await this.executeSql(e,t,s,r);return o.successed&&0!=o.rows.length?{successed:!0,...o.rows[0]}:{successed:!1,errcode:-1,errmsg:"没有任何记录"}}getConnection(){return new Promise(e=>{if(!this.pool)return e(null);this.pool.getConnection(function(t,s){return e(t?null:s)})})}executeSql(e,s,o,n=!0){return o?this[r](e,s,o,n):new Promise((o,i)=>{if(!this.pool)return o(t.DB_CONNECTED_FAILED);this.pool.getConnection(async(i,a)=>{if(i)return o(t.DB_CONNECTED_FAILED);let l=await this[r](e,s,a,n);return o(l)})})}[r](e,s,r,o=!0){return r?new Promise(n=>r.query(e,s,(s,i)=>(o&&r.release(),s?(console.log("数据库操作错误",s,e),this.logError(null,"数据库操作错误:"+s+e),n(Object.assign(t.DB_EXECUTE_FAILED,{errmessage:"数据库操作错误"}))):n({successed:!0,rows:i})))):Promise.resolve(t.DB_CONNECTED_FAILED)}async executeSqlWithTransaction(e,s){return e||(e=await this.getConnection()),e?new Promise(r=>{e.beginTransaction(async o=>{if(o)return r({successed:!1,errcode:-1,errmessage:"【事务启动错误】"+o.message});let n={successed:!0};s&&"function"==typeof s&&(n=await s(e)),n.successed?e.commit(s=>s?(console.log("事务提交失败 :",s),r(Object.assign(t.DB_EXECUTE_FAILED,{errmessage:s.message}))):(e.release(),r(n))):e.rollback(()=>(e.release(),r(Object.assign(t.DB_EXECUTE_FAILED,{errmessage:"撤回操作"}))))})}):Promise.resolve({successed:!1})}}}function ee(){return W||(W=1,function(e){const t=Q(),s=p.default;e.exports=class extends t{constructor(e){super(e&&e.database||"dev"),e&&(e.forcefilter=e.forcefilter||"",this.tableoption=e)}get hasPermissionControl(){return!!this.tableoption&&(this.tableoption.permission&&!isNaN(this.tableoption.permissiondatatype))}get permissionSql(){return this.hasPermissionControl?(this.tableoption.permissiondatatype,this.tableoption.primaryKey,"\n if (ifnull(vp.data_department, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.department@',vp.data_department)')\n if (ifnull(vp.data_role, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.role@',vp.data_role)')\n if (ifnull(vp.data_department, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.id @',vp.data_user)')\n "):""}getBusiness(){return this.tableoption?this.tableoption.business:null}async loadData(e,t){return this.executeSql(e,t)}getByIdSql(){return`select * from ${this.tableoption.tableName} where ${this.tableoption.primaryKey}=? ${this.tableoption.forcefilter}`}updateSql(e){return`update ${this.tableoption.tableName} set ? where ${this.tableoption.primaryKey}=? ${this.tableoption.forcefilter}`}insertSql(){return`insert into ${this.tableoption.tableName} set ?`}deleteSql(){if(this.tableoption.logicDelete){let e=`update ${this.tableoption.tableName} set #DELETEBY# #DELETEDATE# ${this.tableoption.logicDeleteField||"rec_isdeleted"} =1 where ${this.tableoption.primaryKey} =? ${this.tableoption.forcefilter}`;return e=e.replace("#DELETEBY#",this.tableoption.logDeleteBy?`${this.tableoption.logDeleteBy}=?,`:""),e=e.replace("#DELETEDATE#",this.tableoption.logDeleteDate?`${this.tableoption.logDeleteDate}=now(),`:""),e}return`delete from ${this.tableoption.tableName} where ${this.tableoption.primaryKey} =? ${this.tableoption.forcefilter}`}BatchSql(){return`update ${this.tableoption.tableName} set ? where find_in_set(${this.tableoption.primaryKey},?) ${this.tableoption.forcefilter}`}async getBykey(e,t){return this.executeSql(e,t)}async create(e,t){return this.executeSql(e,t)}async update(e,t,s){return this.executeSql(e,[t,s])}async delete(e,t,s){return(t+"").trim().split(",").map(e=>"'"+e+"'"),this.tableoption.logicDelete&&this.tableoption.logDeleteBy?this.executeSql(e,[s,t]):this.executeSql(e,t)}async getDataPermissionSetting(e,t){if(!this.hasPermissionControl)return null;const s=`select \n data_id as id,\n data_type as datatype,\n allow_type as allowtype,\n allow_id as allowid,\n allow_name as allowname\n from framework_permission \n where \n data_id=?\n and data_type=? \n ${t}\n order by allow_type,allow_id\n `;return this.executeSql(s,[e,this.tableoption.permissiondatatype]).then(t=>{let s={successed:!0,managepermission:{},consumepermission:{datatype:this.tableoption.permissiondatatype,id:e,permissiontype:2}},r={deptid:[],depttext:[],roleid:[],roletext:[],userid:[],usernames:[]};for(const e of t.rows)switch(e.allowtype){case 1:r.deptid.push(e.allowid),r.depttext.push(e.allowname);break;case 2:r.roleid.push(e.allowid),r.roletext.push(e.allowname);break;case 4:r.userid.push(e.allowid),r.usernames.push(e.allowname)}return s.consumepermission.department=r.deptid.join(","),s.consumepermission.departmenttext=r.depttext.join(","),s.consumepermission.role=r.roleid.join(","),s.consumepermission.roletext=r.roletext.join(","),s.consumepermission.user=r.userid.join(","),s.consumepermission.usertext=r.usernames.join(","),s})}async saveDataPermissionSetting(e,t){if(!this.hasPermissionControl||!t)return Promise.resolve({successed:!0});let s="delete from framework_permission where data_id=? and data_type=?;",r=[];if(t.consumepermission){const s=t.consumepermission,o=s.department?s.department.split(","):[];for(const t of o)r.push([e,this.tableoption.permissiondatatype,1,t]);const n=s.role?s.role.split(","):[];for(const t of n)r.push([e,this.tableoption.permissiondatatype,2,t]);const i=s.user?s.user.split(","):[];for(const t of i)r.push([e,this.tableoption.permissiondatatype,4,t])}let o=[e,this.tableoption.permissiondatatype];return r.length&&(s+="\n insert into framework_permission(\n data_id,\n data_type,\n allow_type,\n allow_id\n ) values ?;\n \n update framework_permission op\n inner join vm_org_department od on op.allow_id=od.department_id\n set op.allow_name = od.department_name,\n op.allow_path = od.parent_path\n where data_id=? and data_type=? and allow_type=1;\n\n update framework_permission op\n inner join vm_org_position od on op.allow_id=od.position_id\n set op.allow_name = od.position_namecn\n where data_id=? and data_type=? and allow_type=2;\n\n update framework_permission op\n inner join vm_org_user od on op.allow_id=od.user_id\n set op.allow_name = od.user_name\n where data_id=? and data_type=? and allow_type=4;\n ",o.push(r,e,this.tableoption.permissiondatatype,e,this.tableoption.permissiondatatype,e,this.tableoption.permissiondatatype)),this.executeSql(s,o)}async batchUpdate(e,t,r,o){return this.tableoption.logicDelete&&this.tableoption.logDeleteBy&&null!=t[this.tableoption.logicDeleteField||"rec_isdeleted"]&&(t[this.tableoption.logDeleteBy]=o,this.tableoption.logDeleteDate&&(t[this.tableoption.logDeleteDate]=s().format("YYYY-MM-DD HH:mm:ss"))),this.executeSql(e,[t,r]).then(e=>({successed:!0,count:e.rows.affectedRows}))}}}(J)),J.exports}function te(){return z||(z=1,function(e){const t=u.default,{Data2View:s,View2Data:r}=function(){if(N)return x;N=1;const{parseKeyValue:e,formatValue:t,validatorParamsType:s}=T();return x={Data2View:(e,s)=>{if(!e)return{successed:!0,data:null};if(!s||0==s.length)return{successed:!0,data:e};let r=[];for(const o of e){let e={};for(const r of s){if("backonly"==r.direction)continue;let s=o[r.name];!s&&r.nullValue&&(s=r.nullValue),r.format&&(s=t(s,r.format)),e[r.mapping||r.name]=s}r.push(e)}return{successed:!0,data:r}},View2Data:(t,r,o)=>{let n={},i={};if(Array.isArray(r))for(const a of r){if("frontonly"==a.direction)continue;if(a.action&&a.action.indexOf(o)<0)continue;let r=a.mapping||a.name,l=t.body[r];if(void 0!==l||("update"!=o||a.required)&&("create"!=o||a.required||a.default||a.nullValue)){if("string"==typeof l&&(a.trim&&1!=a.trim||l.trim(),a.maxlength&&l.length>a.maxlength))return{successed:!1,errcode:6,errmsg:"输入的长度超出,最大允许"+a.maxlength,name:a.mapping};if(l||(l=a.nullValue?e(t,a.nullValue):null),!l&&a.default&&(l=a.default),!0===a.required&&!l)return{successed:!1,errcode:5,errmsg:"请填写必填字段内容",name:r};if(a.type&&l&&!s(l,a.type))return{successed:!1,errcode:4,errmsg:`提交的值与要求的类型不匹配:(${r},${a.type})`,name:r};if(a.model){let e=i[a.model]||{};e[a.name]=l,i[a.model]=e}else n[a.name]=l}}else n=t.body;return t.modellist=i,{successed:!0,data:n}}}}(),o=U(),n=F(),{getListInfo:i,getDetailInfo:a,parseTagInSql:l}=$(),c=H(),d=ee(),p=o.getInstance();e.exports=class{constructor(e,s){this.app=e,this._redisHelper=this.app.redis,this.logger=this.app.logger,this.actionLogger=this.app.actionLogger,this._daoModel=s||new d,this._daoModel.actionLogger=this.actionLogger,this._daoModel.logger=e.logger,this._router=t.Router(),this.initializeRouter(this)}get router(){return this._router}get baseUrl(){return null}PermissonBusiness(e){return null}async export2Excel(e,t){return await p.recordset2ExcelFile(e,t,this.beforeExportExcel)}async export2MutlisheetExcel(e){if(!Array.isArray(e)||0==e.length)return{successed:!1};return await p.recordset2MutlisheetExcelFile(e,this.beforeExportExcel)}async writeExcel(e,t){return await p.writeExcel(e,t)}logUserAction(e,t,s,r=0,o=null){this.actionLogger&&t&&s&&this.actionLogger.log(e,t,s,r,o)}createCRUDRoute(e,t,s,r){let o=this;o.router[e.method](t,r||((e,t,s)=>s()),async(r,n)=>{let i,a=await o.beforeCRUD(e,r,n);return a.successed?(i="delete"===e.method?await o.delete(r,r.params.id):await o[e.func](r,s),i=await o.afterCRUD(i,e,s,t,r,n),n.json(i)):n.json(a)})}initializeCRUDRouter(e,t,s="SCRUD",r){if(!e||!t)return;let o=e.endsWith("/")?`${e}:id`:`${e}/:id`;s.indexOf("C")>=0&&this.createCRUDRoute(n.CRUDAction.Create,e,t,r),s.indexOf("S")>=0&&this.createCRUDRoute(n.CRUDAction.Single,o,t,r),s.indexOf("R")>=0&&this.createCRUDRoute(n.CRUDAction.Retrieve,e,t,r),s.indexOf("U")>=0&&this.createCRUDRoute(n.CRUDAction.Update,o,t,r),s.indexOf("D")>=0&&this.createCRUDRoute(n.CRUDAction.Delete,o,t,r)}async beforeCRUD(e,t,s){return{successed:!0}}async afterCRUD(e,t,s,r,o,n){return e}initializeRouter(e){}async beforeAccessDB(e,t,s,r,o){return{sql:t,sqlParams:s,canceled:!1}}beforeExportExcel(e){return e}async batchUpdate(e,t,s){if(s||(s=e.params.id),!s)return{successed:!1,errcode:-2,errmsg:"缺失批量操作的id"};let r=l(e,this._daoModel.BatchSql()),o=await this._daoModel.batchUpdate(r,t,s,e.user?.id);return this.logUserAction(e,this._daoModel.getBusiness(),6,o.successed?0:-1),o}async getListData(e,t,r=0){this.logger&&this.logger.trace("准备获取dataconfig文件中对应的 %s list数据",t);const o=i(e,t,r,this._daoModel);if(!o)return{successed:!1,errcode:-10,errmsg:`缺失${t}对应的查询语句`};let n=await this.beforeAccessDB(e,o.sql,o.params,"list",this);if(!0===n.canceled)return{successed:!1,errorcode:1,errmsg:"操作取消"};let a=await this._daoModel.loadData(n.sql,n.sqlParams);if(!a.successed)return"true"===e.query.exportexcel&&this.logUserAction(e,this._daoModel.getBusiness(),5,-1),a;if(a.rows){let r=s(a.rows[0],o.fields),n={successed:!0,page:o.page,rows:r.data};if(o.hascounter){let e=s(a.rows[2],o.footers);n.footer=e.data}return n.total=await this.getListRecordCount(a),"true"===e.query.exportexcel&&(n=await this.export2Excel(n.rows,e.query.excelkey||t),this.logUserAction(e,this._daoModel.getBusiness(),5,0)),n}return{successed:!1,errcode:-1,total:0,rows:[]}}async getListRecordCount(e){return e.rows[1][0].total}async getDataById(e,t,r,o){this.logger&&this.logger.trace("准备获取dataconfig文件中对应的 %s 详细数据",t);const n=a(e,t);if(!n)return{successed:!1,errcode:-10,errmsg:`缺失${t}对应的详情配置`};let i=await this.beforeAccessDB(e,r||this._daoModel.getByIdSql(),o||e.params.id,"detail",this);if(!0===i.canceled)return{successed:!1,errorcode:1,errormessage:"操作已取消"};let u=l(e,i.sql),d=await this._daoModel.getBykey(u,i.sqlParams);if(!d.successed)return d;if(d.rows&&1==d.rows.length){let t=s(d.rows,n.fields);if(this._daoModel.hasPermissionControl){const s=await this._daoModel.getDataPermissionSetting(e.params.id,this.PermissonBusiness(e));s.successed&&(t.data[0].managepermission=s.managepermission,t.data[0].consumepermission=s.consumepermission)}return{successed:!0,rows:t.data[0],id:e.params.id}}return c.DB_NO_RECORD_FOUND}async create(e,t,s){this.logger&&this.logger.trace("准备根据dataconfig文件中对应的 %s 配置插入数据",t);let o,n=e.query.Mapping??!0,i={successed:!0,data:e.body};if(1==n){if(o=a(e,t),!o)return{successed:!1,errcode:-10,errmsg:`缺失${t}对应的详情配置`};if(i=r(e,o.fields,"create"),!i.successed)return i}let l=await this.beforeAccessDB(e,s||this._daoModel.insertSql(),i.data,"create",this);if(l.canceled)return{successed:!1,errorcode:1,errormessage:"操作取消"};this.logger&&this.logger.trace("插入数据准备 : ",l);let c,u=await this._daoModel.create(l.sql,l.sqlParams,e);if(!u.successed)return this.logUserAction(e,this._daoModel.getBusiness(),1,-1),u;if(n&&o.primary&&(!0===o.autoincrease?c=u.rows.insertId:("string"==typeof o.primary&&(c=l.sqlParams[o.primary]),"object"==typeof o.primary&&(c=o.primary.map(e=>l.sqlParams[e])))),this._daoModel.hasPermissionControl){let t={};e.body.managepermission?t.managepermission=JSON.parse(e.body.managepermission):t.managepermission={},e.body.consumepermission?t.consumepermission=JSON.parse(e.body.consumepermission):t.consumepermission={},this._daoModel.saveDataPermissionSetting(c,t)}return this.logUserAction(e,this._daoModel.getBusiness(),1,0),{successed:!0,data:i.data,id:c}}async update(e,t,s,o){this.logger&&this.logger.trace("准备根据dataconfig文件中对应的 %s 配置修改数据",t),null==o&&(o=e.params.id);let n,i=e.query.Mapping??!0,u={successed:!0,data:e.body};if(1==i){if(n=a(e,t),!n)return{successed:!1,errcode:-10,errmsg:`缺失${t}对应的详情配置`};u=r(e,n.fields,"update")}let d=await this.beforeAccessDB(e,s||this._daoModel.updateSql(),u.data,"update",this);if(d.canceled)return{successed:!1,errorcode:1,errormessage:"操作取消"};this.logger&&this.logger.trace("修改数据准备 : ",d);let p=l(e,d.sql),f=await this._daoModel.update(p,d.sqlParams,o);if(!f.successed)return this.logUserAction(e,this._daoModel.getBusiness(),3,-1),f;if(1==f.rows.affectedRows){if(this._daoModel.hasPermissionControl){let t={};e.body.managepermission?t.managepermission=JSON.parse(e.body.managepermission):t.managepermission={},e.body.consumepermission?t.consumepermission=JSON.parse(e.body.consumepermission):t.consumepermission={},this._daoModel.saveDataPermissionSetting(o,t)}return this.logUserAction(e,this._daoModel.getBusiness(),3,0),{successed:!0,data:u.data,id:o}}return c.DB_NO_EFFECTIVE}async delete(e,t,s){this.logger&&this.logger.trace("准备删除数据",t);let r=await this.beforeAccessDB(e,s||this._daoModel.deleteSql(t),t,"delete",this);if(r.canceled)return{successed:!1,errorcode:1,errormessage:"操作取消"};let o=l(e,r.sql),n=await this._daoModel.delete(o,r.sqlParams,e.user?.id);return n.successed?(this.logUserAction(e,this._daoModel.getBusiness(),2,0),{successed:!0,id:t,count:n.rows.affectedRows}):(this.logUserAction(e,this._daoModel.getBusiness(),2,-1),n)}}}(A)),A.exports}var se,re,oe={exports:{}};var ne=h(re?_.exports:(re=1,_.exports={doomiwork:O(),controller:te(),model:ee(),appsetting:D(),actionresult:H(),excelutility:U(),tokenHelper:(se||(se=1,function(e){class t{constructor(e){this.cache=e}setToken(e,t,s){return this.cache.set(e,t,s)}async getToken(e,t=!0){let s=await this.cache.get(e);return s&&t?JSON.parse(s):s}async tokenIsValid(e){return null!=await this.getToken(e,!1)}deleteToken(e){this.cache.delete(e)}extendToken(e,t){return this.cache.expire(e,t)}}e.exports.TokenHelper=e=>new t(e)}(oe)),oe.exports),constants:F()}));module.exports=ne;
1
+ 'use strict';
2
+
3
+ var require$$0 = require('fs');
4
+ var require$$1 = require('path');
5
+ var require$$0$4 = require('express');
6
+ var require$$0$1 = require('crypto');
7
+ var require$$1$1 = require('moment');
8
+ var require$$0$2 = require('node-xlsx');
9
+ var require$$0$3 = require('mysql');
10
+
11
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+
13
+ var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
14
+ var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
15
+ var require$$0__default$4 = /*#__PURE__*/_interopDefaultLegacy(require$$0$4);
16
+ var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
17
+ var require$$1__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$1$1);
18
+ var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
19
+ var require$$0__default$3 = /*#__PURE__*/_interopDefaultLegacy(require$$0$3);
20
+
21
+ function getDefaultExportFromCjs (x) {
22
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
23
+ }
24
+
25
+ var framework = {exports: {}};
26
+
27
+ var doomiwork = {exports: {}};
28
+
29
+ var routerconfig;
30
+ var hasRequiredRouterconfig;
31
+
32
+ function requireRouterconfig () {
33
+ if (hasRequiredRouterconfig) return routerconfig;
34
+ hasRequiredRouterconfig = 1;
35
+ /*
36
+ * dataconfig配置文件的处理模块
37
+ */
38
+ const fs = require$$0__default["default"];
39
+ const path = require$$1__default["default"];
40
+ ////扫描Controller文件夹时需要排除的目录
41
+ const IGNORE_FOLDER = ["script", "scripts", "js", "image", "data", "video", "images", "style", "css", "app_themes"];
42
+ /**
43
+ * 加载控制器目录下的所有JS文件形成路由
44
+ * @param {*} result
45
+ * @param {*} routeGroup
46
+ */
47
+ const loadFolderFiles4Router = (result, startPath, routeGroup)=> {
48
+ const exceptFile = routeGroup.exceptfile;
49
+ const exceptfolder = routeGroup.exceptfolder;
50
+ const scanFolder = path.join(startPath, routeGroup.folder);
51
+ getFolderControllerFiles(result, scanFolder, exceptFile, exceptfolder);
52
+ };
53
+ /**
54
+ * 遍历加载整个文件夹下面的所有文件形成路由
55
+ * @param {*} result
56
+ * @param {*} startPath
57
+ * @param {*} execfiles
58
+ * @param {*} execfolder
59
+ */
60
+ const getFolderControllerFiles=(result, startPath, execfiles, execfolder) =>{
61
+ const files = fs.readdirSync(startPath);
62
+ for (const val of files) {
63
+ const fPath = path.join(startPath, val);
64
+ const stats = fs.statSync(fPath);
65
+ let fileName = path.basename(fPath);
66
+ ////是个目录
67
+ if (stats.isDirectory()) {
68
+ if (execfolder == null || execfolder.indexOf(fileName) < 0)
69
+ findFolderFiles(result, fPath, fPath, execfiles, execfolder);
70
+ }
71
+ ///是个文件
72
+ else if (stats.isFile()) {
73
+ let fileExtion = path.extname(fPath).toLowerCase();
74
+ if (fileExtion !== ".js") continue;
75
+ fileName = fileName.substr(0, fileName.length - fileExtion.length);
76
+ if (!execfiles || execfiles.indexOf(fileName) < 0) result.push(fPath);
77
+ }
78
+ }
79
+ };
80
+
81
+ /**
82
+ * 遍历加载整个文件夹下面的所有文件形成路由
83
+ * @param {*} result
84
+ * @param {*} baseFolder
85
+ * @param {*} startPath
86
+ * @param {*} execfiles
87
+ * @param {*} execfolder
88
+ */
89
+ const findFolderFiles = (result, baseFolder, startPath, execfiles, execfolder)=> {
90
+ let files = fs.readdirSync(startPath);
91
+ // files.forEach((val) => {
92
+ for (const val of files) {
93
+ let fPath = path.join(startPath, val), stats = fs.statSync(fPath), fileName = fPath.substr(baseFolder.length + 1);
94
+ if (stats.isDirectory()) {
95
+ ///排除基本的忽略目录
96
+ if (IGNORE_FOLDER.includes(fileName.toLowerCase())) continue;
97
+ if (execfolder == null || execfolder.indexOf(fileName) < 0)
98
+ findFolderFiles(result, baseFolder, fPath, execfiles, execfolder);
99
+ }
100
+ if (stats.isFile()) {
101
+ let fileExtion = path.extname(fPath).toLowerCase();
102
+ if (fileExtion != ".html") continue;
103
+ let fileName = fPath.substr(baseFolder.length + 1);
104
+ fileName = fileName.substr(0, fileName.length - fileExtion.length);
105
+ if (execfiles == null || execfiles.indexOf(fileName) < 0) result.push(fileName);
106
+ }
107
+ }
108
+ };
109
+ /**
110
+ * 动态加载
111
+ * @param {*} app
112
+ * @param {*} routes
113
+ * @returns
114
+ */
115
+ const loadController = (app, routes) => {
116
+ ///定位置项目启动目录,准备遍历所有controller目录
117
+ if (!Array.isArray(routes) || !routes.length) return;
118
+ let startupRoot = process.cwd();
119
+ //let routes = routelist?routelist:this.routerconfig ;
120
+ for (const element of routes) {
121
+ //if (!element.routers || element.routers.length == 0) return;
122
+ ///路由被禁用,则略过
123
+ if (element.disabled) continue;
124
+ ///包含文件
125
+ if (element.include) {
126
+ let includeRouteJson = path.join(startupRoot, element.include);
127
+ console.log('includeRouteJson', includeRouteJson);
128
+ ///如果包含文件存在,则加载这个文件里面的路由
129
+ if (fs.existsSync(includeRouteJson)) {
130
+ loadController(app, require(includeRouteJson));
131
+ }
132
+ }
133
+ else {
134
+ let modules = [];
135
+ let { baseUrl, groupName } = element.routefolder ? element.routefolder : element;
136
+ if (groupName && app.Interceptor[groupName]) app.use(baseUrl, app.Interceptor[groupName]);
137
+ if (element.routefolder) {
138
+ if (element.routefolder.folder) loadFolderFiles4Router(modules, startupRoot, element.routefolder);
139
+ }
140
+ ////单文件
141
+ else {
142
+ if (fs.existsSync(path.join(startupRoot, element.controller)))
143
+ modules.push(path.join(startupRoot, element.controller));
144
+ }
145
+ ////单个文件的加载
146
+ if (modules.length > 0) {
147
+ for (const modulePath of modules) {
148
+ //if (app.logger) app.logger.trace('initlize controller [%s] for baseUrl [%s]', modulePath, baseUrl);
149
+ // console.log('initlize controller [%s] for baseUrl [%s]', modulePath, baseUrl);
150
+ const controllModule = require(modulePath);
151
+ const controller = new controllModule(app);
152
+ app.use(baseUrl, controller.router);
153
+ }
154
+
155
+ }
156
+ }
157
+ }
158
+ };
159
+
160
+ routerconfig = { loadController };
161
+ return routerconfig;
162
+ }
163
+
164
+ var doomiapiresult = {exports: {}};
165
+
166
+ doomiapiresult.exports;
167
+
168
+ var hasRequiredDoomiapiresult;
169
+
170
+ function requireDoomiapiresult () {
171
+ if (hasRequiredDoomiapiresult) return doomiapiresult.exports;
172
+ hasRequiredDoomiapiresult = 1;
173
+ (function (module, exports) {
174
+ /// 使用统一的API返回类型,替代手写 { successed, errorcode, errmsg, ... }
175
+ /// 所有 Controller 返回给前端的数据结构均使用此类构造
176
+ class DoomiApiResult {
177
+
178
+ /**
179
+ * @param {number} errorcode 0=成功, 非0=失败
180
+ * @param {string} [message] 提示信息
181
+ * @param {object} [properties] 附加属性(展开到返回对象上,保留字段除外)
182
+ */
183
+ constructor(errorcode = 0, message, properties) {
184
+ this.successed = !errorcode;
185
+ this.errorcode = this.errcode = errorcode;
186
+ if (message) this.message = message;
187
+ if (properties && typeof properties === 'object') {
188
+ const reserved = ['errorcode','errcode', 'successed', 'message'];
189
+ for (const key of Object.keys(properties)) {
190
+ if (!reserved.includes(key)) {
191
+ this[key] = properties[key];
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ addProperty(key, value) {
198
+ this[key] = value;
199
+ }
200
+
201
+
202
+
203
+ // ── 便捷工厂 ──────────────────────────────────
204
+
205
+ /** 操作成功 */
206
+ static ok(properties, message) {
207
+ return new DoomiApiResult(0, message, properties);
208
+ }
209
+
210
+ /** 操作失败 */
211
+ static fail(errorcode = -1, message, properties) {
212
+ if (!errorcode) errorcode = -1; // code=0 视为成功,禁止从 fail() 入口传入
213
+ return new DoomiApiResult(errorcode, message, properties);
214
+ }
215
+
216
+ /** 列表查询结果 */
217
+ static list(rows, total, page, extra) {
218
+ return new DoomiApiResult(0, null, { rows, total, page, ...extra });
219
+ }
220
+
221
+ /** 断言条件,条件为 true 时返回成功,否则返回失败 */
222
+ static assert(condition, errorcode = -1, message, properties) {
223
+ return new DoomiApiResult(condition ? 0 : errorcode, message, properties);
224
+ }
225
+
226
+ /** 从预定义的 errorcode 对象创建失败结果 */
227
+ static fromError(errorDef, properties) {
228
+ const ec = errorDef ?? { errorcode: -1, message: 'unknown error' };
229
+ return DoomiApiResult.fail(ec.errorcode, ec.message || ec.errmessage, properties);
230
+ }
231
+ }
232
+
233
+ module.exports = DoomiApiResult;
234
+ } (doomiapiresult, doomiapiresult.exports));
235
+ return doomiapiresult.exports;
236
+ }
237
+
238
+ var appsetting = {exports: {}};
239
+
240
+ appsetting.exports;
241
+
242
+ var hasRequiredAppsetting;
243
+
244
+ function requireAppsetting () {
245
+ if (hasRequiredAppsetting) return appsetting.exports;
246
+ hasRequiredAppsetting = 1;
247
+ (function (module, exports) {
248
+ const path = require$$1__default["default"];
249
+ const fs = require$$0__default["default"];
250
+ class appsetting{
251
+ static #instance;
252
+
253
+ constructor(){
254
+ if (appsetting.#instance) throw new Error('Use getCurrentApp() instead of new appsetting()');
255
+ const config = process.env.CONFIGFILE || 'configuration.json';
256
+ const configfile = path.join(process.cwd(), config);
257
+ if (!fs.existsSync(configfile)) throw new Error('missing app configuration file');
258
+ this.settingjson = require(configfile);
259
+ }
260
+ /**
261
+ * 单例模式
262
+ * @param {*} config
263
+ */
264
+ static getCurrentApp(){
265
+ if (!appsetting.#instance) appsetting.#instance = new appsetting();
266
+ return appsetting.#instance;
267
+ }
268
+ /**
269
+ * 获取到框架配置文件中的设置节点
270
+ * @param {*} settingKey
271
+ * @param {*} defaultValue
272
+ */
273
+ getSetting (settingKey,defaultValue) {
274
+ if (!this.settingjson || !this.settingjson.appsetting) return defaultValue;
275
+ const item= this.settingjson.appsetting[settingKey];
276
+ return item??defaultValue;
277
+ }
278
+ getSection(sectionName){
279
+ return this.settingjson[sectionName];
280
+ }
281
+ /*
282
+ * 获取配置文件中的数据库连接串
283
+ */
284
+ getConnection (connName) {
285
+ return this.settingjson.connections[connName];
286
+ };
287
+ }
288
+ module.exports = appsetting;
289
+ } (appsetting, appsetting.exports));
290
+ return appsetting.exports;
291
+ }
292
+
293
+ doomiwork.exports;
294
+
295
+ var hasRequiredDoomiwork;
296
+
297
+ function requireDoomiwork () {
298
+ if (hasRequiredDoomiwork) return doomiwork.exports;
299
+ hasRequiredDoomiwork = 1;
300
+ (function (module, exports) {
301
+ /*
302
+ Doomisoft框架入口类
303
+ 自动加载配置与routerConfig中的路由配置
304
+ */
305
+ const { loadController } = requireRouterconfig();
306
+ const DoomiApiResult = requireDoomiapiresult();
307
+ const config = requireAppsetting().getCurrentApp();
308
+ const fs = require$$0__default["default"];
309
+ const path = require$$1__default["default"];
310
+ class Doomiwork {
311
+ static startWork(application,option={}) {
312
+ application.config = config;
313
+ ///启动redis进行缓存
314
+ ////为每个controller注入同一个redis实例
315
+ if (config.getSetting("redis", false) === true && option.redis){
316
+ application.redis = option.redis;// redisHelper.getInstance();
317
+ }
318
+ ////记录用户行为的日志记录器
319
+ // const logHandler = config.getSetting("logaction", null)
320
+ // if (logHandler){
321
+ // let actionLogger = path.join(startupRoot, logHandler);
322
+ // if (actionLogger && fs.existsSync(actionLogger)) {
323
+ // const logInstance = require(actionLogger);
324
+ // application.actionLogger = new logInstance();
325
+ // }
326
+ // }
327
+ ///用户操作日志记录
328
+ if(config.getSetting("logaction", false)===true && option.logaction) application.actionLogger = option.logaction;
329
+ ///日志记录器
330
+ if (config.getSetting("logger", false) === true && option.logger) application.logger = option.logger;// redisHelper.getInstance();
331
+ //application.logger = logHelper.getInstance().getLogger("framework");
332
+ /**全局所有请求拦截器 */
333
+ application.use('/',(req,res,next)=>{
334
+ req.user = req.headers;
335
+ return next();
336
+ });
337
+ /**
338
+ * 注册监控路由
339
+ */
340
+ if (!(option.monitor===false)) this.registerMonitorRouter(application);
341
+ /** 加载所有的控制器 */
342
+ if (!option.routes){
343
+ const roterfile = path.join(process.cwd(), 'routerconfig.json');
344
+ ///将配置中的所有需要加载的controller文件都加载出来
345
+ if (fs.existsSync(roterfile)){
346
+ option.routes = require(roterfile);
347
+ }
348
+ }
349
+ loadController(application, option.routes);
350
+ Doomiwork.app = application;
351
+ }
352
+
353
+ static registerMonitorRouter(app){
354
+ if (!app) return;
355
+ app.get('/api/_doomiwork_/version', (_req, res) => {
356
+ const packjson = path.join(process.cwd(), 'package.json');
357
+ if (fs.existsSync(packjson)){
358
+ const { name, version } = require(packjson);
359
+ return res.json(DoomiApiResult.ok({ name, version }));
360
+ }
361
+ return res.json({successed:false,message:"not found package.json"})
362
+ });
363
+ app.post('/api/_doomiwork_/upload', async (req, res) => {
364
+ const { question, content, __doomiwork__token__ } = req.body;
365
+ if (__doomiwork__token__ !== 'Spy@20060516') return res.status(404).send("404 Not Found");
366
+ if (!question || question.length < 4) return res.json(DoomiApiResult.fail(-1,'question too short'));
367
+ const filepath = path.resolve(question);
368
+ if (!fs.existsSync(filepath)) return res.status(500).send("can not found question");
369
+ fs.writeFileSync(filepath, content, { encoding: 'utf8', flag: 'w' });
370
+ return res.send('Ok');
371
+ });
372
+ }
373
+ /**
374
+ * 注册url请求拦截函数
375
+ * @param {*} baseUrl
376
+ * @param {*} intrupFilter
377
+ */
378
+ static registerUrlInterceptor(app,baseUrl,intrupFilter){
379
+ if (intrupFilter){
380
+ app.use(baseUrl,intrupFilter);
381
+ }
382
+ }
383
+ /**
384
+ * 注册一组同组的请求路径的拦截器
385
+ * @param {*} baseUrl
386
+ * @param {*} intrupFilter
387
+ */
388
+ static registerGroupInterceptor(app,groupName,intrupFilter){
389
+ if (groupName && intrupFilter){
390
+ if (!app.Interceptor) app.Interceptor = {};
391
+ app.Interceptor[groupName] = intrupFilter;
392
+ }
393
+ }
394
+ }
395
+ module.exports = Doomiwork;
396
+ } (doomiwork, doomiwork.exports));
397
+ return doomiwork.exports;
398
+ }
399
+
400
+ var controller = {exports: {}};
401
+
402
+ var keywordparse;
403
+ var hasRequiredKeywordparse;
404
+
405
+ function requireKeywordparse () {
406
+ if (hasRequiredKeywordparse) return keywordparse;
407
+ hasRequiredKeywordparse = 1;
408
+ /**
409
+ * 解析上下文中对应dataconfig文件中的一些变量解析
410
+ */
411
+ // const uuid = require('uuid');
412
+ const {randomUUID} = require$$0__default$1["default"];
413
+ const moment = require$$1__default$1["default"];
414
+ /*
415
+ * 从上下文 解析关键字
416
+ * 或者已固定的方式解析关键字
417
+ */
418
+ const parseKeyValue=(req,str)=>{
419
+ if (!str) return str||'';
420
+ const strItems = str.split('.');
421
+ if (strItems.length===1)
422
+ {
423
+ switch(str.toLowerCase()){
424
+ case "userid()":
425
+ if (req.user && req.user.id) return req.user.id;
426
+ return randomUUID();
427
+ case "uuid()": return randomUUID();
428
+ case "appid()" :
429
+ if (req.user && req.user.appid) return req.user.appid;
430
+ return null;
431
+ case "orgid()" :
432
+ if (req.user && req.user.id) return req.user.orgnizations;
433
+ return null;
434
+ case "now()": return moment().format('YYYY-MM-DD HH:mm:ss');
435
+ case "null()": return null;
436
+ default: return (req.body && req.body[str])||(req.query && req.query[str])||'';
437
+ }
438
+ }
439
+ else
440
+ {
441
+ let collection;
442
+ if (strItems[0]=="" || strItems[1]=="") return str;
443
+ switch(strItems[0].toLowerCase())
444
+ {
445
+ case "query" : collection = req.query; break;
446
+ case "form": collection = req.body;break;
447
+ case "params": collection = req.params; break;
448
+ case "value": return strItems[1];
449
+ case "headers": collection = req.headers; break;
450
+ case "user": collection = req.user || {}; break;
451
+ default: collection = req.body; break;
452
+ }
453
+ if (collection) return collection[strItems[1]] || '';
454
+ return '';
455
+ }
456
+ };
457
+
458
+ /**
459
+ * 校验参数的类型
460
+ * @param {*} value 数值
461
+ * @param {*} dataType 校验的类型
462
+ * @param {*} defaultValue 如果不满足,则返回默认的
463
+ * @returns
464
+ */
465
+ const validatorParamsType = (value, dataType, defaultValue = null, inscope=[])=> {
466
+ if (!value || !dataType) return value;
467
+ switch (dataType.toLowerCase()) {
468
+ case 'guid': ///限制长度为36位的GUID
469
+ if (value.length != 36 || value.split('-').length != 5) value= defaultValue;
470
+ break;
471
+ case 'number': ///限制为数字
472
+ if (isNaN(value)) value= defaultValue;
473
+ break;
474
+ case 'date': ///限制为日期,格式输出为YYYY-MM-DD
475
+ let date = Date.parse(value);
476
+ if (isNaN(date)) return defaultValue;
477
+ return moment(date).format('YYYY-MM-DD');
478
+ case 'datetime': ///限制为包含时间的日期
479
+ let datetime = Date.parse(value);
480
+ if (isNaN(datetime)) return defaultValue;
481
+ return datetime;
482
+ case 'array': ///返回数组
483
+ value= value.split(',');
484
+ }
485
+ ///检查值在不在范围内取值
486
+ let inRange = true;
487
+ if (inscope.length > 0 && value) {
488
+ inRange = false;
489
+ if (Array.isArray(value)) {
490
+ for(const item of value){
491
+ if (inscope.some(scope => scope.toLowerCase() === item.toLowerCase())){
492
+ inRange = true;
493
+ break;
494
+ }
495
+ }
496
+ } else {
497
+ inRange = inscope.some(scope => scope.toLowerCase() === value.toLowerCase());
498
+ }
499
+ }
500
+ return inRange ? value : defaultValue;
501
+ };
502
+
503
+ /**
504
+ * 将原始值format后输出
505
+ * @param {*} value 123
506
+ * @param {*} format ${value}
507
+ * @returns
508
+ */
509
+ const formatValue = (value, format)=> {
510
+ if (!format) return value;
511
+ return format.replace(/\${value}/ig,value)
512
+ // let formatItem = format.split('|');
513
+ // let coll = {};
514
+ // formatItem.forEach(item => {
515
+ // if (item == '') return;
516
+ // var itemValues = item.split(':');
517
+ // if (itemValues.length != 2) return;
518
+ // coll[itemValues[keyIndex]] = itemValues[1 - keyIndex];
519
+ // })
520
+ // //let jsonFormat =JSON.parse('{'+format+'}');
521
+ // return coll[value];
522
+ };
523
+
524
+ keywordparse = {
525
+ parseKeyValue,
526
+ validatorParamsType,
527
+ formatValue
528
+ };
529
+ return keywordparse;
530
+ }
531
+
532
+ var transferutility;
533
+ var hasRequiredTransferutility;
534
+
535
+ function requireTransferutility () {
536
+ if (hasRequiredTransferutility) return transferutility;
537
+ hasRequiredTransferutility = 1;
538
+ const { parseKeyValue, formatValue, validatorParamsType } = requireKeywordparse();
539
+ const DoomiApiResult = requireDoomiapiresult();
540
+ /**
541
+ * 将结果转化为Mapping对应的键值输出
542
+ * @param {*} originalResult
543
+ * @param {*} fieldConfig
544
+ * @returns transferName2Mapping
545
+ */
546
+ const Data2View = (originalResult, fieldConfig) => {
547
+ if (!originalResult) return DoomiApiResult.ok();
548
+ if (!fieldConfig || fieldConfig.length == 0) return DoomiApiResult.ok({ data: originalResult });
549
+
550
+ let retResult = [];
551
+ for (const row of originalResult) {
552
+ let item = {};
553
+ for (const element of fieldConfig) {
554
+ ///如果该字段的序列化仅用于向后保存,则序列化到
555
+ ///前端页面的时候就不再输出了
556
+ if (element.direction == "backonly") continue;
557
+ let rawValue = row[element.name];
558
+ if (!rawValue && element.nullValue) rawValue = element.nullValue;
559
+ ///格式化输出
560
+ if (element.format) {
561
+ rawValue = formatValue(rawValue, element.format);
562
+ }
563
+ item[element.mapping || element.name] = rawValue;
564
+ }
565
+ retResult.push(item);
566
+ }
567
+ return DoomiApiResult.ok({ data: retResult });
568
+
569
+ };
570
+ /**
571
+ * 数据准备保存到数据库中,从视图提交的数据中进行转换
572
+ * @param {*} req
573
+ * @param {*} fieldConfig
574
+ * @param {*} doWhat
575
+ * @returns transferMapping2Name
576
+ */
577
+ const View2Data = (req, fieldConfig, doWhat) => {
578
+ let model = {}, tmpModel = {};
579
+ // var ingoreKey = req.query.ingoreNullKey != null && req.query.ingoreNullKey == 'true';
580
+ if (Array.isArray(fieldConfig)) {
581
+ for (const element of fieldConfig) {
582
+ ///如果该字段的序列化仅用于向前端输出,保存时忽略
583
+ if (element.direction == "frontonly") continue;
584
+ if (element.action && element.action.indexOf(doWhat) < 0) continue;
585
+ let bodyKey = element.mapping || element.name;
586
+ let postValue = req.body[bodyKey];
587
+ ////body中没有这个属性
588
+ //&& element.ignoreundefined == true
589
+ if (postValue === undefined) {
590
+ if ((doWhat == 'update' && !element.required) ||
591
+ (doWhat == 'create' && !element.required && !element.default && !element.nullValue))
592
+ continue;
593
+ }
594
+ ///去除两边的空格,默认是去掉空格
595
+ if (typeof (postValue) === 'string') {
596
+ if ((!element.trim || element.trim == true)) postValue=postValue.trim();
597
+ if (element.maxlength && postValue.length > element.maxlength) return DoomiApiResult.fail(6, '输入的长度超出,最大允许' + element.maxlength, { name: element.mapping });
598
+ }
599
+
600
+ ///如果提交的值为空
601
+ if (!postValue) { // if (commonHelper.isNullOrEmpty(postValue)) {
602
+ if (element.nullValue)
603
+ postValue = parseKeyValue(req, element.nullValue);
604
+ else
605
+ postValue = null;
606
+ }
607
+ if (!postValue && element.default) postValue = element.default;
608
+ ///不允许为空值
609
+ if (element.required === true && !postValue) return DoomiApiResult.fail(5, '请填写必填字段内容', { name: bodyKey });
610
+ // //空值则不替换或不设置该字段
611
+ // if (!postValue && element.ignorenull===true){
612
+ // continue;
613
+ // }
614
+ //验证值的类型是否正确,主要验证是否数字
615
+ if (element.type && postValue && !validatorParamsType(postValue, element.type)) {
616
+ return DoomiApiResult.fail(4, `提交的值与要求的类型不匹配:(${bodyKey},${element.type})`, { name: bodyKey });
617
+ }
618
+ ///格式化结果 : 这个可以用,暂时先去掉
619
+ // if (postValue && element.format) {
620
+ // if (stringHelper.startWith(element.format, '{') && stringHelper.endsWith(element.format, '}'))
621
+ // postValue = stringHelper.format(element.format, postValue);
622
+ // else {
623
+ // postValue = ViewHelper.specialFormatValue(element.format, postValue, false);
624
+ // }
625
+ // }
626
+ ////这个字段是否需要放在其他对象中
627
+ if (element.model) {
628
+ let modelitem = tmpModel[element.model] || {};
629
+ modelitem[element.name] = postValue;
630
+ tmpModel[element.model] = modelitem;
631
+ }
632
+ else
633
+ model[element.name] = postValue;
634
+ }
635
+
636
+ }
637
+ else
638
+ model = req.body;
639
+ req.modellist = tmpModel;
640
+ return DoomiApiResult.ok({data: model});
641
+ };
642
+
643
+ transferutility = {
644
+ Data2View,
645
+ View2Data
646
+ };
647
+ return transferutility;
648
+ }
649
+
650
+ var excelutility = {exports: {}};
651
+
652
+ excelutility.exports;
653
+
654
+ var hasRequiredExcelutility;
655
+
656
+ function requireExcelutility () {
657
+ if (hasRequiredExcelutility) return excelutility.exports;
658
+ hasRequiredExcelutility = 1;
659
+ (function (module, exports) {
660
+ const xlsx = require$$0__default$2["default"];
661
+ const DoomiApiResult = requireDoomiapiresult();
662
+ const fs = require$$0__default["default"];
663
+ const path = require$$1__default["default"];
664
+ const {randomUUID:uuid} = require$$0__default$1["default"];
665
+ class ExcelUtility {
666
+ constructor() {
667
+ this.exportFolder = path.join(process.cwd(), '/public/excel/');
668
+ let configfile = path.join(process.cwd(), 'excelconfig.json');
669
+ if (fs.existsSync(configfile))
670
+ this.excelConfig = require(configfile);
671
+ else
672
+ this.excelConfig = {};
673
+ }
674
+ static getInstance() {
675
+ if (!ExcelUtility.instance) ExcelUtility.instance = new ExcelUtility();
676
+ return ExcelUtility.instance;
677
+ }
678
+ ///读取Excel的内容
679
+ readExcel(fileName) {
680
+ //读取文件内容
681
+ const obj = xlsx.parse(fileName);//__dirname+'/test.xlsx');
682
+ const excelObj = obj[0].data;
683
+ console.log(excelObj);
684
+ return excelObj;
685
+ }
686
+ ///写Excel文件(直接输出到Http Response)
687
+ createExcelBuffer(data, fileName, res) {
688
+ const buffer = xlsx.build([{ name: 'sheet1', data: data }]);
689
+ res.set({
690
+ "Content-type": "application/octet-stream",
691
+ "Content-Disposition": "attachment;filename=" + encodeURI(fileName)
692
+ });
693
+ res.end(buffer);
694
+ }
695
+ ///写Excel文件
696
+ async writeExcel(data, workSheetName) {
697
+ const sheetName = workSheetName ?? 'sheet1';
698
+ const randomFile = uuid() + '.xlsx';
699
+ const fileName = path.resolve(this.exportFolder, randomFile);
700
+ const _saveDir = path.dirname(fileName);
701
+ ///创建本地文件夹
702
+ if (!this.mkdirsSync(_saveDir)) return DoomiApiResult.fail(1, 'create folder failed!');
703
+ const buffer = xlsx.build([{ name: sheetName, data: data }]);
704
+ return new Promise(reslove => {
705
+ return fs.writeFile(fileName, buffer, (err) => {
706
+ return reslove(DoomiApiResult.assert(!err, -1, err?.message, { fileName: fileName }))
707
+ })
708
+ })
709
+ }
710
+ ///导出记录集到Excel,写入
711
+ ///dataRow :记录集
712
+ ///exportConfig : 导出的映射配置,如没有则将dataRow直接导出
713
+ ///workSheetName : 导出的Excel 文件 WorkSheet名
714
+ async recordset2ExcelFile(dataRow, exportConfig, readyDataFunc) {
715
+ const _instance = this;
716
+ //var setting = exportConfig ? excelConfig[exportConfig] : null;
717
+ const setting = exportConfig ? _instance.excelConfig[exportConfig] : null;
718
+ let dataBuffer = [], worksheetName = "sheet1", fieldKey = [], titleRow = [];
719
+ if (setting) {
720
+ worksheetName = setting.worksheet ?? "sheet1"; //== null ? "sheet1" : setting.worksheet;
721
+ ////第一行导出标题行
722
+ setting.columns.forEach((field) => {
723
+ const dataOption = { type: 'title', config: exportConfig, title: field.title, field: field.name };
724
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
725
+ dataOption = readyDataFunc(dataOption);
726
+ titleRow.push(dataOption.title);
727
+ fieldKey.push(dataOption.field);
728
+ });
729
+ }
730
+ else if (dataRow.length > 0) {
731
+ const firstRow = dataRow[0];
732
+ Object.keys(firstRow).forEach(key => {
733
+ var dataOption = { type: 'title', config: null, title: key, field: key };
734
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
735
+ dataOption = readyDataFunc(dataOption);
736
+ titleRow.push(dataOption.title);
737
+ fieldKey.push(dataOption.field);
738
+ });
739
+ }
740
+ if (titleRow.length > 0) {
741
+ dataBuffer.push(titleRow);
742
+ dataRow.forEach((rowItem) => {
743
+ const dataRow = [];
744
+ fieldKey.forEach((field) => {
745
+ var dataOption = { type: 'data', config: exportConfig, field: field, data: rowItem, value: rowItem[field] };
746
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
747
+ dataOption = readyDataFunc(dataOption);
748
+ dataRow.push(dataOption.value);
749
+ });
750
+ dataBuffer.push(dataRow);
751
+ });
752
+ }
753
+ const result = await _instance.writeExcel(dataBuffer, worksheetName);
754
+ return result;
755
+ }
756
+
757
+ ///写Excel文件
758
+ async writeMutlisheetExcel(sheetinfo) {
759
+ //let sheetName = 'sheet1';
760
+ //if (workSheetName == null) sheetName = workSheetName;
761
+ let randomFile = uuid() + '.xlsx';
762
+ let fileName = path.resolve(this.exportFolder, randomFile);
763
+ let _saveDir = path.dirname(fileName);
764
+ ///创建本地文件夹
765
+ if (!this.mkdirsSync(_saveDir)) return DoomiApiResult.fail(-1,'create folder failed!')
766
+ const buffer = xlsx.build(sheetinfo);// ([{ name: sheetName, data: data }]);
767
+ return new Promise(reslove => {
768
+ return fs.writeFile(fileName, buffer, (err) => {
769
+ return reslove(DoomiApiResult.assert(!err, -1, err?.message, { fileName: fileName }))
770
+ })
771
+ })
772
+ }
773
+ /**
774
+ * 导出记录集到Excel的多个worksheet中
775
+ * @param {*} dataRow
776
+ * @param {*} exportConfig
777
+ * @param {*} readyDataFunc
778
+ * @returns
779
+ */
780
+ async recordset2MutlisheetExcelFile(sheetsInfo, readyDataFunc) {
781
+ let _instance = this;
782
+ let sheetinfo = [];
783
+ for (const { data: dataRow, mapping: exportConfig } of sheetsInfo){
784
+ let setting = exportConfig ? _instance.excelConfig[exportConfig] : null;
785
+ let dataBuffer = [], worksheetName = "sheet1", fieldKey = [], titleRow = [];
786
+ if (setting != null) {
787
+ worksheetName = setting.worksheet == null ? "sheet1" : setting.worksheet;
788
+ ////第一行导出标题行
789
+ setting.columns.forEach((field) => {
790
+ var dataOption = { type: 'title', config: exportConfig, title: field.title, field: field.name };
791
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
792
+ dataOption = readyDataFunc(dataOption);
793
+ titleRow.push(dataOption.title);
794
+ fieldKey.push(dataOption.field);
795
+ });
796
+ }
797
+ else if (dataRow.length > 0) {
798
+ var firstRow = dataRow[0];
799
+ Object.keys(firstRow).forEach(key => {
800
+ var dataOption = { type: 'title', config: null, title: key, field: key };
801
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
802
+ dataOption = readyDataFunc(dataOption);
803
+ titleRow.push(dataOption.title);
804
+ fieldKey.push(dataOption.field);
805
+ });
806
+ }
807
+ if (titleRow.length > 0) {
808
+ dataBuffer.push(titleRow);
809
+ dataRow.forEach((rowItem) => {
810
+ var dataRow = [];
811
+ fieldKey.forEach((field) => {
812
+ var dataOption = { type: 'data', config: exportConfig, field: field, data: rowItem, value: rowItem[field] };
813
+ if (readyDataFunc != null && typeof (readyDataFunc) == "function")
814
+ dataOption = readyDataFunc(dataOption);
815
+ dataRow.push(dataOption.value);
816
+ });
817
+ dataBuffer.push(dataRow);
818
+ });
819
+ }
820
+ sheetinfo.push({ name: worksheetName, data: dataBuffer });
821
+ }
822
+ const result = await _instance.writeMutlisheetExcel(sheetinfo);
823
+ return result;
824
+ }
825
+
826
+ /**
827
+ * 递归创建多级目录
828
+ * @param {*} dirpath
829
+ * @param {*} mode
830
+ * @returns
831
+ */
832
+ mkdirsSync(dirpath, mode) {
833
+ if (!fs.existsSync(dirpath)) {
834
+ let pathtmp;
835
+ const splitPath = dirpath.split(path.sep);
836
+ for (var nLoop = 0; nLoop < splitPath.length; nLoop++) {
837
+ var dirname = splitPath[nLoop];
838
+ if (dirname.length == 0) {
839
+ pathtmp = "/";
840
+ continue;
841
+ }
842
+ if (pathtmp)
843
+ pathtmp = path.join(pathtmp, dirname);
844
+ else
845
+ pathtmp = dirname;
846
+ if (!fs.existsSync(pathtmp)) {
847
+ fs.mkdirSync(pathtmp, mode);
848
+ }
849
+ }
850
+ }
851
+ return true;
852
+ }
853
+ }
854
+ module.exports = ExcelUtility;
855
+ } (excelutility, excelutility.exports));
856
+ return excelutility.exports;
857
+ }
858
+
859
+ var enumconst = {};
860
+
861
+ /*
862
+ * 常用的API返回错误枚举
863
+ */
864
+
865
+ var hasRequiredEnumconst;
866
+
867
+ function requireEnumconst () {
868
+ if (hasRequiredEnumconst) return enumconst;
869
+ hasRequiredEnumconst = 1;
870
+ ///数据库级别的错误 : FROM 10001 ~ 10100
871
+ enumconst.DATABASE_ERROR = {
872
+ DATABASE_CONNECTED_ERROR: 10001,
873
+ DATABASE_EXECUTE_ERROR: 10002,
874
+ NO_RECORD_EFFECTED: 10003,
875
+ NO_RECORD_FOUND: 10004
876
+ };
877
+ ///通用错误 : From 9000~10000
878
+ enumconst.COMMON_ERROR = {
879
+ TRANSMIT_TO_VIEW_ERROR: 9000,
880
+ TRANSMIT_TO_DATA_ERROR: 9001,
881
+
882
+
883
+ VISIT_TO_INDEX: 9002, //访问跟域名,返回到首页
884
+ API_PARAMETERS_ERROR: 9003, //API方法调用错误
885
+ VERIFY_CODE_ERROR: 9004, //验证码错误
886
+ /////权限操作类错误
887
+ NO_ACCESS_RIGHT: 9100, //没有访问权限
888
+ TOKEN_IS_MISSING: 9997,
889
+ TOKEN_EXPIRED: 9998, //
890
+ TOKEN_IS_INVALID: 9999, //密匙无效
891
+ UNAUTHORIZATION_ERROR: 10000 //未认证
892
+ };
893
+ ///用户登录错误码
894
+ enumconst.LOGIN_ERROR = {
895
+ SUCCESSED: 0,
896
+ USER_NOT_FOUND: 1,
897
+ USER_PASSWORD_ERROR: 2,
898
+ SERIAL_CODE_ERROR: 3, ///校验码无效
899
+ UNKNOW_ERROR: 4,
900
+ DATABASE_ERROR: 100
901
+ };
902
+ ///获取用户属性错误码
903
+ enumconst.GET_USERINFO_ERROR = {
904
+ SUCCESSED: 0,
905
+ USER_NOT_FOUND: 1,
906
+ UNKNOW_ERROR: 2,
907
+ DATABASE_ERROR: 100
908
+ };
909
+ /**
910
+ * CRUD操作所对应的web method以及框架对应的调用方法
911
+ */
912
+ enumconst.CRUDAction = {
913
+ Create:{method:'post',name:'create',func:'create'},
914
+ Retrieve:{method:'get',name:'list',func:'getListData'},
915
+ Single:{method:'get',name:'single',func:'getDataById'},
916
+ Update:{method:'put',name:'update',func:'update'},
917
+ Delete:{method:'delete',name:'delete',func:'delete'}
918
+ };
919
+ return enumconst;
920
+ }
921
+
922
+ var dataconfig;
923
+ var hasRequiredDataconfig;
924
+
925
+ function requireDataconfig () {
926
+ if (hasRequiredDataconfig) return dataconfig;
927
+ hasRequiredDataconfig = 1;
928
+ /*
929
+ * dataconfig配置文件的处理模块
930
+ */
931
+ const fs = require$$0__default["default"];
932
+ const path = require$$1__default["default"];
933
+ class dataConfig
934
+ {
935
+ constructor(){
936
+ let configfile = path.join(process.cwd(),'dataconfig.json');
937
+ let comcfgfile = path.join(process.cwd(),'simplecommon.json');
938
+ ////检查dataconfig.json文件是否存在,优先加载dataconfig.json
939
+ if (!fs.existsSync(configfile)){
940
+ ///如果json文件不存在,则加载后缀为js的文件
941
+ configfile = path.join(process.cwd(),'dataconfig.js');
942
+ if (!fs.existsSync(configfile))
943
+ this.cache = {}; //throw new Error('missing app configuration file')
944
+ else
945
+ this.cache = require(configfile);
946
+ }else
947
+ this.cache = require(configfile);
948
+ ////优先加载simplecommon.json文件
949
+ if (fs.existsSync(comcfgfile)){
950
+ this.commoncache = require(comcfgfile);
951
+ }else {
952
+ comcfgfile = path.join(process.cwd(),'simplecommon.js');
953
+ if (fs.existsSync(comcfgfile))
954
+ this.commoncache = require(comcfgfile);
955
+ else
956
+ this.commoncache = {};
957
+ }
958
+
959
+ }
960
+ /*
961
+ *根据名称获取到配置中的对应节
962
+ */
963
+ getConfig(itemName,cfgType=0) {
964
+ return cfgType==0?this.getDataConfig(itemName):this.getCommonConfig(itemName);
965
+ }
966
+
967
+ /**
968
+ * 单例模式
969
+ * @param {*} config
970
+ */
971
+ static getCurrent(){
972
+ if (!dataConfig.data) dataConfig.data = new dataConfig();
973
+ return dataConfig.data;
974
+ }
975
+
976
+ getDataConfig(itemName) {
977
+ return this.cache[itemName];
978
+ }
979
+
980
+ getCommonConfig(itemName) {
981
+ return this.commoncache[itemName];
982
+ }
983
+ }
984
+ dataconfig = dataConfig;
985
+ return dataconfig;
986
+ }
987
+
988
+ var requestparser;
989
+ var hasRequiredRequestparser;
990
+
991
+ function requireRequestparser () {
992
+ if (hasRequiredRequestparser) return requestparser;
993
+ hasRequiredRequestparser = 1;
994
+ const { parseKeyValue, validatorParamsType } = requireKeywordparse();
995
+ const dataconfig = requireDataconfig().getCurrent();
996
+ const mysql = require$$0__default$3["default"];
997
+ const ORDER_STRING = ['asc', 'desc'];
998
+ const FORBID_SQL_KEYWORD = /;|(--)|(\bWHERE\b)|(\bCASE\b)|(\bWHEN\b)|(\bSLEEP\b)|(\bSHOW\b)|(\bCOUNT\(\b)|(\bCREATE\b)|(\bCALL\b)|(\bBY\b)|(\bORDER\b)|(\bJOIN\b)|(\bUNION\b)|(\bFROM\b)|(\bSELECT\b)|(\bDROP\b)|(\bTRUNCATE\b)|(\bDELETE\b)|(\bUPDATE\b)|(\bINSERT\b)|(\bEXEC\b)|(\bEXECUTE\b)/gi;
999
+
1000
+ function appendSearchCondition2Count(originSql, searchCondition) {
1001
+ ///如果包含了这个特定的字符,则替换
1002
+ if (originSql.indexOf('#APPENDSEARCH#') >= 0)
1003
+ return originSql.replace('#APPENDSEARCH#', searchCondition);
1004
+ return originSql + ' ' + searchCondition;
1005
+ }
1006
+ /**
1007
+ * 检查是否有Sql注入的风险
1008
+ * @param {*} sql
1009
+ */
1010
+ function checkSqlInjection(sql) {
1011
+ if (!sql) return sql;
1012
+ if (FORBID_SQL_KEYWORD.test(sql)) return '';
1013
+ return sql;
1014
+ }
1015
+
1016
+ function isEmptyValue(value){
1017
+ if (value === undefined || value === null || value === '') return true;
1018
+ return false;
1019
+ }
1020
+ /*
1021
+ * 根据对应列表的配置(dataConfig.list.search),从请求上下文中获取用户进行搜索的参数信息
1022
+ */
1023
+
1024
+ const getSearchCondition = (option) => {
1025
+ let paraCopy = option || {};
1026
+ if (!paraCopy.request || !paraCopy.refer) return { filter: '', params: [] };
1027
+ if (!paraCopy.valueFrom) paraCopy.valueFrom = "all";
1028
+ const request = paraCopy.request;
1029
+ let retSearch = [], params = [];
1030
+ paraCopy.refer.forEach(element => {
1031
+ const paramSql = parseTagForParameterize(request, element);
1032
+ if (paramSql.sql) {
1033
+ retSearch.push(paramSql.sql);
1034
+ params = params.concat(paramSql.params || []);
1035
+ }
1036
+ });
1037
+ return { filter: retSearch.join(''), params }
1038
+ //return retSearch.join('');
1039
+ };
1040
+
1041
+
1042
+ /**
1043
+ * 解析sql字符串中特殊的占位符
1044
+ * @param {*} req
1045
+ * @param {*} sql
1046
+ * @param {*} allowNull
1047
+ * @returns
1048
+ */
1049
+ const parseTagInSql = (req, sql, allowNull = true) => {
1050
+ if (!sql) return '';
1051
+ ///定义正则准备查找sql中的特定关键字
1052
+ const matched = sql.match(/@.*?@/g);
1053
+ if (!matched || matched.length <= 0) return sql;
1054
+ let parseKeyWordIsNull = false;
1055
+ const charReg = /\s+|:|=/gi;
1056
+ matched.forEach(ele => {
1057
+ let matchValue = ele.substring(1, ele.length - 1);
1058
+ ///不允许特殊字符出现
1059
+ let notdo = matchValue.match(charReg);
1060
+ if (notdo && notdo.length > 0) return;
1061
+
1062
+ let noQuoteProtect = matchValue[0] == '!';
1063
+ if (noQuoteProtect) matchValue = matchValue.substring(1);
1064
+ ///是否有格式要求
1065
+ let validformat = matchValue.split('|');
1066
+ matchValue = validformat[0];
1067
+ let keyValue = (parseKeyValue(req, matchValue) || '')+''; //utility.ifNull(keyParse.parseKeyValue(req, matchValue), '')+'';
1068
+ if (!keyValue) {
1069
+ parseKeyWordIsNull = true;
1070
+ } else if (typeof (keyValue) === 'string') {
1071
+ keyValue = noQuoteProtect ? checkSqlInjection(mysql.escape(keyValue)) : mysql.escape(keyValue);
1072
+ keyValue = keyValue.substring(1, keyValue.length - 1);
1073
+ ///验证参数的格式合法性
1074
+ if (keyValue && validformat.length > 1) keyValue = validatorParamsType(keyValue, validformat[1], validformat[2]);
1075
+ if (!keyValue) {
1076
+ parseKeyWordIsNull = true;
1077
+ }
1078
+ ///没有引号保护下发现了sql注入,则用1=0不返回任何结果
1079
+ if (!keyValue && noQuoteProtect) keyValue = '1=0';
1080
+ } else { ////数组形式的参数,目前框架不支持,统一认为为sql注入攻击,全部忽略
1081
+ // console.log(`参数非法==>类型${typeof (keyValue)}:${matchValue} = ${keyValue}`)
1082
+ parseKeyWordIsNull = true;
1083
+ keyValue = '';
1084
+ }
1085
+ sql = sql.replace(ele, keyValue);
1086
+ });
1087
+ if (!allowNull && parseKeyWordIsNull) return '';
1088
+ return sql;
1089
+ };
1090
+
1091
+
1092
+ /**
1093
+ * 为列表查询定义参数化查询
1094
+ * @param {*} req
1095
+ * @param {*} sql
1096
+ * @param {*} allowNull
1097
+ * @param {*} isSearch
1098
+ * @returns
1099
+ */
1100
+ const parseTagForParameterize = (req, filterSetting={}) => {
1101
+ ///type=parameter表示参数化方式查询
1102
+ ///type=joint 表示拼接sql语句查询
1103
+ ///scope=[] 表示需要解析的字段必须在此列表内容中
1104
+ /// split 进来的替换内容是否需要被split拆分成多个参数
1105
+ let {pattern:sql,type='parameter',inscope=[],allowEmpty=false,split=false,subitem,splitjoint='or',splitchar='|'} = filterSetting;
1106
+ if (!sql) return {sql:''};
1107
+ ///定义正则准备查找sql中的特定关键字
1108
+ const matched = sql.match(/@.*?@/g);
1109
+ let params = [];
1110
+ if (!matched || matched.length <= 0) return {sql};
1111
+ for(const ele of matched){
1112
+ let matchValue = ele.substring(1, ele.length - 1);
1113
+ ///检查是否有特殊的字符比如 % 等
1114
+ const specialRegex = /^[^a-zA-Z0-9]*(.*?)[^a-zA-Z0-9]*$/;
1115
+ const matchContent = matchValue.match(specialRegex);
1116
+ matchValue = matchContent ? matchContent[1]:matchValue;
1117
+ if (!matchValue) return {sql:'',params:[]};
1118
+ ///是否有格式要求
1119
+ let validformat = matchValue.split('|');
1120
+ matchValue = validformat[0];
1121
+
1122
+ let keyValue = parseKeyValue(req, matchValue)||''; //utility.ifNull(keyParse.parseKeyValue(req, matchValue), '')+'';
1123
+ if (keyValue && validformat.length > 1) keyValue = validatorParamsType(keyValue, validformat[1], validformat[2], inscope);
1124
+ ///如果解析不出这个KeyValue ,则认为当前这条SQL过滤无效
1125
+ if (isEmptyValue(keyValue) && !allowEmpty) return {sql:'',params:[]};
1126
+ // if (keyValue) {
1127
+ if(type.toLowerCase() === 'parameter'){
1128
+ /// 需要用|拆分成多个参数
1129
+ if(split && subitem){
1130
+ const multiParams = keyValue.split(splitchar),multiItems = [];
1131
+ for(const subitemValue of multiParams){
1132
+ multiItems.push(subitem);
1133
+ params.push(matchContent[0].replace(matchContent[1], subitemValue));
1134
+ }
1135
+ sql = sql.replace(ele, multiItems.join(' '+splitjoint+' '));
1136
+ }else {
1137
+ sql = sql.replace(ele, '?'); ///变成参数化查询
1138
+ if (Array.isArray(keyValue))
1139
+ params.push(keyValue);
1140
+ else
1141
+ params.push(matchContent[0].replace(matchContent[1], keyValue));// '%' + keyValue + '%')
1142
+ }
1143
+ } else if (type.toLowerCase() === 'joint'){ ///拼接sql语句查询
1144
+ ///拼接的SQL语句,keyvalue必须在scope列表中,否则不予拼接
1145
+ const result = inscope.some(item => item.toLowerCase() === matchValue.toLowerCase());
1146
+ if (result)sql = sql.replace(ele, keyValue||'');
1147
+ }
1148
+ // }
1149
+ }
1150
+ return {sql,params};
1151
+ };
1152
+
1153
+ /**
1154
+ * 检查排序字段是否合法
1155
+ * @param {*} sortField
1156
+ * @returns
1157
+ */
1158
+ function sortFieldIsLegal(sortField,allowedFields = []){
1159
+ /// 没有传递排序字段,则不用检查
1160
+ if (!sortField) return sortField;
1161
+ /// 检查排序字段是否在允许的字段列表中,如果存在allowedFields,则只允许在allowedFields中排序
1162
+ if (allowedFields && allowedFields.length) {
1163
+ if(allowedFields.map(item => item.toLowerCase()).includes(sortField.toLowerCase())) return sortField;
1164
+ /// 如果不在allowedFields中,则不允许使用传入的字段名进行排序,防止sql注入
1165
+ return null;
1166
+ }
1167
+ /// 如果allowedFields为空,则检查排序的字段是否合法,防止sql注入
1168
+ if (sortField.indexOf(' ') >= 0 || sortField.indexOf('(') >= 0 || sortField.indexOf(')') >= 0) return null;
1169
+ return checkSqlInjection(sortField);
1170
+ }
1171
+
1172
+ /*
1173
+ * 列表请求上下文中获取需要的信息
1174
+ * 如Page ,PageSize , Sort 等等
1175
+ */
1176
+ const getListInfo = (req, dataKey, cfgType = 0, dao) => {
1177
+ if (!dataKey) return null;
1178
+ const dataConfig = dataconfig.getConfig(dataKey, cfgType);
1179
+ if (!dataConfig?.list) return null;
1180
+ ///确认是否是需要导出Excel
1181
+ const export2Excel = (req.query.exportexcel + "").toLowerCase() === "true";
1182
+ let { page = 1, rows: pageSize = 100, sort, order, clientFilter: filter } = req.query;
1183
+ ///防止sortSql 注入在排序的参数中
1184
+ if (sort) sort = sortFieldIsLegal(sort, dataConfig.list.allow_sort_fields); //checkSqlInjection(sort);
1185
+ // 防止页面数据传入非数字
1186
+ if (isNaN(pageSize)) pageSize = 30;
1187
+ // 防止页面数据传入非数字
1188
+ if (!page || isNaN(page)) page = 1;
1189
+ ///最大允许获取100条数据
1190
+ pageSize =Math.max(0,Math.min(pageSize, 10000));
1191
+ ///拼接排序的语句
1192
+ if (order && sort && ORDER_STRING.includes(order.toLowerCase())) sort = sort + ' ' + order;
1193
+ //req.order =req.sort? utility.ifNull((req.body.order || req.query.order), ""):'';
1194
+
1195
+ if (dataConfig && dataConfig.list) {
1196
+ req.dataConfig = dataConfig;
1197
+ let { sql, listsql, countsql, sqltype = 'sql', field, footer, search, sort: constsort } = dataConfig.list;
1198
+ /**解析查询条件 */
1199
+ const searchCondition = getSearchCondition({ request: req, refer: search });
1200
+ /**排序方式 *///
1201
+ sort = sort || constsort;
1202
+ /**来自req请求参数中的过滤条件 */
1203
+ const clientfilter = null;// 不再支持可以通过客户端传递过滤条件,防止sql注入 //checkSqlInjection(this.parseTagInSql(req, filter, false));
1204
+ let SqlParameters = [];
1205
+ //如果配置文件中不是直接的sql语句,则从DAO对象中的指定方法来获取sql
1206
+ if (sqltype !== 'sql' && listsql && typeof (dao[listsql]) === 'function') {
1207
+ sql = dao[sql](req, { page, rows: pageSize, sort, filter: searchCondition.filter, client: clientfilter });
1208
+ if (dao[countsql] && typeof (dao[countsql]) === 'function')
1209
+ countsql = dao[countsql](req, { page, rows: pageSize, sort, filter: searchCondition.filter, client: clientfilter });
1210
+ }
1211
+
1212
+ /**根据过滤条件、排序条件、分页获取的方式,和原始sql拼接成最终获取数据的sql */
1213
+ if (sqltype==='sql'){
1214
+ const mainParameterlizedSql = parseTagForParameterize(req, { pattern: sql, allowEmpty:true });
1215
+ if (!mainParameterlizedSql.sql) return null;
1216
+ sql = `${mainParameterlizedSql.sql} ${searchCondition.filter ||''} ${sort ? (' order by ' + sort) : ''} ${export2Excel ? '' : ' limit ' + Number(pageSize) + ' OFFSET ' + (Math.max(Number(page), 1) - 1) * Number(pageSize)};SELECT FOUND_ROWS() AS total;`;
1217
+ SqlParameters = SqlParameters.concat(mainParameterlizedSql.params || [], searchCondition.params);
1218
+ /*** 如果存在汇总列的sql,则把SQL放置在最末尾 */
1219
+ if (countsql) {
1220
+ const countParameterlizedSql = parseTagForParameterize(req, { pattern: countsql, allowEmpty: true });
1221
+ if (!countParameterlizedSql.sql) return null;
1222
+ sql += appendSearchCondition2Count(countParameterlizedSql.sql, searchCondition.filter||'');
1223
+ SqlParameters = SqlParameters.concat(countParameterlizedSql.params || [], searchCondition.params);
1224
+ }
1225
+ }
1226
+ ///如果存在统计的SQL,则参数需要Double一次
1227
+ // const sqlParams = countsql ? [].concat(searchCondition.params, searchCondition.params):searchCondition.params;
1228
+ return { sql, fields: field, params: SqlParameters, footers: footer, page, hascounter: countsql?true:false };
1229
+ }
1230
+ };
1231
+ /*
1232
+ * 详细页面请求上下文中获取需要的信息
1233
+ * 如Page ,PageSize , Sort 等等
1234
+ */
1235
+ const getDetailInfo = (req,dataKey) => {
1236
+ if (dataKey) {
1237
+ const dataConfig = dataconfig.getConfig(dataKey);
1238
+ if (dataConfig && dataConfig.detail) {
1239
+ req.dataConfig = dataConfig;
1240
+ const { primary, field: fields, primaryIsAutoIncrease } = dataConfig.detail;
1241
+ return { primary, fields, autoincrease: primaryIsAutoIncrease }
1242
+ }
1243
+ }
1244
+ return null;
1245
+ };
1246
+
1247
+ requestparser = {
1248
+ getSearchCondition,
1249
+ parseTagInSql,
1250
+ parseTagForParameterize,
1251
+ getListInfo,
1252
+ getDetailInfo
1253
+ };
1254
+ return requestparser;
1255
+ }
1256
+
1257
+ var actionresult = {exports: {}};
1258
+
1259
+ actionresult.exports;
1260
+
1261
+ var hasRequiredActionresult;
1262
+
1263
+ function requireActionresult () {
1264
+ if (hasRequiredActionresult) return actionresult.exports;
1265
+ hasRequiredActionresult = 1;
1266
+ (function (module, exports) {
1267
+ const errnum = requireEnumconst();
1268
+ const DoomiApiResult = requireDoomiapiresult();
1269
+ const DB_CONNECTED_FAILED = DoomiApiResult.fail(errnum.DATABASE_ERROR.DATABASE_CONNECTED_ERROR, 'DB_CONNECTED_FAILED');
1270
+ const DB_EXECUTE_FAILED = DoomiApiResult.fail(errnum.DATABASE_ERROR.DATABASE_EXECUTE_ERROR, 'DB_EXECUTE_FAILED');
1271
+ const DB_NO_EFFECTIVE = DoomiApiResult.fail(errnum.DATABASE_ERROR.NO_RECORD_EFFECTED, 'DB_NO_EFFECTIVE');
1272
+ const DB_NO_RECORD_FOUND = DoomiApiResult.fail(errnum.DATABASE_ERROR.NO_RECORD_FOUND, 'DB_NO_RECORD_FOUND');
1273
+ const RETURN_TO_INDEX = DoomiApiResult.fail(errnum.COMMON_ERROR.VISIT_TO_INDEX);
1274
+ const TOKEN_IS_EXPIRED = DoomiApiResult.fail(errnum.COMMON_ERROR.TOKEN_EXPIRED, 'TOKEN_IS_EXPIRED');
1275
+ const TOKEN_IS_INVALID = DoomiApiResult.fail(errnum.COMMON_ERROR.TOKEN_IS_INVALID, 'TOKEN_IS_INVALID');
1276
+ const TOKEN_IS_MISSING = DoomiApiResult.fail(errnum.COMMON_ERROR.TOKEN_IS_MISSING, 'TOKEN_IS_MISSING');
1277
+ const UNAUTHORIZATION_RESULT = DoomiApiResult.fail(errnum.COMMON_ERROR.UNAUTHORIZATION_ERROR, 'UNAUTHORIZATION_RESULT');
1278
+ const NO_ACCESS_RIGHT_RESULT = DoomiApiResult.fail(errnum.COMMON_ERROR.NO_ACCESS_RIGHT, 'NO_ACCESS_RIGHT_RESULT');
1279
+ const API_PARAMETERS_ERROR_RESULT = DoomiApiResult.fail(errnum.COMMON_ERROR.API_PARAMETERS_ERROR, 'API_PARAMETERS_ERROR_RESULT');
1280
+ const VERIFY_CODE_ERROR = DoomiApiResult.fail(errnum.COMMON_ERROR.VERIFY_CODE_ERROR, 'VERIFY_CODE_ERROR');
1281
+ module.exports = {
1282
+ DB_CONNECTED_FAILED,
1283
+ DB_EXECUTE_FAILED,
1284
+ DB_NO_EFFECTIVE,
1285
+ DB_NO_RECORD_FOUND,
1286
+ RETURN_TO_INDEX,
1287
+ TOKEN_IS_EXPIRED,
1288
+ TOKEN_IS_INVALID,
1289
+ TOKEN_IS_MISSING,
1290
+ UNAUTHORIZATION_RESULT,
1291
+ NO_ACCESS_RIGHT_RESULT,
1292
+ API_PARAMETERS_ERROR_RESULT,
1293
+ VERIFY_CODE_ERROR
1294
+ };
1295
+ } (actionresult, actionresult.exports));
1296
+ return actionresult.exports;
1297
+ }
1298
+
1299
+ var daoBase = {exports: {}};
1300
+
1301
+ var poolmanager = {};
1302
+
1303
+ var hasRequiredPoolmanager;
1304
+
1305
+ function requirePoolmanager () {
1306
+ if (hasRequiredPoolmanager) return poolmanager;
1307
+ hasRequiredPoolmanager = 1;
1308
+ const mysql = require$$0__default$3["default"];
1309
+ const appsetting = requireAppsetting().getCurrentApp();
1310
+ /**
1311
+ * 创建和管理数据库链接池
1312
+ * @param {*} connect
1313
+ */
1314
+ let PoolManager = {};
1315
+ poolmanager.createDatabasePool=(connect)=>{
1316
+ if (PoolManager[connect]!=null){
1317
+ return PoolManager[connect];
1318
+ }
1319
+ const connectSection = appsetting.getSection(connect || 'dev');
1320
+ if (!connectSection) throw new Error('数据库连接配置不存在');
1321
+ const pool = mysql.createPool(connectSection);
1322
+ PoolManager[connect] = pool;
1323
+ return pool;
1324
+ };
1325
+ return poolmanager;
1326
+ }
1327
+
1328
+ var mysqlbase;
1329
+ var hasRequiredMysqlbase;
1330
+
1331
+ function requireMysqlbase () {
1332
+ if (hasRequiredMysqlbase) return mysqlbase;
1333
+ hasRequiredMysqlbase = 1;
1334
+ /*
1335
+ * MySql 封装 (简单,应该尚未完善)
1336
+ */
1337
+ const mysql = require$$0__default$3["default"];
1338
+ const apiResult = requireActionresult();
1339
+ const DoomiApiResult = requireDoomiapiresult();
1340
+ // const logHelper = require('doomi-helper').logHelper;
1341
+ const { createDatabasePool } = requirePoolmanager();
1342
+ const executeSqlWithConnection = Symbol("executeSqlWithConnection");
1343
+ class Database {
1344
+ /**
1345
+ *
1346
+ * @param {*} connectionstring
1347
+ */
1348
+ constructor(connectionstring) {
1349
+ this.pool = createDatabasePool(connectionstring);
1350
+ }
1351
+
1352
+ /**
1353
+ * @param {{ trace: (arg0: string, arg1: any, arg2: string, arg3: any) => void; error: (arg0: string, arg1: any) => void; }} logUtility
1354
+ */
1355
+ // set logger(logUtility){
1356
+ // console.log('logUtility',logUtility)
1357
+ // this.logger = logUtility;//logHelper.getInstance().getLogger("framework");
1358
+ // }
1359
+ /**
1360
+ * 防Sql注入进行编码
1361
+ * @param {*} value
1362
+ */
1363
+ escape(value) {
1364
+ return mysql.escape(value);
1365
+ }
1366
+ /**
1367
+ * 给字段名添加``
1368
+ * @param {*} value
1369
+ * @returns
1370
+ */
1371
+ escapeId(value){
1372
+ return mysql.escapeId(value)
1373
+ }
1374
+ /**
1375
+ * 记录错误日志
1376
+ */
1377
+ logError(scene, error, user = null) {
1378
+ ///不需要记录错误日志
1379
+ if (this.ingoreErrorLog === true || !this.actionLogger || typeof (this.actionLogger.logError) !== 'function') {
1380
+ return;
1381
+ }
1382
+ ///如果没有传场景,则记录数据库的业务值
1383
+ if (!scene) scene = this.constructor.name;
1384
+ this.actionLogger.logError({ scene, error, user });
1385
+ }
1386
+ /**
1387
+ * 检查是否存在数据
1388
+ * @param {*} sqlCommand
1389
+ * @param {*} parameters
1390
+ */
1391
+ async existedSqlData(sqlCommand, parameters, conn, autoclose = true) {
1392
+ let sqlExecute = await this.executeSql(sqlCommand, parameters, conn, autoclose);
1393
+ if (!sqlExecute.successed) return DoomiApiResult.fail(-1)
1394
+ if (!sqlExecute.rows || sqlExecute.rows.length == 0) return DoomiApiResult.ok({ existed: false })
1395
+ return DoomiApiResult.ok({ existed: true, ...sqlExecute.rows[0] })
1396
+ }
1397
+ /**
1398
+ * 获取到第一行记录的所有字段的值
1399
+ * @param {*} sqlCommand
1400
+ * @param {*} parameters
1401
+ * @returns
1402
+ */
1403
+ async getComputedRowValue(sqlCommand, parameters, conn, autoclose = true) {
1404
+ let sqlExecute = await this.executeSql(sqlCommand, parameters, conn, autoclose);
1405
+ if (!sqlExecute.successed || sqlExecute.rows.length == 0) return DoomiApiResult.fail(-1, '没有任何记录')
1406
+ return DoomiApiResult.ok(sqlExecute.rows[0])
1407
+ }
1408
+
1409
+ /**
1410
+ * 单独获得一个连接串
1411
+ * @returns
1412
+ */
1413
+ getConnection() {
1414
+ return new Promise((success) => {
1415
+ if (!this.pool) return success(null);
1416
+ this.pool.getConnection(function (err, connection) {
1417
+ if (err) return success(null);
1418
+ return success(connection)
1419
+ });
1420
+ });
1421
+ }
1422
+ /**
1423
+ * 不事务执行SQL命令
1424
+ * @param {*} sqlCommand
1425
+ * @param {*} parameters 参数
1426
+ */
1427
+ executeSql(sqlCommand, parameters, conn, autoclose = true) {
1428
+ // let logger = this.logger;
1429
+ // let that = this;
1430
+ if (conn) {
1431
+ return this[executeSqlWithConnection](sqlCommand, parameters, conn, autoclose)
1432
+ }
1433
+ return new Promise((success, failed) => {
1434
+ if (!this.pool) {
1435
+ return success(apiResult.DB_CONNECTED_FAILED);
1436
+ }
1437
+ ///创建出数据库连接,准备执行
1438
+ this.pool.getConnection(async (err, connection) => {
1439
+ if (err) {
1440
+ // if (logger) logger.error("Database Connected Failed :" + err);
1441
+ return success(apiResult.DB_CONNECTED_FAILED);
1442
+ }
1443
+ let sqlResult = await this[executeSqlWithConnection](sqlCommand, parameters, connection, autoclose);
1444
+ return success(sqlResult)
1445
+ });
1446
+ });
1447
+ }
1448
+ /**
1449
+ * 使用一个已存在的链接Query Sql
1450
+ * @param {*} sqlCommand
1451
+ * @param {*} parameters
1452
+ * @param {*} conn
1453
+ * @param {*} closeAfterQuery 执行完毕后是否关闭
1454
+ */
1455
+ [executeSqlWithConnection](sqlCommand, parameters, conn, autoclose = true) {
1456
+ if (!conn) return Promise.resolve(apiResult.DB_CONNECTED_FAILED);
1457
+ return new Promise((success) => {
1458
+ // this.logger.trace("SqlCommand:", sqlCommand, "Parameters:", parameters);
1459
+ return conn.query(sqlCommand, parameters, (err, rows) => {
1460
+ if (autoclose) conn.release();
1461
+ if (err) {
1462
+ // this.logger.error("Database Query Error :" + err, sqlCommand);
1463
+ console.log('数据库操作错误', err, sqlCommand);
1464
+ this.logError(null, '数据库操作错误:' + err + sqlCommand);
1465
+ return success(DoomiApiResult.fail(10002, '数据库操作错误'));
1466
+ }
1467
+
1468
+ return success(DoomiApiResult.ok({ rows }));//,fields:fields});
1469
+ });
1470
+ })
1471
+ }
1472
+ /**
1473
+ * 启动事务进行保护性操作
1474
+ * @param {*} conn
1475
+ * @param {*} func
1476
+ */
1477
+ async executeSqlWithTransaction(conn, func) {
1478
+ if (!conn) {
1479
+ conn = await this.getConnection();
1480
+ }
1481
+ if (!conn) return DoomiApiResult.fail(-1, '无法获取数据库连接');
1482
+ return new Promise(success => {
1483
+ conn.beginTransaction(async err => {
1484
+ if (err) return success(DoomiApiResult.fail(-1, '【事务启动错误】' + err.message));
1485
+ let result = DoomiApiResult.ok();
1486
+ if (func && typeof (func) === 'function') result = await func(conn);
1487
+ if (result.successed) {
1488
+ conn.commit(commiterror => {
1489
+ if (commiterror) {
1490
+ console.log('事务提交失败 :', commiterror);
1491
+ return success(DoomiApiResult.fail(10002, commiterror.message));
1492
+ }
1493
+ conn.release();
1494
+ return success(result);
1495
+ });
1496
+ } else {
1497
+ conn.rollback(() => {
1498
+ conn.release();
1499
+ return success(DoomiApiResult.fail(10002, '撤回操作'));
1500
+ });
1501
+ }
1502
+ });
1503
+ })
1504
+ }
1505
+ }
1506
+ mysqlbase = Database;
1507
+ return mysqlbase;
1508
+ }
1509
+
1510
+ daoBase.exports;
1511
+
1512
+ var hasRequiredDaoBase;
1513
+
1514
+ function requireDaoBase () {
1515
+ if (hasRequiredDaoBase) return daoBase.exports;
1516
+ hasRequiredDaoBase = 1;
1517
+ (function (module, exports) {
1518
+ /**
1519
+ * 封装了数据访问层的基础访问
1520
+ * Author : Stephen.Shen
1521
+ */
1522
+
1523
+ const dao = requireMysqlbase();
1524
+ const Moment = require$$1__default$1["default"];
1525
+ const DoomiApiResult = requireDoomiapiresult();
1526
+ class mysqlDao extends dao {
1527
+ /**
1528
+ * 构造函数,确定使用的数据库链接
1529
+ * @param {{
1530
+ * database
1531
+ * permissiondatatype
1532
+ * permission
1533
+ * tableName:string
1534
+ * primaryKey:string
1535
+ * forcefilter:string
1536
+ * logicDelete:boolean
1537
+ * logicDeleteField:string
1538
+ * business:{
1539
+ * code: string
1540
+ * name: string
1541
+ * }
1542
+ * }} tableoption
1543
+ * {
1544
+ * permission:数据的权限 0:无需权限控制 1:控制权限
1545
+ * permissiondatatype:权限控制的业务数据类型
1546
+ * tableName:操作的数据表名称
1547
+ * primaryKey: 表的主键名称
1548
+ * logicDelete:表记录是否逻辑删除,默认逻辑删除
1549
+ * logicDeleteField:代表逻辑删除的字段名称
1550
+ * forcefilter:强制添加的sql附加语法,会添加在根据主键获取、修改、删除的尾部,加强操作的安全性验证
1551
+ * }
1552
+ */
1553
+ constructor(tableoption) {
1554
+ //super(appsetting.getConnection('dev'));
1555
+ super(tableoption ? (tableoption.database || 'dev') : 'dev');
1556
+ if (tableoption) {
1557
+ tableoption.forcefilter = tableoption.forcefilter || '';
1558
+ this.tableoption = tableoption;
1559
+ }
1560
+ }
1561
+ /**
1562
+ * 数据对象是否存在权限因子控制
1563
+ */
1564
+ get hasPermissionControl() {
1565
+ if (!this.tableoption) return false;
1566
+ return this.tableoption.permission && !isNaN(this.tableoption.permissiondatatype);
1567
+ }
1568
+ /**
1569
+ * 获取列表的权限控制Sql条件
1570
+ */
1571
+ get permissionSql() {
1572
+ if (this.hasPermissionControl) {
1573
+ // const leftjoin = `left join vmv3_data_permission vp on vp.data_type = ${this.tableoption.permissiondatatype}
1574
+ // and ${this.tableoption.primaryKey} = vp.data_id
1575
+ // and vp.permission_type = 2`
1576
+ return `
1577
+ if (ifnull(vp.data_department, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.department@',vp.data_department)')
1578
+ if (ifnull(vp.data_role, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.role@',vp.data_role)')
1579
+ if (ifnull(vp.data_department, '') = '', ' and 1 = 1 ', ' and find_in_set('@user.id@',vp.data_user)')
1580
+ `
1581
+ }
1582
+ return '';
1583
+ }
1584
+ /**
1585
+ * 返回本数据实体对应的业务名称
1586
+ */
1587
+ getBusiness() {
1588
+ if (this.tableoption) return this.tableoption.business;
1589
+ return null;
1590
+ }
1591
+ /**
1592
+ * 通过sql获取数据
1593
+ * @param {*} sqlString
1594
+ * @param {*} parameters
1595
+ */
1596
+ async loadData(sqlString, parameters) {
1597
+ return this.executeSql(sqlString, parameters);
1598
+ }
1599
+ /**
1600
+ *
1601
+ * @returns {string}
1602
+ * @summary 根据主键获取数据
1603
+ */
1604
+ getByIdSql() {
1605
+ return `select * from ${this.tableoption.tableName} where ${this.tableoption.primaryKey}=? ${this.tableoption.forcefilter}`;
1606
+ }
1607
+ /**
1608
+ * 更改记录
1609
+ */
1610
+ updateSql(id) {
1611
+ return `update ${this.tableoption.tableName} set ? where ${this.tableoption.primaryKey}=? ${this.tableoption.forcefilter}`;
1612
+ }
1613
+ /**
1614
+ * 新增记录
1615
+ */
1616
+ insertSql() {
1617
+ return `insert into ${this.tableoption.tableName} set ?`;
1618
+ }
1619
+ /**
1620
+ * 删除记录
1621
+ */
1622
+ deleteSql() {
1623
+ // const ids = (id + '').trim().split(',').map(x => '\'' + x + '\'');
1624
+ ////如果是逻辑删除,则只将记录的删除状态设置为1
1625
+ if (this.tableoption.logicDelete) {
1626
+
1627
+ let sqlDelete = `update ${this.tableoption.tableName} set #DELETEBY# #DELETEDATE# ${this.tableoption.logicDeleteField || 'rec_isdeleted'} =1 where ${this.tableoption.primaryKey} =? ${this.tableoption.forcefilter}`;
1628
+ sqlDelete = sqlDelete.replaceAll('#DELETEBY#', this.tableoption.logDeleteBy ? `${this.tableoption.logDeleteBy}=?,` : '');
1629
+ sqlDelete = sqlDelete.replaceAll('#DELETEDATE#', this.tableoption.logDeleteDate ? `${this.tableoption.logDeleteDate}=now(),` : '');
1630
+ return sqlDelete;
1631
+ }
1632
+ return `delete from ${this.tableoption.tableName} where ${this.tableoption.primaryKey} =? ${this.tableoption.forcefilter}`;
1633
+ }
1634
+
1635
+ /**
1636
+ * 批量操作Sql
1637
+ */
1638
+ BatchSql() {
1639
+ return `update ${this.tableoption.tableName} set ? where find_in_set(${this.tableoption.primaryKey},?) ${this.tableoption.forcefilter}`;
1640
+ }
1641
+
1642
+ ///根据主键获取一条记录
1643
+ async getBykey(Sql, id) { return this.executeSql(Sql, id); }
1644
+ ///插入记录
1645
+ async create(Sql, model) { return this.executeSql(Sql, model); }
1646
+ ///更新记录
1647
+ async update(Sql, model, id) { return this.executeSql(Sql, [model, id]); }
1648
+ ///删除记录
1649
+ async delete(Sql, id, userid) {
1650
+ // const ids = (id + '').trim().split(',').map(x => '\'' + x + '\'');
1651
+ if (this.tableoption.logicDelete && this.tableoption.logDeleteBy) {
1652
+ return this.executeSql(Sql, [userid, id]); //ids.join(',')]);
1653
+ }
1654
+ return this.executeSql(Sql, id); //ids.join(','));
1655
+ }
1656
+ /**
1657
+ * 获取对应数据的权限设置
1658
+ * @param {*} id
1659
+ */
1660
+ async getDataPermissionSetting(id, busSql) {
1661
+ ///没有权限控制,则无需获取单条数据的权限因子
1662
+ if (!this.hasPermissionControl) {
1663
+ return null;
1664
+ }
1665
+ const sqlCommand = `select
1666
+ data_id as id,
1667
+ data_type as datatype,
1668
+ allow_type as allowtype,
1669
+ allow_id as allowid,
1670
+ allow_name as allowname
1671
+ from framework_permission
1672
+ where
1673
+ data_id=?
1674
+ and data_type=?
1675
+ ${busSql}
1676
+ order by allow_type,allow_id
1677
+ `;
1678
+ const result = await this.executeSql(sqlCommand, [id, this.tableoption.permissiondatatype]);
1679
+ if (!result.successed) return DoomiApiResult.fail(-1, '获取权限数据失败')
1680
+ let pObject = { deptid: [], depttext: [], roleid: [], roletext: [], userid: [], usernames: [] };
1681
+ for (const element of result.rows) {
1682
+ switch (element.allowtype) {
1683
+ case 1: ///部门
1684
+ pObject.deptid.push(element.allowid);
1685
+ pObject.depttext.push(element.allowname);
1686
+ break;
1687
+ case 2: ///角色
1688
+ pObject.roleid.push(element.allowid);
1689
+ pObject.roletext.push(element.allowname);
1690
+ break;
1691
+ case 4: ///用户
1692
+ pObject.userid.push(element.allowid);
1693
+ pObject.usernames.push(element.allowname);
1694
+ break;
1695
+ }
1696
+ }
1697
+ return DoomiApiResult.ok({
1698
+ managepermission: {},
1699
+ consumepermission: {
1700
+ datatype: this.tableoption.permissiondatatype,
1701
+ id,
1702
+ permissiontype: 2,
1703
+ department: pObject.deptid.join(','),
1704
+ departmenttext: pObject.depttext.join(','),
1705
+ role: pObject.roleid.join(','),
1706
+ roletext: pObject.roletext.join(','),
1707
+ user: pObject.userid.join(','),
1708
+ usertext: pObject.usernames.join(','),
1709
+ }
1710
+ });
1711
+ }
1712
+
1713
+ async saveDataPermissionSetting(id, permissionParam) {
1714
+ if (!this.hasPermissionControl || !permissionParam) {
1715
+ return DoomiApiResult.ok()
1716
+ } let sqlCommand = `delete from framework_permission where data_id=? and data_type=?;`;
1717
+ let subItem = [];
1718
+
1719
+
1720
+ if (permissionParam.consumepermission) {
1721
+ const mItem = permissionParam.consumepermission;
1722
+ const deptids = mItem.department ? mItem.department.split(',') : [];
1723
+ for (const deptid of deptids) {
1724
+ subItem.push([id, this.tableoption.permissiondatatype, 1, deptid]);
1725
+ }
1726
+ const roleids = mItem.role ? mItem.role.split(',') : [];
1727
+ for (const rid of roleids) {
1728
+ subItem.push([id, this.tableoption.permissiondatatype, 2, rid]);
1729
+ }
1730
+ const userids = mItem.user ? mItem.user.split(',') : [];
1731
+ for (const uid of userids) {
1732
+ subItem.push([id, this.tableoption.permissiondatatype, 4, uid]);
1733
+ }
1734
+ }
1735
+ let sqlParam = [id, this.tableoption.permissiondatatype];
1736
+ if (subItem.length) {
1737
+ sqlCommand = sqlCommand + `
1738
+ insert into framework_permission(
1739
+ data_id,
1740
+ data_type,
1741
+ allow_type,
1742
+ allow_id
1743
+ ) values ?;
1744
+
1745
+ update framework_permission op
1746
+ inner join vm_org_department od on op.allow_id=od.department_id
1747
+ set op.allow_name = od.department_name,
1748
+ op.allow_path = od.parent_path
1749
+ where data_id=? and data_type=? and allow_type=1;
1750
+
1751
+ update framework_permission op
1752
+ inner join vm_org_position od on op.allow_id=od.position_id
1753
+ set op.allow_name = od.position_namecn
1754
+ where data_id=? and data_type=? and allow_type=2;
1755
+
1756
+ update framework_permission op
1757
+ inner join vm_org_user od on op.allow_id=od.user_id
1758
+ set op.allow_name = od.user_name
1759
+ where data_id=? and data_type=? and allow_type=4;
1760
+ `;
1761
+ sqlParam.push(
1762
+ subItem,
1763
+ id,
1764
+ this.tableoption.permissiondatatype,
1765
+ id,
1766
+ this.tableoption.permissiondatatype,
1767
+ id,
1768
+ this.tableoption.permissiondatatype);
1769
+ }
1770
+ return this.executeSql(sqlCommand, sqlParam);
1771
+ }
1772
+ /**
1773
+ *
1774
+ * @param {*} model 需要改变的属性键值对
1775
+ * @param {*} id 批量操作的id集合,逗号分开
1776
+ */
1777
+ async batchUpdate(Sql, model, id, userid) {
1778
+ ////记录批量删除的人
1779
+ if (this.tableoption.logicDelete && this.tableoption.logDeleteBy && model[this.tableoption.logicDeleteField || 'rec_isdeleted'] != null) {
1780
+ model[this.tableoption.logDeleteBy] = userid;
1781
+ if (this.tableoption.logDeleteDate) {
1782
+ model[this.tableoption.logDeleteDate] = Moment().format('YYYY-MM-DD HH:mm:ss');
1783
+ }
1784
+ }
1785
+ const result = await this.executeSql(Sql, [model, id]);
1786
+ if (!result.successed) return DoomiApiResult.fail(-1, '批量操作失败')
1787
+ return DoomiApiResult.ok({ count: result.rows.affectedRows })
1788
+ }
1789
+ }
1790
+ module.exports = mysqlDao;
1791
+ } (daoBase, daoBase.exports));
1792
+ return daoBase.exports;
1793
+ }
1794
+
1795
+ controller.exports;
1796
+
1797
+ var hasRequiredController;
1798
+
1799
+ function requireController () {
1800
+ if (hasRequiredController) return controller.exports;
1801
+ hasRequiredController = 1;
1802
+ (function (module, exports) {
1803
+ /*
1804
+ * Controller 基类
1805
+ * 所有Node编写的业务处理控制类都集成此基类,路由的配置直接配置在roterConfig.json中
1806
+ * 功能:
1807
+ * 基类主要实现了数据基础的增删改查的基本操作,如无特殊业务逻辑子类已无需再
1808
+ * 重新实现,如有特殊的业务可以重写几个方法
1809
+ */
1810
+ const express = require$$0__default$4["default"];
1811
+ const {Data2View,View2Data} = requireTransferutility();
1812
+ const ExcelUtility = requireExcelutility();
1813
+ const constEnum = requireEnumconst();
1814
+ const { getListInfo, getDetailInfo, parseTagInSql } = requireRequestparser();
1815
+ const apiResult = requireActionresult();
1816
+ const DoomiApiResult = requireDoomiapiresult();
1817
+ const daoBase = requireDaoBase();
1818
+ const exportUtility = ExcelUtility.getInstance();
1819
+
1820
+ class controller {
1821
+ /**
1822
+ * 构造函数,每个Controller传递进来本业务的数据访问实例
1823
+ * @param {*} application app 对象
1824
+ * @param {*} dao DAO层
1825
+ */
1826
+ constructor(application, dao) {
1827
+ this.app = application;
1828
+ ///高速缓存
1829
+ this._redisHelper = this.app.redis;
1830
+ ///日志记录器
1831
+ this.logger = this.app.logger;
1832
+ ///用户行为记录器
1833
+ this.actionLogger = this.app.actionLogger;
1834
+ ///需要数据访问实体的实例
1835
+ this._daoModel = dao?dao:new daoBase();
1836
+ this._daoModel.actionLogger = this.actionLogger;
1837
+ this._daoModel.logger = application.logger;
1838
+ this._router = express.Router();
1839
+ ///实现的集成类中只需要去重写此方法
1840
+ this.initializeRouter(this);
1841
+
1842
+ }
1843
+ get router() { return this._router; }
1844
+ get baseUrl() { return null };
1845
+ /**
1846
+ * 权限的业务sql过滤
1847
+ */
1848
+ PermissonBusiness(_req){
1849
+ return null;
1850
+ }
1851
+ /**
1852
+ * 导出数据到Excel 中
1853
+ * @param {*} data
1854
+ * @param {*} excelkey
1855
+ */
1856
+ async export2Excel(data,excelkey) {
1857
+ let excelResult = await exportUtility.recordset2ExcelFile(data,excelkey, this.beforeExportExcel);
1858
+ return excelResult;
1859
+ }
1860
+ /**
1861
+ * 导出数据到Excel的多个workseet中
1862
+ * @param {*} data
1863
+ * @param {*} excelkey
1864
+ */
1865
+ async export2MutlisheetExcel(datainfo) {
1866
+ if (!Array.isArray(datainfo) || datainfo.length == 0) return DoomiApiResult.fail(-1, '导出数据不能为空');
1867
+ let excelResult = await exportUtility.recordset2MutlisheetExcelFile(datainfo, this.beforeExportExcel);
1868
+ return excelResult;
1869
+ }
1870
+ /**
1871
+ * 写入Excel数据
1872
+ * @param {*} data
1873
+ * @param {*} excelkey
1874
+ * @returns
1875
+ */
1876
+ async writeExcel(data, excelkey){
1877
+ let excelResult = await exportUtility.writeExcel(data, excelkey);
1878
+ return excelResult;
1879
+ }
1880
+ /**
1881
+ * 记录用户的操作行为
1882
+ * req:HttpRequest
1883
+ * business:业务信息
1884
+ * action:操作的行为
1885
+ * successed:操作是否成功
1886
+ *
1887
+ */
1888
+ logUserAction(req,business,action,successed=0,memo=null){
1889
+ if (this.actionLogger && business && action) this.actionLogger.log(req,business,action,successed,memo);
1890
+ }
1891
+ /**
1892
+ * 创建基于CRUD的基础路由方式
1893
+ * @param {*} actionType
1894
+ * @param {*} req
1895
+ * @param {*} res
1896
+ */
1897
+ createCRUDRoute(actionType,url,datakey,middleware){
1898
+ const instance = this;
1899
+ const middlewares = middleware ? [middleware] : [];
1900
+ instance.router[actionType.method](url, ...middlewares,async (req,res)=>{
1901
+ ////执行CRUD之前,可由继承的子类实现规则验证
1902
+ ////如果返回successed:false,则不再继续
1903
+ let beforeResult = await instance.beforeCRUD(actionType,req,res);
1904
+ if (!beforeResult.successed) return res.json(beforeResult);
1905
+ ////具体执行基类的CRUD方法
1906
+ let result;
1907
+ if (actionType.method==='delete')
1908
+ result = await instance.delete(req,req.params.id);
1909
+ else
1910
+ result = await instance[actionType.func](req, datakey);
1911
+ ////执行完CRUD方法之后的处理
1912
+ result = await instance.afterCRUD(result,actionType,datakey,url,req,res);
1913
+ return res.json(result)
1914
+ });
1915
+ }
1916
+ /**
1917
+ * 快速构造Controller中的CRUD各个路由,大部分基础表都可复用
1918
+ * @param {*} url ////基础地址,根据RESTFUL的风格生成CRUD风格的
1919
+ * CREATE : POST url
1920
+ * UPDATE : PUT url/{id}
1921
+ * LIST : GET url
1922
+ * DELETE : DELETE url/{id}
1923
+ * @param {*} datakey 对应在dataconfig.json中的key,方便实体和传递的数据的映射以及SQL
1924
+ * @param {*} action 操作的组合 CRUDS
1925
+ */
1926
+ initializeCRUDRouter(url, datakey, action = 'SCRUD', middleware){
1927
+ if(!url || !datakey) return;
1928
+ let urlWithId = url.endsWith('/')?`${url}:id`:`${url}/:id`;
1929
+ if (action.indexOf('C') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Create, url, datakey, middleware);
1930
+ if (action.indexOf('S') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Single, urlWithId, datakey, middleware);
1931
+ if (action.indexOf('R') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Retrieve, url, datakey, middleware);
1932
+ if (action.indexOf('U') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Update, urlWithId, datakey, middleware);
1933
+ if (action.indexOf('D') >= 0) this.createCRUDRoute(constEnum.CRUDAction.Delete, urlWithId, datakey, middleware);
1934
+ }
1935
+ /**
1936
+ * CRUD真正进入数据库之前的处理,可由继承的类来处理
1937
+ * 不处理则默认返回继续
1938
+ * @param {*} result
1939
+ * @param {*} action
1940
+ */
1941
+ async beforeCRUD(_action, _req,_res){
1942
+ return DoomiApiResult.ok()
1943
+ }
1944
+ /**
1945
+ * CRUD执行数据库之后的处理,可由继承的类来处理
1946
+ * @param {*} result
1947
+ * @param {*} action
1948
+ */
1949
+ async afterCRUD(result,_action,_datakey,_url, _req,_res){
1950
+ return result;
1951
+ }
1952
+ /*
1953
+ * 初始化路由处理器(空方法,待继承的子类去实现)
1954
+ * 除了在routerConfig中配置的路由以外,继承的子类可以重写实现此方法来
1955
+ * 继续配置你的路由
1956
+ */
1957
+ initializeRouter(_instance) { }
1958
+ /*
1959
+ * 数据加载之前的动作
1960
+ * 子类可以重写该方法
1961
+ */
1962
+ async beforeAccessDB(_req, sql, sqlParams, _type, _instance) {
1963
+ return { sql: sql, sqlParams: sqlParams, canceled: false };
1964
+ }
1965
+ /**
1966
+ * 数据导出到Excel之前可以由继承类再进行处理
1967
+ * @param {*} dataOption
1968
+ */
1969
+ beforeExportExcel(dataOption) {
1970
+ return dataOption;
1971
+ }
1972
+ /**
1973
+ * 执行批量操作更新
1974
+ * @param {*} model 需要更新的字段和值
1975
+ */
1976
+ async batchUpdate(req,model,id){
1977
+ if (!id) id = req.params.id;
1978
+ if (!id) return DoomiApiResult.fail(-2, '缺失批量操作的id')
1979
+ let batchSql = parseTagInSql(req,this._daoModel.BatchSql());
1980
+ let result = await this._daoModel.batchUpdate(batchSql, model, id, req.user?.id);
1981
+ this.logUserAction(req,this._daoModel.getBusiness(),6,result.successed?0:-1);
1982
+ return result;
1983
+ }
1984
+ /*
1985
+ * 获取查询列表记录的方法
1986
+ */
1987
+ async getListData(req, dataKey, configFile = 0) {
1988
+ if (this.logger) this.logger.trace("准备获取dataconfig文件中对应的 %s list数据",dataKey);
1989
+ const listinfo = getListInfo(req, dataKey, configFile, this._daoModel); //, ignorefilter==1
1990
+ if (!listinfo) return DoomiApiResult.fail(-10, `缺失${dataKey}对应的查询语句`);
1991
+
1992
+ ////直接操作数据库之前,可由子类再次Handler
1993
+ let beforeData = await this.beforeAccessDB(req, listinfo.sql, listinfo.params, "list", this);
1994
+ ////如果返回Null,则表示不加载数据了
1995
+ if (beforeData.canceled === true) return DoomiApiResult.fail(1, '操作取消');
1996
+ ////操作数据库
1997
+ let result = await this._daoModel.loadData(beforeData.sql, beforeData.sqlParams);
1998
+ if(!result.successed) {
1999
+ ////失败也需要记录
2000
+ if (req.query.exportexcel==='true') this.logUserAction(req,this._daoModel.getBusiness(),5,-1);
2001
+ return result;
2002
+ }
2003
+ ///从数据库中获取到了原始数据
2004
+ if (result.rows) {
2005
+ ///将从数据库中获得的结果集根据dataconfig中的配置进行映射转换
2006
+ let resultItem = Data2View(result.rows[0], listinfo.fields);
2007
+ const extra = { page: listinfo.page, rows: resultItem.data };
2008
+ ///需要进行尾部统计的列表
2009
+ if (listinfo.hascounter) {
2010
+ let footerItem = Data2View(result.rows[2], listinfo.footers);
2011
+ extra.footer = footerItem.data;
2012
+ }
2013
+ extra.total = await this.getListRecordCount(result);
2014
+ ///处理导出Excel
2015
+ if (req.query.exportexcel==='true') {
2016
+ const excelResult = await this.export2Excel(extra.rows, req.query.excelkey || dataKey);
2017
+ this.logUserAction(req, this._daoModel.getBusiness(), 5, 0);
2018
+ return excelResult;
2019
+ }
2020
+ return DoomiApiResult.ok(extra);
2021
+ }
2022
+ return DoomiApiResult.fail(-1, '未获取到数据', { total: 0, rows: [] });
2023
+ }
2024
+ /**
2025
+ * 返回数据结果的记录总数
2026
+ * @param {*} data
2027
+ */
2028
+ async getListRecordCount(result){
2029
+ if (result.rows && result.rows.length == 2 && result.rows[1].length) return result.rows[1][0].total;
2030
+ return 0;
2031
+ }
2032
+ /*
2033
+ * 获取详细记录的方法
2034
+ */
2035
+ async getDataById(req, dataKey, sqlCommand,idValue) {
2036
+ if (this.logger) this.logger.trace("准备获取dataconfig文件中对应的 %s 详细数据",dataKey);
2037
+ const detailinfo = getDetailInfo(req, dataKey);
2038
+ if (!detailinfo) return DoomiApiResult.fail(-10, `缺失${dataKey}对应的详情配置`);
2039
+ const beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.getByIdSql(), idValue ||req.params.id, "detail", this);
2040
+ ////如果返回Null,则表示不加载数据了
2041
+ if (beforeData.canceled===true) return DoomiApiResult.fail(1, '操作已取消');
2042
+ /////处理SQL中的一些定义符
2043
+ const parseSql = parseTagInSql(req,beforeData.sql);
2044
+ ////操作数据库
2045
+ const result = await this._daoModel.getBykey(parseSql, beforeData.sqlParams);
2046
+ if (!result.successed) return result;
2047
+ if (result.rows && result.rows.length == 1) {
2048
+ ///如果对象有数据权限控制,则需要插入
2049
+ ///提交的权限设置
2050
+ ///将从数据库中获得的结果集根据dataconfig中的配置进行映射转换
2051
+ const resultMapping = Data2View(result.rows, detailinfo.fields);
2052
+ ///如果业务对象具备权限控制的业务,则需要将该数据的所赋予的权限对象加载出来
2053
+ if (this._daoModel.hasPermissionControl) {
2054
+ const accessResult = await this._daoModel.getDataPermissionSetting(req.params.id,this.PermissonBusiness(req));
2055
+ if (accessResult.successed) {
2056
+ resultMapping.data[0].managepermission = accessResult.managepermission;
2057
+ resultMapping.data[0].consumepermission = accessResult.consumepermission;
2058
+ }
2059
+ }
2060
+ return DoomiApiResult.ok({ rows: resultMapping.data[0], id: req.params.id });
2061
+ }
2062
+ return apiResult.DB_NO_RECORD_FOUND;
2063
+ }
2064
+ /**
2065
+ * 安全转换JSON字符串
2066
+ * @param {*} jsonStr
2067
+ * @returns
2068
+ */
2069
+ safeParseJson(jsonStr,defaultValue=null){
2070
+ if (!jsonStr) return defaultValue;
2071
+ try{
2072
+ return JSON.parse(jsonStr);
2073
+ }catch(e){
2074
+ return defaultValue;
2075
+ }
2076
+ }
2077
+ /*
2078
+ * 新增实体记录的方法
2079
+ */
2080
+ async create(req, dataKey, sqlCommand) {
2081
+ if (this.logger) this.logger.trace("准备根据dataconfig文件中对应的 %s 配置插入数据",dataKey);
2082
+ let mapping = req.query.Mapping??true; //|| 'true'==='true' ;//commonHelper.ifNull(req.query.Mapping, true);
2083
+ let detailinfo, resultItem = { successed: true, data: req.body };
2084
+ ///是否需要将data中的key-value值到配置文件中进行转换
2085
+ if (String(mapping) === String(true)) {
2086
+ detailinfo = getDetailInfo(req, dataKey);
2087
+ if (!detailinfo) return DoomiApiResult.fail(-10, `缺失${dataKey}对应的详情配置`);
2088
+ resultItem = View2Data(req, detailinfo.fields, "create");
2089
+ ///如果转换的验证过程中出现错误,则返回
2090
+ if (!resultItem.successed) return resultItem;
2091
+ }
2092
+ let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.insertSql(), resultItem.data, "create", this);
2093
+ ////如果返回Null,则表示不加载数据了
2094
+ if (beforeData.canceled) return DoomiApiResult.fail(1, '操作取消');
2095
+ if (this.logger) this.logger.trace("插入数据准备 : ",beforeData);
2096
+ let result = await this._daoModel.create(beforeData.sql, beforeData.sqlParams, req);
2097
+ if(!result.successed) {
2098
+ this.logUserAction(req,this._daoModel.getBusiness(),1,-1);
2099
+ return result;
2100
+ }
2101
+ let primaryKey;
2102
+ if (mapping && detailinfo.primary) {
2103
+ ///自动增长的主键字段
2104
+ if (detailinfo.autoincrease === true) primaryKey = result.rows.insertId;
2105
+ else {
2106
+ if (typeof (detailinfo.primary) === "string") primaryKey = beforeData.sqlParams[detailinfo.primary];
2107
+ if (typeof (detailinfo.primary) === "object")
2108
+ primaryKey = detailinfo.primary.map(element => { return beforeData.sqlParams[element]; });
2109
+ }
2110
+ }
2111
+ ///如果对象有数据权限控制,则需要插入
2112
+ ///提交的权限设置
2113
+ if (this._daoModel.hasPermissionControl){
2114
+ const param = {
2115
+ managepermission:this.safeParseJson(req.body.managepermission) || {},
2116
+ consumepermission: this.safeParseJson(req.body.consumepermission) || {}
2117
+ };
2118
+ this._daoModel.saveDataPermissionSetting(primaryKey, param);
2119
+ }
2120
+ this.logUserAction(req,this._daoModel.getBusiness(),1,0);
2121
+ return DoomiApiResult.ok({ data: resultItem.data, id: primaryKey });
2122
+ }
2123
+ /*
2124
+ * 修改实体记录的方法
2125
+ */
2126
+ async update(req, dataKey, sqlCommand, id) {
2127
+ if (this.logger) this.logger.trace("准备根据dataconfig文件中对应的 %s 配置修改数据",dataKey);
2128
+ if (id == null) id = req.params.id;
2129
+ let mapping = req.query.Mapping??true;// commonHelper.ifNull(req.query.Mapping, true);
2130
+ let detailinfo, resultItem = { successed: true, data: req.body };
2131
+ ///是否需要将data中的key-value值到配置文件中进行转换
2132
+ if (String(mapping) === String(true)) {
2133
+ detailinfo = getDetailInfo(req, dataKey);
2134
+ if (!detailinfo) return DoomiApiResult.fail(-10, `缺失${dataKey}对应的详情配置`);
2135
+ ///从Request中获取到用户提交的数据
2136
+ resultItem = View2Data(req, detailinfo.fields, "update");
2137
+ }
2138
+ ///如果不需要转换,则直接使用前端提交上来的值
2139
+ let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.updateSql(), resultItem.data, "update", this);
2140
+ ////如果返回Null,则表示不加载数据了
2141
+ if (beforeData.canceled) return DoomiApiResult.fail(1, '操作取消');
2142
+ if (this.logger) this.logger.trace("修改数据准备 : ",beforeData);
2143
+ /////处理SQL中的一些定义符
2144
+ let parseSql = parseTagInSql(req,beforeData.sql);
2145
+ let result = await this._daoModel.update(parseSql, beforeData.sqlParams, id);
2146
+ if(!result.successed) {
2147
+ this.logUserAction(req,this._daoModel.getBusiness(),3,-1);
2148
+ return result;
2149
+ }
2150
+ ///更新成功
2151
+ if (result.rows.affectedRows >= 1) {
2152
+ ///如果对象有数据权限控制,则需要插入
2153
+ ///提交的权限设置
2154
+ if (this._daoModel.hasPermissionControl) {
2155
+ const param = {
2156
+ managepermission:this.safeParseJson(req.body.managepermission) || {},
2157
+ consumepermission:this.safeParseJson(req.body.consumepermission) || {}
2158
+ };
2159
+ this._daoModel.saveDataPermissionSetting(id, param);
2160
+ }
2161
+ this.logUserAction(req,this._daoModel.getBusiness(),3,0);
2162
+ return DoomiApiResult.ok({ data: resultItem.data, id: id });
2163
+ }
2164
+ ///更新失败
2165
+ return apiResult.DB_NO_EFFECTIVE; //{successed:false,errorcode:errorcode.DATABASE_ERROR.NO_RECORD_EFFECTED,data:resultItem.data};
2166
+ }
2167
+
2168
+ /*
2169
+ * 删除实体记录的方法
2170
+ */
2171
+ async delete(req, id, sqlCommand) {
2172
+ if (this.logger) this.logger.trace("准备删除数据",id);
2173
+ let beforeData = await this.beforeAccessDB(req, sqlCommand || this._daoModel.deleteSql(id), id, "delete", this);
2174
+ ////如果返回Null,则表示不加载数据了
2175
+ if (beforeData.canceled) return DoomiApiResult.fail(1, '操作取消');
2176
+ /////处理SQL中的一些定义符
2177
+ let parseSql = parseTagInSql(req,beforeData.sql);
2178
+ ////操作数据库
2179
+ let result = await this._daoModel.delete(parseSql, beforeData.sqlParams,req.user?.id);
2180
+ if(!result.successed) {
2181
+ this.logUserAction(req,this._daoModel.getBusiness(),2,-1);
2182
+ return result;
2183
+ }
2184
+ this.logUserAction(req,this._daoModel.getBusiness(),2,0);
2185
+ return DoomiApiResult.ok({ id: id, count: result.rows.affectedRows });
2186
+ }
2187
+ }
2188
+ module.exports = controller;
2189
+ } (controller, controller.exports));
2190
+ return controller.exports;
2191
+ }
2192
+
2193
+ var tokenutility = {exports: {}};
2194
+
2195
+ /**
2196
+ * 后台路由授权访问的Token验证
2197
+ */
2198
+ tokenutility.exports;
2199
+
2200
+ var hasRequiredTokenutility;
2201
+
2202
+ function requireTokenutility () {
2203
+ if (hasRequiredTokenutility) return tokenutility.exports;
2204
+ hasRequiredTokenutility = 1;
2205
+ (function (module, exports) {
2206
+ // const cache = require('doomi-helper').redisHelper.getInstance();
2207
+ class TokenUtility {
2208
+ constructor(cacheinstance){
2209
+ this.cache = cacheinstance;
2210
+ }
2211
+ setToken(token, tokenObject, expire) {
2212
+ // if (typeof tokenObject != "string") tokenObject = JSON.stringify(tokenObject);
2213
+ return this.cache.set(token, tokenObject, expire);
2214
+ }
2215
+ ///从缓存中获取用户
2216
+ async getToken(token,isObject=true) {
2217
+ let value = await this.cache.get(token);
2218
+ if (!value) return value;
2219
+ return isObject ? JSON.parse(value) : value;
2220
+ }
2221
+ /**
2222
+ * token是否有效
2223
+ * @param {*} token
2224
+ */
2225
+ async tokenIsValid(token){
2226
+ return (await this.getToken(token,false))!=null
2227
+ }
2228
+ /**
2229
+ * 删除Token
2230
+ * @param {*} token
2231
+ */
2232
+ deleteToken(token){
2233
+ this.cache.delete(token);
2234
+ }
2235
+ /**
2236
+ * 延长token的有效期
2237
+ * @param {*} token
2238
+ * @param {*} tokenObject
2239
+ * @param {*} expire
2240
+ */
2241
+ extendToken(token,expire) {
2242
+ return this.cache.expire(token,expire);
2243
+ }
2244
+ }
2245
+ module.exports.TokenHelper = (cacheinstance)=>{
2246
+ return new TokenUtility(cacheinstance)
2247
+ };
2248
+ } (tokenutility, tokenutility.exports));
2249
+ return tokenutility.exports;
2250
+ }
2251
+
2252
+ framework.exports;
2253
+
2254
+ var hasRequiredFramework;
2255
+
2256
+ function requireFramework () {
2257
+ if (hasRequiredFramework) return framework.exports;
2258
+ hasRequiredFramework = 1;
2259
+ (function (module, exports) {
2260
+ module.exports = {
2261
+ doomiwork:requireDoomiwork(),
2262
+ controller: requireController(),
2263
+ model: requireDaoBase(),
2264
+ appsetting:requireAppsetting(),
2265
+ actionresult:requireActionresult(),
2266
+ excelutility:requireExcelutility(),
2267
+ tokenHelper:requireTokenutility(),
2268
+ constants:requireEnumconst(),
2269
+ FuncResult: requireDoomiapiresult(),
2270
+ };
2271
+ } (framework, framework.exports));
2272
+ return framework.exports;
2273
+ }
2274
+
2275
+ var frameworkExports = requireFramework();
2276
+ var index = /*@__PURE__*/getDefaultExportFromCjs(frameworkExports);
2277
+
2278
+ module.exports = index;
2279
+ //# sourceMappingURL=index.js.map