Browse Source

假勤数据展开

master
巴林闲侠 2 years ago
parent
commit
6c0d883862
  1. 5
      api/.vscode/launch.json
  2. 1
      api/app/lib/controllers/member/index.js
  3. 34
      api/app/lib/models/holiday.js
  4. 142
      api/app/lib/models/overtime.js
  5. 88
      api/app/lib/models/vacate.js
  6. 429
      api/app/lib/schedule/attendance.js
  7. 59
      api/app/lib/schedule/timor_holiday.js
  8. 65
      api/app/lib/utils/days.js
  9. 22
      api/config.js
  10. 2
      api/sequelize-automate.config.js

5
api/.vscode/launch.json

@ -38,12 +38,9 @@
// "--clickHouseUser ",
// "--clickHousePassword ",
//
// "--clickHousePepEmis pepca",
//
"--clickHousePepEmis pepca8",
"--clickHouseCamworkflow camworkflow",
]
},
{

1
api/app/lib/controllers/member/index.js

@ -97,6 +97,7 @@ async function searchPepMember (ctx) {
})
}
})
ctx.status = 200;
ctx.body = returnD
} catch (error) {

34
api/app/lib/models/holiday.js

@ -0,0 +1,34 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Holiday = sequelize.define("holiday", {
day: {
type: DataTypes.DATEONLY,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "day",
autoIncrement: false,
unique: "holiday_day_uindex"
},
holiday: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "holiday",
autoIncrement: false
}
}, {
tableName: "holiday",
comment: "",
indexes: []
});
dc.models.Holiday = Holiday;
return Holiday;
};

142
api/app/lib/models/overtime.js

@ -0,0 +1,142 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Overtime = sequelize.define("overtime", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "overtime_id_uindex"
},
pepUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "pep_user_id",
autoIncrement: false
},
startTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "start_time",
autoIncrement: false
},
endTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "end_time",
autoIncrement: false
},
duration: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "duration",
autoIncrement: false
},
pepProcessStoryId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "pep_process_story_id",
autoIncrement: false
},
wfProcessState: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "wf_process_state",
autoIncrement: false
},
takeRestWorkday: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "工作日调休",
primaryKey: false,
field: "take_rest_workday",
autoIncrement: false
},
takeRestDayoff: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "普假调休",
primaryKey: false,
field: "take_rest_dayoff",
autoIncrement: false
},
takeRestFestivals: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "节假日调休",
primaryKey: false,
field: "take_rest_festivals",
autoIncrement: false
},
payWorkday: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "工作日补偿",
primaryKey: false,
field: "pay_workday",
autoIncrement: false
},
payDayoff: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "普假补偿",
primaryKey: false,
field: "pay_dayoff",
autoIncrement: false
},
payFestivals: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: "0",
comment: "节假日补偿",
primaryKey: false,
field: "pay_festivals",
autoIncrement: false
},
compensate: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "补偿方式",
primaryKey: false,
field: "compensate",
autoIncrement: false
}
}, {
tableName: "overtime",
comment: "",
indexes: []
});
dc.models.Overtime = Overtime;
return Overtime;
};

88
api/app/lib/models/vacate.js

@ -0,0 +1,88 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Vacate = sequelize.define("vacate", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "vacate_id_uindex"
},
pepUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "pep_user_id",
autoIncrement: false
},
startTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "start_time",
autoIncrement: false
},
endTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "end_time",
autoIncrement: false
},
type: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "请假类别",
primaryKey: false,
field: "type",
autoIncrement: false
},
duration: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "时长 s",
primaryKey: false,
field: "duration",
autoIncrement: false
},
pepProcessStoryId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "和 项企 workflow_process_history 关联",
primaryKey: false,
field: "pep_process_story_id",
autoIncrement: false
},
wfProcessState: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "流程状态",
primaryKey: false,
field: "wf_process_state",
autoIncrement: false
}
}, {
tableName: "vacate",
comment: "",
indexes: []
});
dc.models.Vacate = Vacate;
return Vacate;
};

429
api/app/lib/schedule/attendance.js

@ -0,0 +1,429 @@
const schedule = require('node-schedule');
const moment = require('moment')
module.exports = function (app, opts) {
const updateAttendance = app.fs.scheduleInit(
// 妥妥流水账 (*^▽^*)
{
interval: '34 21 4 * * *',
// interval: '*/3 * * * *',
immediate: true,
// proRun: true,
},
async () => {
console.info('假勤数据更新 ', moment().format('YYYY-MM-DD HH:mm:ss'));
const { workFlow: { processState } } = opts
try {
const startTime = moment()
const { models } = app.fs.dc
const { judgeHoliday } = app.fs.utils
const { clickHouse } = app.fs
const { database: camWorkflow } = clickHouse.camWorkflow.opts.config
const { } = app.fs.utils
let overtimeNeedData = {
begainTime: {
keyWord: ['加班开始时间'],
require: true,
},
endTime: {
keyWord: ['加班结束时间'],
require: true,
},
duration: {
keyWord: ['总时长(小时)']
},
compensate: {
keyWord: ['加班补偿'],
require: true,
},
hrAffirmDuration: {
keyWord: ['人事核定加班小时', '核定加班小时'],
require: true,
},
}
let vacateNeedData = {
begainTime: {
keyWord: ['请假开始时间', '请假起始时间'],
keys: ['leaveStartTime'],
require: true,
},
endTime: {
keyWord: ['请假结束时间', '请假终止时间'],
keys: ['leaveEndTime'],
require: true,
},
type: {
keyWord: ['请假类别', '请假类型'],
keys: ['leaveType'],
require: true,
},
hrAffirmType: {
keyWord: ['核定请假类别'],
},
duration: {
keyWord: ['请假时长(小时)', '请假小时'],
keys: ['leaveTime']
},
hrAffirmDuration: {
keyWord: ['核定请假小时'],
},
}
const schemaRecursionObj = ({
jsonSchema, keyWord, targetKeys = [], schemaPath, require
}) => {
let schemaPath_ = JSON.parse(JSON.stringify(schemaPath))
if (jsonSchema.properties) {
for (let prKey in jsonSchema.properties) {
if (
keyWord.includes(jsonSchema.properties[prKey].title)
|| targetKeys.includes(prKey)
) {
schemaPath_.push({
prKey,
...jsonSchema.properties[prKey]
})
return schemaPath_
} else if (jsonSchema.properties[prKey].properties) {
schemaPath_.push({
prKey,
...jsonSchema.properties[prKey]
})
schemaPath_ = schemaRecursionObj({
jsonSchema: jsonSchema.properties[prKey],
keyWord,
targetKeys,
schemaPath: schemaPath_,
require,
})
if (!schemaPath_.length && require) {
console.warn('数据字段查找错误:', jsonSchema.properties);
}
if (schemaPath_.length > schemaPath.length) {
return schemaPath_
}
}
}
} else {
return schemaPath_
}
}
const dataRecursionObj = (dataObj, index, needData, lastKeyObj, nd) => {
const keyObj = needData[nd].schemaPath[index]
if (dataObj.hasOwnProperty(keyObj.prKey)) {
if (lastKeyObj.prKey == keyObj.prKey) {
let gotValue = dataObj[keyObj.prKey]
if (keyObj.enum) {
let vIndex = keyObj.enum.findIndex(ke => ke == gotValue)
gotValue = keyObj.enumNames[vIndex]
}
return gotValue
} else {
return dataRecursionObj(
dataObj[keyObj.prKey],
index + 1,
needData,
lastKeyObj,
nd
)
}
}
}
const getData = (applyDetail, needData) => {
for (let nd in needData) {
if (needData[nd].noProcess) {
continue
}
if (applyDetail.formSchema) {
const { jsonSchema } = JSON.parse(applyDetail.formSchema)
needData[nd].schemaPath = schemaRecursionObj({
jsonSchema: jsonSchema || {},
keyWord: needData[nd]['keyWord'],
targetKeys: needData[nd]['keys'],
schemaPath: [],
require: nd.require
})
if (
needData[nd].schemaPath
&& needData[nd].schemaPath.length
) {
const lastKeyObj = needData[nd]
.schemaPath[needData[nd].schemaPath.length - 1]
if (applyDetail.formData) {
const formData = JSON.parse(applyDetail.formData)
needData[nd].value = dataRecursionObj(
formData, 0, needData, lastKeyObj, nd
)
} else {
console.warn(
`表单数据缺失:`,
applyDetail
);
}
} else {
if (needData[nd].require) {
// 记录错误 关键数据没找到
console.warn(
`数据字段查找错误:${nd.needData[nd]['keyWord'].join('、')}`,
jsonSchema
);
}
}
}
}
}
const attendanceRes = await clickHouse.pepEmis.query(
`
SELECT
story.id AS historyId,
story.apply_user AS pepUserId,
story.form_data AS formData,
story.submit_form_data AS submitFormData,
fform.form_schema AS formSchema,
fprocess.name AS processName,
procin.state_ AS state,
fform.id AS formId
`
+
`,fversion.id AS versionId` +
`,fgroup.name AS groupName` +
`
FROM
workflow_process_history AS story
INNER JOIN workflow_process_version AS fversion
ON fversion.id = story.version_id
INNER JOIN workflow_process_form AS fform
ON fform.id = fversion.form_id
INNER JOIN workflow_process AS fprocess
ON fprocess.id = fform.process_id
INNER JOIN workflow_group AS fgroup
ON fgroup.id = fprocess.group_id
AND fgroup.name = '假勤管理'
INNER JOIN ${camWorkflow}.act_hi_procinst AS procin
ON procin.id_ = story.procinst_id
`
).toPromise()
let insertCount = 0, updateCount = 0, invalidCount = 0, unCompletedCount = 0, unknowCount = 0
for (let a of attendanceRes) {
console.log(`处理 ${a.pepUserId}·s ${a.processName}(form:${a.formId} story:${a.historyId}`);
if (a.processName) {
if ('COMPLETED' == a.state) {
if (a.processName.indexOf('请假') > -1) {
let needData = JSON.parse(JSON.stringify(vacateNeedData))
getData(a, needData)
const { begainTime, endTime, type, hrAffirmType, duration, hrAffirmDuration } = needData
if (begainTime.value && endTime.value && type.value) {
let durationSec = 0
if (hrAffirmDuration.value) {
durationSec = parseFloat(hrAffirmDuration.value) * 3600
} else if (duration.value) {
durationSec = parseFloat(duration.value) * 3600
} else {
durationSec = moment(endTime.value).diff(moment(begainTime.value), 'second')
}
if (typeof durationSec != 'number' || isNaN(durationSec) || durationSec <= 0) {
console.warn('请假时长计算结果错误', hrAffirmDuration, duration);
invalidCount++
} else {
let typeStorage = ''
if (hrAffirmType.value) {
typeStorage = hrAffirmType.value
} else {
typeStorage = type.value
}
const existRes = await models.Vacate.findOne({
where: {
pepProcessStoryId: a.historyId
}
})
let storageD = {
pepUserId: a.pepUserId,
pepProcessStoryId: a.historyId,
startTime: moment(begainTime.value).format('YYYY-MM-DD HH:mm:ss'),
endTime: moment(endTime.value).format('YYYY-MM-DD HH:mm:ss'),
duration: durationSec,
type: typeStorage,
wfProcessState: a.state,
}
if (existRes) {
await models.Vacate.update(storageD, {
where: {
id: existRes.id
}
})
updateCount++
} else {
await models.Vacate.create(storageD)
insertCount++
}
}
} else {
console.warn('必填 value 缺失:', needData,);
console.warn('流程数据:', a);
invalidCount++
}
} else if (a.processName.indexOf('加班') > -1) {
// 深拷贝所需查询数据
let needData = JSON.parse(JSON.stringify(overtimeNeedData))
// 获取表单里的数据并插入 needData
getData(a, needData)
const { begainTime, endTime, duration, compensate, hrAffirmDuration } = needData
if (begainTime.value && endTime.value && hrAffirmDuration.value && compensate.value) {
let durationSec = parseFloat(hrAffirmDuration.value) * 3600
if (typeof durationSec != 'number' || isNaN(durationSec || durationSec <= 0)) {
console.warn('加班时长计算结果错误', duration);
invalidCount++
} else {
// 开始时间
let begainTime_ = moment(begainTime.value)
// 加上人事确定的时间的结束时间
let endTimeWithHrAffirm = begainTime_.clone().add(durationSec, 'seconds')
// 定义需要统计的各类变量
let takeRestWorkday = 0,
takeRestDayoff = 0,
takeRestFestivals = 0,
payWorkday = 0,
payDayoff = 0,
payFestivals = 0
// 判断 结束时间在加班当天的时间节点后 也就是说跨天加班了
if (endTimeWithHrAffirm.isSameOrAfter(begainTime_)) {
let packageSuccess = true
// 考虑加了好多天的流程
let curday = begainTime_.clone()
while (curday.isSameOrBefore(endTimeWithHrAffirm)) {
let duration_ = 0
if (curday.isSame(endTimeWithHrAffirm, 'day')) {
// 是同一天
duration_ = endTimeWithHrAffirm.diff(curday, 'seconds')
} else if (curday.isSame(begainTime_, 'day')) {
// 和开始日期是同一天
// 同时也说明和结束日期不是同一天
duration_ = begainTime_.clone()
.endOf('day')
.diff(begainTime_, 'seconds') + 1
} else {
// 跨了好几天
// 不但 curday 加 后一天也加
duration_ = 24 * 3600
}
const holidayRes = await judgeHoliday(curday.format('YYYY-MM-DD'))
if (holidayRes) {
if (compensate.value && compensate.value.indexOf('调休') >= 0) {
if (holidayRes.workday) {
takeRestWorkday += duration_
} else if (holidayRes.dayoff) {
takeRestDayoff += duration_
} else if (holidayRes.festivals) {
takeRestFestivals += duration_
} else {
let a = 4
}
} else if (compensate.value && compensate.value.indexOf('补偿') >= 0) {
if (holidayRes.workday) {
payWorkday += duration_
} else if (holidayRes.dayoff) {
payDayoff += duration_
} else if (holidayRes.festivals) {
payFestivals += duration_
}
} else {
console.warn(`加班补偿字段未知:`, compensate.value);
invalidCount++
packageSuccess = false
break
}
} else {
console.warn(`节假日信息获取失败`, curday.format('YYYY-MM-DD'));
invalidCount++
packageSuccess = false
break
}
curday = curday.add(1, 'day').startOf('day')
}
if (packageSuccess) {
const existRes = await models.Overtime.findOne({
where: {
pepProcessStoryId: a.historyId
}
})
let storageD = {
pepUserId: a.pepUserId,
pepProcessStoryId: a.historyId,
startTime: moment(begainTime.value).format('YYYY-MM-DD HH:mm:ss'),
endTime: moment(endTime.value).format('YYYY-MM-DD HH:mm:ss'),
duration: durationSec,
wfProcessState: a.state,
takeRestWorkday,
takeRestDayoff,
takeRestFestivals,
payWorkday,
payDayoff,
payFestivals,
compensate: compensate.value
}
if (existRes) {
await models.Overtime.update(storageD, {
where: {
id: existRes.id
}
})
updateCount++
} else {
await models.Overtime.create(storageD)
insertCount++
}
}
} else {
console.warn(`结束时间在开始时间之前(unbelievable)`, '开始' + begainTime.value, '结束' + endTime.value, '人事确认结束' + endTimeWithHrAffirm.format());
invalidCount++
}
}
} else {
console.warn('必填 value 缺失:', needData,);
console.warn('流程数据:', a);
invalidCount++
}
} else {
console.warn('假勤分组内不明流程');
unknowCount++
}
} else {
unCompletedCount++
}
} else {
invalidCount++
}
}
console.info(`
假勤数据更新 用时 ${moment().diff(startTime, 'seconds')} s
`)
console.info(`
${attendanceRes.length};
新增${insertCount};
更新数据${updateCount};
非完成状态流程${unCompletedCount};
不明流程${unknowCount}
无效(warning)${invalidCount};
`);
} catch (error) {
app.fs.logger.error(`sechedule: updateAttendance, error: ${error}`);
}
});
return {
updateAttendance,
}
}

59
api/app/lib/schedule/timor_holiday.js

@ -0,0 +1,59 @@
'use strict';
const moment = require('moment');
const request = require('superagent');
module.exports = function (app, opts) {
const timorHoliday = app.fs.scheduleInit(
{
interval: '54 42 4 */7 * * *',
// immediate: true,
proRun: true,
},
async () => {
const { timorApiUrl } = opts
const { models } = app.fs.dc
const existCount = await models.Holiday.count()
let begainDay = existCount ? moment() : moment('2022-01-01')
let endDay = moment().add(3, 'months').endOf('month')
let checkDay = begainDay.clone()
while (checkDay.isSameOrBefore(endDay)) {
try {
const checkDayStr = checkDay.format('YYYY-MM-DD')
let holidayRes = await request.get(
timorApiUrl + `holiday/info/${checkDayStr}`,
)
let holidayData = holidayRes.body || {}
if (holidayData.code == 0) {
const dbRes = await models.Holiday.findOne({
where: {
day: checkDayStr
}
})
if (dbRes) {
await models.Holiday.update({ holiady: holidayData }, {
where: {
day: checkDayStr
}
})
} else {
await models.Holiday.create({
day: checkDayStr,
holiady: holidayData
})
}
}
checkDay = checkDay.add(1, 'day')
} catch (error) {
console.error(error);
// TODO 发邮件
}
}
}
)
return {
timorHoliday
}
}

65
api/app/lib/utils/days.js

@ -0,0 +1,65 @@
'use strict';
const moment = require('moment')
const request = require('superagent');
module.exports = function (app, opts) {
async function judgeHoliday (dayStr) {
const { timorApiUrl } = opts
const { models } = app.fs.dc
let dayStr_ = dayStr || moment().format('YYYY-MM-DD')
let holidayData = null
const dbRes = await models.Holiday.findOne({
where: {
day: dayStr_
}
})
if (dbRes) {
holidayData = dbRes.dataValues.holiday
} else {
let holidayRes = await request.get(
timorApiUrl + `holiday/info/${dayStr_}`
)
holidayData = holidayRes.body || {}
}
if (holidayData && holidayData.code == 0) {
let returnD = {
workday: false,
dayoff: false,
festivals: false,
params: holidayData.type
}
let holidayType = holidayData.type.type
if (
holidayType == 2
&& holidayData.holiday
&& holidayData.holiday.wage == 3
) {
// 正经节假日 3倍工资那种
// festivals
returnD.festivals = true
} else if (
holidayType == 1
|| (
holidayType == 2
&& holidayData.holiday
&& holidayData.holiday.wage < 3
)
) {
// 普假 休息日非节假日
returnD.dayoff = true
} else if (holidayType == 0 || holidayType == 3) {
// 工作日或补班
returnD.workday = true
}
return returnD
} else {
return false
}
}
return {
judgeHoliday
}
}

22
api/config.js

@ -28,6 +28,7 @@ args.option('qndmn', 'qiniuDomain');
args.option('clickHouseUrl', 'clickHouse Url');
args.option('clickHousePort', 'clickHouse Port');
args.option('clickHousePepEmis', 'clickHouse 项企数据库名称');
args.option('clickHouseCamworkflow', 'clickHouse 工作流数据库名称');
const flags = args.parse(process.argv);
@ -54,6 +55,10 @@ const CLICKHOUST_PORT = process.env.CLICKHOUST_PORT || flags.clickHousePort
const CLICKHOUST_USER = process.env.CLICKHOUST_USER || flags.clickHouseUser
const CLICKHOUST_PASSWORD = process.env.CLICKHOUST_PASSWORD || flags.clickHousePassword
const CLICKHOUST_PEP_EMIS = process.env.CLICKHOUST_PEP_EMIS || flags.clickHousePepEmis
const CLICKHOUST_CAM_WORKFLOW = process.env.CLICKHOUST_CAM_WORKFLOW || flags.clickHouseCamworkflow
// timor 节假日查询
const API_TIMOR_URL = 'http://timor.tech/api/'
if (
!POMS_DB
@ -61,7 +66,7 @@ if (
|| !API_EMIS_URL
|| !QINIU_DOMAIN_QNDMN_RESOURCE || !QINIU_BUCKET_RESOURCE || !QINIU_AK || !QINIU_SK
|| !CLICKHOUST_URL || !CLICKHOUST_PORT
|| !CLICKHOUST_PEP_EMIS
|| !CLICKHOUST_PEP_EMIS || !CLICKHOUST_CAM_WORKFLOW
) {
console.log('缺少启动参数,异常退出');
args.showHelp();
@ -90,6 +95,16 @@ const product = {
exclude: [
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
workFlow: {
processState: [
'WAIT', //保存待发
'ACTIVE', // 正在运行中
'SUSPENDED', // 流程暂停
'COMPLETED', //流程正常结束
'EXTERNALLY_TERMINATED', // 手动结束流程
'INTERNALLY_TERMINATED' //流程异常结束
]
},
redis: {
host: IOTA_REDIS_SERVER_HOST,
port: IOTA_REDIS_SERVER_PORT,
@ -110,6 +125,7 @@ const product = {
password: 'Fs2689'
}
},
timorApiUrl: API_TIMOR_URL,
pssaRequest: [{
name: 'emisRequest',
root: API_EMIS_URL
@ -123,6 +139,10 @@ const product = {
{
name: 'pepEmis',
db: CLICKHOUST_PEP_EMIS
},
{
name: 'camWorkflow',
db: CLICKHOUST_CAM_WORKFLOW
}
]
}

2
api/sequelize-automate.config.js

@ -26,7 +26,7 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['member'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
tables: ['overtime'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

Loading…
Cancel
Save