zmh
1 year ago
12 changed files with 594 additions and 7 deletions
@ -0,0 +1,19 @@ |
|||
{ |
|||
// 使用 IntelliSense 了解相关属性。 |
|||
// 悬停以查看现有属性的描述。 |
|||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 |
|||
"version": "0.2.0", |
|||
"configurations": [ |
|||
{ |
|||
"type": "node", |
|||
"request": "launch", |
|||
"name": "启动程序", |
|||
"program": "${workspaceFolder}\\index.js", |
|||
"env": { |
|||
"NODE_ENV": "development", |
|||
"FS_ENV": "false", |
|||
"FS_ENV_TEST":"false" |
|||
} |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,12 @@ |
|||
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2 |
|||
|
|||
MAINTAINER liuxinyi "liu.xinyi@free-sun.com.cn" |
|||
|
|||
COPY . /app |
|||
|
|||
WORKDIR /app |
|||
|
|||
RUN npm cache clean -f && npm install --production --force --registry http://10.8.30.22:7000 |
|||
|
|||
|
|||
CMD [ "node", "index.js" ] |
@ -0,0 +1,24 @@ |
|||
const ENV_SY_POOL = { //商用数据库配置
|
|||
user: 'FashionAdmin', |
|||
host: '10.8.40.210', |
|||
database: 'HRM', |
|||
password: '123456', |
|||
port: 5432 |
|||
} |
|||
const ENV_CS_POOL = { //生产环境数据库配置
|
|||
user: 'postgres', |
|||
host: '10.8.30.166', |
|||
database: 'HRM', |
|||
password: '123', |
|||
port: 5432 |
|||
} |
|||
const PRO_POOL = { //研发自测用
|
|||
user: 'postgres', |
|||
host: '10.8.30.166', |
|||
database: 'hr-dev', |
|||
password: '123', |
|||
port: 5432 |
|||
} |
|||
module.exports = { |
|||
ENV_SY_POOL, ENV_CS_POOL, PRO_POOL |
|||
} |
@ -0,0 +1,434 @@ |
|||
try { |
|||
const { Pool, Client } = require('pg') |
|||
const Hex = require('crypto-js/enc-hex'); |
|||
const MD5 = require('crypto-js/md5'); |
|||
const request = require('superagent'); |
|||
const fs = require("fs"); |
|||
const args = require('args'); |
|||
const moment = require('moment'); |
|||
|
|||
const { ENV_SY_POOL, ENV_CS_POOL, PRO_POOL } = require('./config.js') |
|||
|
|||
args.option(['e', 'env'], '商用环境'); |
|||
args.option(['t', 'test'], '测试环境'); |
|||
args.option(['p', 'product'], '生产环境'); |
|||
const flags = args.parse(process.argv); |
|||
|
|||
console.log("process.env.FS_ENV:", process.env.FS_ENV); |
|||
console.log("process.env.FS_ENV_TEST:", process.env.FS_ENV_TEST); |
|||
console.log(" flags.env:", flags.env); |
|||
console.log("flags.test:", flags.test); |
|||
|
|||
const FS_ENV = process.env.FS_ENV || flags.env || false; |
|||
const FS_ENV_TEST = process.env.FS_ENV_TEST || flags.test || false; |
|||
|
|||
|
|||
let poolSetting = PRO_POOL; |
|||
let readAnswer = true; |
|||
|
|||
if (FS_ENV && 'true' == FS_ENV) {//商用
|
|||
poolSetting = ENV_SY_POOL; |
|||
console.log("poolSetting:FS_ENV"); |
|||
} else if (FS_ENV_TEST && 'true' == FS_ENV_TEST) {//测试
|
|||
poolSetting = ENV_CS_POOL; |
|||
console.log("poolSetting:FS_ENV_TEST"); |
|||
} else {//研发
|
|||
poolSetting = PRO_POOL; |
|||
//对权限初始变动时,readAnswer需设为false,其他数据库执行更新时设为true
|
|||
readAnswer = false; |
|||
console.log("poolSetting:PRO_POOL"); |
|||
} |
|||
const pool = new Pool(poolSetting); |
|||
const baiduInfo = { |
|||
appid: '20200917000567738', |
|||
key: 'xXm4jsuuD38JIkkhEcK6' |
|||
} |
|||
// 功能名称 alias翻译别名,show展示的名字,btn操作按钮,child子类,order排序
|
|||
let resource = [ |
|||
{ |
|||
show: '人员档案', |
|||
alias: '人员档案管理', |
|||
order: 1, |
|||
child: [{ |
|||
show: '人员档案', |
|||
child: [{ |
|||
btn: '新增档案', |
|||
alias: '新增档案' |
|||
}, { |
|||
btn: '导入员工信息' |
|||
}, { |
|||
btn: '导出', |
|||
alias: '导出员工档案' |
|||
}, { |
|||
btn: '编辑档案' |
|||
}, { |
|||
btn: '删除档案' |
|||
}] |
|||
}, { |
|||
show: '员工信息', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出员工信息' |
|||
}] |
|||
}, { |
|||
show: '岗位评级', |
|||
child: [{ |
|||
btn: '导入', |
|||
alias: '导入岗位评级' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '部门档案', |
|||
alias: '部门档案管理', |
|||
order: 2, |
|||
child: [{ |
|||
show: '部门档案' |
|||
}] |
|||
}, { |
|||
show: '假勤管理', |
|||
order: 3, |
|||
child: [{ |
|||
show: '出勤统计', |
|||
}, { |
|||
show: '请假统计', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出请假统计' |
|||
}] |
|||
}, { |
|||
show: '加班统计', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出加班统计' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '员工沟通', |
|||
order: 4, |
|||
child: [{ |
|||
show: '员工沟通统计', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出员工沟通统计' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '招聘记录', |
|||
order: 5, |
|||
child: [{ |
|||
show: '任用记录' |
|||
}] |
|||
}, { |
|||
show: '销售统计', |
|||
order: 6, |
|||
child: [{ |
|||
show: '销售人员分布', |
|||
child: [{ |
|||
btn: '新增', |
|||
alias: '新增销售人员' |
|||
}, { |
|||
btn: '导入', |
|||
alias: '导入销售人员分布' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '培训档案', |
|||
order: 7, |
|||
child: [{ |
|||
show: '培训资源储存库', |
|||
child: [{ |
|||
btn: '新增文件夹' |
|||
}, { |
|||
btn: '编辑文件夹' |
|||
}, { |
|||
btn: '删除文件夹' |
|||
}, { |
|||
btn: '新增子文件夹' |
|||
}, { |
|||
btn: '编辑子文件夹' |
|||
}, { |
|||
btn: '删除子文件夹' |
|||
}, { |
|||
btn: '上传文件' |
|||
}, { |
|||
btn: '下载', |
|||
alias: '下载培训资料' |
|||
}, { |
|||
btn: '删除', |
|||
alias: '删除培训资料' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '培训管理', |
|||
order: 8, |
|||
child: [{ |
|||
show: '个人培训记录', |
|||
child: [{ |
|||
btn: '导入', |
|||
alias: '导入个人培训记录' |
|||
}] |
|||
}, { |
|||
show: '部门培训记录', |
|||
child: [{ |
|||
btn: '导入', |
|||
alias: '导入部门培训记录' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '基本动作管理', |
|||
order: 9, |
|||
child: [{ |
|||
show: '周报管理', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出周报' |
|||
}] |
|||
}, { |
|||
show: '销售日志', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出销售日志' |
|||
}] |
|||
}, { |
|||
show: '工程日志', |
|||
child: [{ |
|||
btn: '导出', |
|||
alias: '导出工程日志' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '员工考核', |
|||
order: 10, |
|||
child: [{ |
|||
show: '试用期员工考核' |
|||
}, { |
|||
show: '正式员工考核', |
|||
child: [{ |
|||
btn: '下载', |
|||
alias: '下载正式员工考核' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '中层考核', |
|||
order: 11, |
|||
child: [{ |
|||
show: '月度过程考核', |
|||
alias: '中层月度过程考核', |
|||
child: [{ |
|||
btn: '下载', |
|||
alias: '下载中层月度过程考核' |
|||
}] |
|||
}, { |
|||
show: '季度考核', |
|||
alias: '中层季度考核', |
|||
child: [{ |
|||
btn: '下载', |
|||
alias: '下载中层季度考核' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '高层考核', |
|||
order: 12, |
|||
child: [{ |
|||
show: '月度过程考核', |
|||
alias: '高层月度过程考核', |
|||
child: [{ |
|||
btn: '下载', |
|||
alias: '下载高层月度过程考核' |
|||
}] |
|||
}, { |
|||
show: '季度考核', |
|||
alias: '高层季度考核', |
|||
child: [{ |
|||
btn: '下载', |
|||
alias: '下载高层季度考核' |
|||
}] |
|||
}] |
|||
}, { |
|||
show: '奖惩信息', |
|||
alias: '奖惩管理', |
|||
order: 13, |
|||
child: [{ |
|||
show: '奖惩信息' |
|||
}] |
|||
}]; |
|||
|
|||
let transResult = ''; |
|||
let answerObj = {}; |
|||
|
|||
const getAnswer = async (query) => { |
|||
let start = (new Date()).getTime(); |
|||
let salt = start; |
|||
let str1 = baiduInfo.appid + query + salt + baiduInfo.key; |
|||
let sign = Hex.stringify(MD5(str1)); |
|||
let answer = await request.get('http://api.fanyi.baidu.com/api/trans/vip/translate').timeout(1000 * 30).query({ |
|||
q: query, |
|||
appid: baiduInfo.appid, |
|||
salt: salt, |
|||
from: 'zh', |
|||
to: 'en', |
|||
sign: sign |
|||
}); |
|||
if (answer.body.error_code) { |
|||
console.warn(answer.body); |
|||
throw '百度不给力,快快debug' |
|||
} |
|||
let rslt = answer.body.trans_result; |
|||
// let upperCaseRslt = rslt[0].dst.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase()).replace(/ /g, '');
|
|||
let upperCaseRslt = rslt[0].dst.toUpperCase().replace(/ /g, ''); |
|||
while (((new Date()).getTime() - start) < (1000 / 5)) {//每s只能调用10次
|
|||
continue; |
|||
} |
|||
return upperCaseRslt |
|||
} |
|||
|
|||
(async () => { |
|||
const client = await pool.connect() |
|||
try { |
|||
let oldAnswer = {}; |
|||
let answers; |
|||
if (readAnswer) { |
|||
answers = fs.readFileSync('Answer.txt', 'utf-8') |
|||
answers = JSON.parse(answers); |
|||
|
|||
fs.exists('./AnswerOld.txt', (exists) => { |
|||
if (exists) { |
|||
oldAnswer = fs.readFileSync('AnswerOld.txt', 'utf-8') |
|||
if (oldAnswer != '') { |
|||
oldAnswer = JSON.parse(oldAnswer) |
|||
} else { |
|||
oldAnswer = {} |
|||
} |
|||
} else {//文件不存在
|
|||
oldAnswer = {} |
|||
} |
|||
}); |
|||
|
|||
} else { |
|||
oldAnswer = fs.readFileSync('Answer.txt', 'utf-8') |
|||
if ('' != oldAnswer) |
|||
oldAnswer = JSON.parse(oldAnswer) |
|||
else oldAnswer = {} |
|||
} |
|||
|
|||
await client.query('BEGIN') |
|||
|
|||
let answerArr = []; |
|||
|
|||
const dealResource = async (resource, flag, parentId, childNum) => { |
|||
let index = 1; |
|||
for (let r of resource) { |
|||
let query = r.alias || r.show || r.btn |
|||
console.log(query); |
|||
let name = r.show || r.btn; |
|||
let answer = readAnswer ? answers[query] : await getAnswer(query) |
|||
if (answerArr.some(a => a == answer)) { |
|||
console.error(r); |
|||
console.error(`${query}译名重复了!`) |
|||
throw 'xxx' |
|||
} else { |
|||
answerArr.push(answer) |
|||
} |
|||
let res = {} |
|||
/**对比原来的code */ |
|||
if (oldAnswer[query]) { //resource
|
|||
res = await client.query(`SELECT * FROM resource where code = $1`, [oldAnswer[query]]) |
|||
if (!res.rows.length) { |
|||
console.log(query, 'code码未找到对应值 :', oldAnswer[query]) |
|||
throw `code码未找到对应值 : ${oldAnswer[query]}`; |
|||
} |
|||
if (res.rows[0].name != name || (r.order && res.rows[0].order != r.order) || res.rows[0].order != index) { |
|||
await client.query(`UPDATE resource SET name = $1 ,"order" = $2 WHERE id = $3`, [name, r.order || index, res.rows[0].id]) |
|||
} |
|||
if (r.old && oldAnswer[r.old]) {//r如果原来存在
|
|||
//name code互换
|
|||
const { id } = res.rows[0]; |
|||
res = await client.query(`SELECT * FROM resource where code = $1`, [oldAnswer[r.old]]); |
|||
await client.query(`UPDATE resource SET code = $1 , name = $2 WHERE id = $3`, [oldAnswer[r.old], r.old, id]); |
|||
if (res.rows) |
|||
await client.query(`UPDATE resource SET code = $1 , name = $2 WHERE id = $3`, [oldAnswer[query], name, res.rows[0].id]) |
|||
} |
|||
if (oldAnswer[query] != answer) {//原code码和新翻译不一样
|
|||
// await client.query(`UPDATE system_functions SET code = $1 WHERE code = $2`, [answer, oldAnswer[query]])
|
|||
answer = oldAnswer[query]; //采用原翻译
|
|||
} |
|||
|
|||
if (parentId && parentId != res.rows[0].parentId) {//和库里的parent_id不一致
|
|||
await client.query(`UPDATE resource SET parent_id = $1 WHERE id = $2`, [parentId, res.rows[0].id]); |
|||
} |
|||
|
|||
console.log(oldAnswer[query]); |
|||
delete oldAnswer[query]; |
|||
} else { |
|||
res = await client.query(`SELECT * FROM resource where code = $1`, [answer]) |
|||
if (res && !res.rows.length) { |
|||
const queryText = `INSERT INTO resource(name, code, "order", create_time, parent_id)
|
|||
VALUES( $1, $2, $3, $4, $5) RETURNING id`;
|
|||
res = await client.query(queryText, [name, answer, r.order || index, moment(), parentId ? parentId : null]); |
|||
} |
|||
} |
|||
|
|||
answerObj[query] = answer; |
|||
if (childNum) { |
|||
for (let i = 0; i < childNum; i++) |
|||
transResult += ' '; |
|||
} |
|||
transResult += `${query} : ${r.btn ? '按钮' : '功能'} : ${answer} [${r.order || index}]` |
|||
if (r.child) { |
|||
transResult += '\n'; |
|||
let num = childNum || 0; |
|||
await dealResource(r.child, null, res.rows[0].id, ++num) |
|||
} else { |
|||
if (!flag) |
|||
transResult += ';\n' |
|||
} |
|||
index++; |
|||
} |
|||
} |
|||
await dealResource(resource, true, null, null) |
|||
console.log("oldAnswer", oldAnswer); |
|||
/**删除多余code */ |
|||
for (let item in oldAnswer) { |
|||
if (oldAnswer[item]) { |
|||
const functionData = await client.query(`SELECT * FROM resource where code = $1`, [oldAnswer[item]]); |
|||
if (functionData.rows[0]) { |
|||
const dealChild = async (id) => { |
|||
/**判断当前的code是否是其它code的父值parent_id */ |
|||
const childFunction = await client.query(`SELECT * FROM resource where parent_id = $1`, [id]); |
|||
if (childFunction.rows.length) { |
|||
const childIds = childFunction.rows.reduce((p, c) => p = p.concat(c.id), []); |
|||
for (let child of childIds) { |
|||
await dealChild(child); |
|||
await client.query(`DELETE FROM resource where id = $1`, [child]); |
|||
} |
|||
} |
|||
} |
|||
await dealChild(functionData.rows[0].id); |
|||
await client.query(`DELETE FROM resource where id = $1`, [functionData.rows[0].id]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
await client.query('COMMIT') |
|||
if (!readAnswer) { |
|||
const old = fs.readFileSync('Answer.txt', 'utf-8') |
|||
fs.writeFileSync('AnswerOld.txt', old, 'utf-8'); |
|||
|
|||
fs.writeFileSync('AuthCode.txt', transResult, 'utf-8'); |
|||
fs.writeFileSync('Answer.txt', JSON.stringify(answerObj), 'utf-8'); |
|||
console.log('文件生成完毕!') |
|||
} |
|||
console.log('执行完毕~') |
|||
} catch (e) { |
|||
await client.query('ROLLBACK') |
|||
console.log('执行错误~') |
|||
throw e |
|||
} finally { |
|||
client.release() |
|||
} |
|||
})().catch(e => console.error(e.stack)) |
|||
|
|||
|
|||
} catch (error) { |
|||
console.error(error) |
|||
} |
@ -0,0 +1,19 @@ |
|||
pipeline { |
|||
agent { |
|||
node{ |
|||
label 'jnlp-slave' |
|||
} |
|||
} |
|||
|
|||
stages { |
|||
stage('Testing hrm......') { |
|||
steps { |
|||
buildName "#${BUILD_NUMBER} ~/pep/${JOB_NAME}:${IMAGE_VERSION}" |
|||
buildDescription "harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}" |
|||
sh 'nerdctl build -t harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION} .' |
|||
sh 'nerdctl push harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}' |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
pipeline { |
|||
agent { |
|||
node{ |
|||
label 'jnlp-slave' |
|||
} |
|||
} |
|||
|
|||
stages { |
|||
stage('Testing hrm......') { |
|||
steps { |
|||
buildName '#${BUILD_NUMBER} ~/pep/${JOB_NAME}:${IMAGE_VERSION}' |
|||
buildDescription 'registry.ngaiot.com/pep/${JOB_NAME}:${IMAGE_VERSION}' |
|||
sh 'pwd' |
|||
sh 'nerdctl build -t registry.ngaiot.com/pep/${JOB_NAME}:${IMAGE_VERSION} .' |
|||
sh 'nerdctl push registry.ngaiot.com/pep/${JOB_NAME}:${IMAGE_VERSION}' |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
{ |
|||
"name": "appkey-generator", |
|||
"version": "1.0.0", |
|||
"description": "tool", |
|||
"main": "index.js", |
|||
"scripts": { |
|||
"test": "mocha", |
|||
"start": "set NODE_ENV=development&&node index -e false -t false -p true" |
|||
}, |
|||
"author": "liu", |
|||
"license": "ISC", |
|||
"dependencies": { |
|||
"args": "^3.0.7", |
|||
"crypto-js": "^3.3.0", |
|||
"pg": "^7.18.2", |
|||
"pg-hstore": "^2.3.2", |
|||
"sequelize": "^4.22.12", |
|||
"superagent": "^6.1.0", |
|||
"moment": "^2.29.4" |
|||
} |
|||
} |
@ -0,0 +1,39 @@ |
|||
//create by zhouxin on 2022.10.10 |
|||
|
|||
一、To 测试/研发小伙伴 (修改数据库配置、环境变量参数) |
|||
1.修改config.js数据库配置 |
|||
todo-todo-todo: |
|||
1)测试:修改【ENV_SY_POOL】和【ENV_CS_POOL】定义的配置值; |
|||
2)研发:修改【PRO_POOL】定义的配置值 |
|||
配置参数说明: |
|||
{ |
|||
"host" : 数据库host, //默认值为 10.8.30.36" |
|||
"user" : 数据库user, //默认值为 FashionAdmin |
|||
"database" : 数据库database, // 默认值为 emis0630, |
|||
"password" : 数据库密码, //默认值为 123456", |
|||
"port" : 数据库端口号 //默认值为 5432" |
|||
} |
|||
|
|||
2. 环境变量/启动参数 修改 |
|||
todo-todo-todo: 根据场景设置对应环境参数的true/false, 判断顺序为:FS_ENV > FS_ENV_TEST |
|||
环境变量参数说明: |
|||
{ |
|||
FS_ENV : false , //商用环境 |
|||
FS_ENV_TEST : true , //测试环境 |
|||
} |
|||
|
|||
二、To 研发 |
|||
//启动参数含义 |
|||
配置参数说明: |
|||
{ |
|||
e : false , //env 商用环境 |
|||
t : false , //test 测试环境 |
|||
p : true //product 研发环境 |
|||
} |
|||
|
|||
研发思路(同pm权限工具)answerOld.txt文件,用于和新更改的权限做对比 |
|||
1.第一次执行时,测试需删除answeOld.text文件;研发看情况清空Answer.txt文件还是 readAnswer变量设置为true; |
|||
测试环境调用百度翻译接口有问题,更改权限码后需将answerOld.txt提交 |
|||
|
|||
2.开发注意:中文名称不变,两个 互换位置可以加old属性,仅限两两互换 |
|||
存在bug:中文名称未更改只是换了位置的话,是不做更新的,如不换名字换位置,建议把名称调整下或者单独删除原来那条以及answeOld.text去除 |
Loading…
Reference in new issue