Compare commits
10 Commits
3bab0c3f8a
...
9a20760490
Author | SHA1 | Date | |
---|---|---|---|
9a20760490 | |||
![]() |
00099ed8c2 | ||
![]() |
4c5b831c22 | ||
![]() |
3a566de9d3 | ||
![]() |
180027be76 | ||
![]() |
7421fd70bb | ||
![]() |
40facf16f0 | ||
![]() |
568f95dd5b | ||
![]() |
4919782303 | ||
![]() |
ff74112724 |
@ -17,13 +17,15 @@
|
|||||||
"axios": "0.18.1",
|
"axios": "0.18.1",
|
||||||
"core-js": "3.6.5",
|
"core-js": "3.6.5",
|
||||||
"element-ui": "2.13.2",
|
"element-ui": "2.13.2",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
"js-cookie": "2.2.0",
|
"js-cookie": "2.2.0",
|
||||||
"normalize.css": "7.0.0",
|
"normalize.css": "7.0.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"path-to-regexp": "2.4.0",
|
"path-to-regexp": "2.4.0",
|
||||||
"vue": "2.6.10",
|
"vue": "2.6.10",
|
||||||
"vue-router": "3.0.6",
|
"vue-router": "3.0.6",
|
||||||
"vuex": "3.1.0"
|
"vuex": "3.1.0",
|
||||||
|
"xlsx": "^0.16.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "4.4.4",
|
"@vue/cli-plugin-babel": "4.4.4",
|
||||||
@ -45,6 +47,7 @@
|
|||||||
"sass": "1.26.8",
|
"sass": "1.26.8",
|
||||||
"sass-loader": "8.0.2",
|
"sass-loader": "8.0.2",
|
||||||
"script-ext-html-webpack-plugin": "2.1.3",
|
"script-ext-html-webpack-plugin": "2.1.3",
|
||||||
|
"script-loader": "^0.7.2",
|
||||||
"serve-static": "1.13.2",
|
"serve-static": "1.13.2",
|
||||||
"svg-sprite-loader": "4.1.3",
|
"svg-sprite-loader": "4.1.3",
|
||||||
"svgo": "1.2.2",
|
"svgo": "1.2.2",
|
||||||
|
94
src/api/constant/approvals.js
Normal file
94
src/api/constant/approvals.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// 审批
|
||||||
|
export default {
|
||||||
|
// 审批类型
|
||||||
|
approvalType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '转正'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '调岗'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '离职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '员工信息审核'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '调薪'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '工资审核'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '请假'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
value: '销假'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9',
|
||||||
|
value: '外出'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
value: '销外出'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '11',
|
||||||
|
value: '出差'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '12',
|
||||||
|
value: '销出差'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '13',
|
||||||
|
value: '外勤打卡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '14',
|
||||||
|
value: '补打卡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '15',
|
||||||
|
value: '加班'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '16',
|
||||||
|
value: '招聘'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '17',
|
||||||
|
value: '录用'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 审批状态
|
||||||
|
approvalState: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '审批中'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '审批驳回'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '已撤销'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '审批通过'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
254
src/api/constant/attendance.js
Normal file
254
src/api/constant/attendance.js
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
// 员工端
|
||||||
|
export default {
|
||||||
|
// 假期类型
|
||||||
|
holidayType: [{
|
||||||
|
id: '1',
|
||||||
|
value: '正常',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '旷工',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '事假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '调休',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '迟到',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '早退',
|
||||||
|
isEnable: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
vacationtype: [{
|
||||||
|
id: '1',
|
||||||
|
name: '正常'
|
||||||
|
}, {
|
||||||
|
id: '2',
|
||||||
|
name: '旷工'
|
||||||
|
}, {
|
||||||
|
id: '3',
|
||||||
|
name: '迟到'
|
||||||
|
}, {
|
||||||
|
id: '4',
|
||||||
|
name: '早退'
|
||||||
|
}, {
|
||||||
|
id: '5',
|
||||||
|
name: '外出'
|
||||||
|
}, {
|
||||||
|
id: '6',
|
||||||
|
name: '出差'
|
||||||
|
}, {
|
||||||
|
id: '7',
|
||||||
|
name: '年假'
|
||||||
|
}, {
|
||||||
|
id: '8',
|
||||||
|
name: '事假'
|
||||||
|
}, {
|
||||||
|
id: '9',
|
||||||
|
name: '病假'
|
||||||
|
}, {
|
||||||
|
id: '10',
|
||||||
|
name: '婚假'
|
||||||
|
}, {
|
||||||
|
id: '11',
|
||||||
|
name: '丧假'
|
||||||
|
}, {
|
||||||
|
id: '12',
|
||||||
|
name: '产假'
|
||||||
|
}, {
|
||||||
|
id: '13',
|
||||||
|
name: '奖励产假'
|
||||||
|
}, {
|
||||||
|
id: '14',
|
||||||
|
name: '陪产假'
|
||||||
|
}, {
|
||||||
|
id: '15',
|
||||||
|
name: '探亲假'
|
||||||
|
}, {
|
||||||
|
id: '16',
|
||||||
|
name: '工伤假'
|
||||||
|
}, {
|
||||||
|
id: '17',
|
||||||
|
name: '调休'
|
||||||
|
}, {
|
||||||
|
id: '18',
|
||||||
|
name: '产检假'
|
||||||
|
}, {
|
||||||
|
id: '19',
|
||||||
|
name: '流产假'
|
||||||
|
}, {
|
||||||
|
id: '20',
|
||||||
|
name: '长期病假'
|
||||||
|
}, {
|
||||||
|
id: '21',
|
||||||
|
name: '测试假'
|
||||||
|
}, {
|
||||||
|
id: '22',
|
||||||
|
name: '补签'
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
type: [{
|
||||||
|
leaveType: '60000',
|
||||||
|
name: '年假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60100',
|
||||||
|
name: '事假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60200',
|
||||||
|
name: '病假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60300',
|
||||||
|
name: '婚假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60400',
|
||||||
|
name: '丧假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60500',
|
||||||
|
name: '产假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60600',
|
||||||
|
name: '奖励产假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60700',
|
||||||
|
name: '陪产假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60800',
|
||||||
|
name: '探亲假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '60900',
|
||||||
|
name: '工伤假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '61000',
|
||||||
|
name: '调休假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '61100',
|
||||||
|
name: '产检假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '61200',
|
||||||
|
name: '流产假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '61300',
|
||||||
|
name: '长期病假',
|
||||||
|
isEnable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leaveType: '61400',
|
||||||
|
name: '测试假',
|
||||||
|
isEnable: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
departmentType: [{
|
||||||
|
dedTypeCode: '51000',
|
||||||
|
name: '迟到扣款',
|
||||||
|
isEnable: false,
|
||||||
|
departmentId: '',
|
||||||
|
periodLowerLimit: '30', // 时间段下限
|
||||||
|
periodUpperLimit: '30', // 时间段上限
|
||||||
|
timesLowerLimit: '2', // 次数下限
|
||||||
|
timesUpperLimit: '2', // 次数上限
|
||||||
|
dedAmonutLowerLimit: '30', // 扣款金额下限
|
||||||
|
dedAmonutUpperLimit: '0', // 扣款金额上限
|
||||||
|
absenceDays: '0.5', // 旷工天数
|
||||||
|
fineSalaryMultiples: '2', // 罚款工资倍数
|
||||||
|
absenceTimesUpperLimt: '0' // 旷工次数上限
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dedTypeCode: '52000',
|
||||||
|
name: '早退扣款',
|
||||||
|
isEnable: false,
|
||||||
|
departmentId: '',
|
||||||
|
periodLowerLimit: '30', // 时间段下限
|
||||||
|
periodUpperLimit: '30', // 时间段上限
|
||||||
|
timesLowerLimit: '2', // 次数下限
|
||||||
|
timesUpperLimit: '2', // 次数上限
|
||||||
|
dedAmonutLowerLimit: '30', // 扣款金额下限
|
||||||
|
dedAmonutUpperLimit: '0', // 扣款金额上限
|
||||||
|
absenceDays: '0.5', // 旷工天数
|
||||||
|
fineSalaryMultiples: '2', // 罚款工资倍数
|
||||||
|
absenceTimesUpperLimt: '0' // 旷工次数上限
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dedTypeCode: '53000',
|
||||||
|
name: '旷工扣款',
|
||||||
|
isEnable: false,
|
||||||
|
departmentId: '',
|
||||||
|
periodLowerLimit: '30', // 时间段下限
|
||||||
|
periodUpperLimit: '30', // 时间段上限
|
||||||
|
timesLowerLimit: '2', // 次数下限
|
||||||
|
timesUpperLimit: '2', // 次数上限
|
||||||
|
dedAmonutLowerLimit: '30', // 扣款金额下限
|
||||||
|
dedAmonutUpperLimit: '0', // 扣款金额上限
|
||||||
|
absenceDays: '0.5', // 旷工天数
|
||||||
|
fineSalaryMultiples: '2', // 罚款工资倍数
|
||||||
|
absenceTimesUpperLimt: '0' // 旷工次数上限
|
||||||
|
}
|
||||||
|
],
|
||||||
|
overtimeType: [{
|
||||||
|
// id: '1',
|
||||||
|
departmentId: '', // 部门ID
|
||||||
|
rule: '工作日可申请加班', // 规则内容
|
||||||
|
ruleStartTime: '', // 规则生效每日开始时间
|
||||||
|
ruleEndTime: '', // 规则生效每日结束时间
|
||||||
|
isTimeOff: false, // 是否调休
|
||||||
|
isEnable: false // 是否可用
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// id: '2',
|
||||||
|
departmentId: '', // 部门ID
|
||||||
|
rule: '休息日可申请加班', // 规则内容
|
||||||
|
ruleStartTime: '', // 规则生效每日开始时间
|
||||||
|
ruleEndTime: '', // 规则生效每日结束时间
|
||||||
|
isTimeOff: false, // 是否调休
|
||||||
|
isEnable: false // 是否可用
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// id: '3',
|
||||||
|
departmentId: '', // 部门ID
|
||||||
|
rule: '法定节假日可申请加班', // 规则内容
|
||||||
|
ruleStartTime: '', // 规则生效每日开始时间
|
||||||
|
ruleEndTime: '', // 规则生效每日结束时间
|
||||||
|
isTimeOff: false, // 是否调休
|
||||||
|
isEnable: false // 是否可用
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
26
src/api/constant/common.js
Normal file
26
src/api/constant/common.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 通用
|
||||||
|
export default {
|
||||||
|
// 启用状态
|
||||||
|
enableState: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '启用'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
value: '禁用'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 有无
|
||||||
|
hasState: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '有'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
value: '无'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
420
src/api/constant/employees.js
Normal file
420
src/api/constant/employees.js
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
// 员工
|
||||||
|
export default {
|
||||||
|
// 聘用形式
|
||||||
|
hireType: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
value: '正式'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
value: '非正式'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 管理形式
|
||||||
|
subjection: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '总部'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '分城市'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 在职状态
|
||||||
|
workingState: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '在职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '离职'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 离职类型
|
||||||
|
leaveType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '主动离职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '被动离职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '退休'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 减员月
|
||||||
|
attritionMonth: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '离职日本月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '离职日次月'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 聘用形式
|
||||||
|
informaltype: [
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '实习'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '劳务'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '顾问'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '返聘'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '外包'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 最高学历
|
||||||
|
highestDegree: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '初中'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '高中'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '中专'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '大专'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '本科'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '硕士'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '博士'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
value: '其他'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 国家/地区
|
||||||
|
isOverseas: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '中国大陆'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '港澳台国外'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 性别
|
||||||
|
gender: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '男'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '女'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 婚姻状况
|
||||||
|
maritaStatus: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '未婚'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '已婚'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '离异'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 生肖
|
||||||
|
animalSymbol: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '鼠'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '牛'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '虎'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '兔'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '龙'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '蛇'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '马'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
value: '羊'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9',
|
||||||
|
value: '猴'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
value: '鸡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '11',
|
||||||
|
value: '狗'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '12',
|
||||||
|
value: '猪'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 星座
|
||||||
|
constellation: [
|
||||||
|
{
|
||||||
|
code: 1,
|
||||||
|
value: '水瓶座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 2,
|
||||||
|
value: '双鱼座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 3,
|
||||||
|
value: '白羊座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 4,
|
||||||
|
value: '金牛座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 5,
|
||||||
|
value: '双子座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 6,
|
||||||
|
value: '巨蟹座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 7,
|
||||||
|
value: '狮子座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 8,
|
||||||
|
value: '处女座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 9,
|
||||||
|
value: '天秤座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 10,
|
||||||
|
value: '天蝎座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 11,
|
||||||
|
value: '射手座'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 12,
|
||||||
|
value: '摩羯座'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 血型
|
||||||
|
bloodType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: 'A型'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: 'B型'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: 'O型'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: 'AB型'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 学历
|
||||||
|
educationType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '统招'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '自考'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '成考'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 转正
|
||||||
|
positiveType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '已转正'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '未转正'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 合同期限
|
||||||
|
contractPeriod: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '6月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '12月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '24月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '36月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '其他'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 签约次数
|
||||||
|
renewalCount: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
value: '0次'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
value: '1次'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
value: '2次'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
value: '3次'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
value: '4次或以上'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 简历来源
|
||||||
|
resumeSource: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '智联招聘'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '拉勾网'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '前程无忧'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '猎聘网'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '校园宣讲'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '猎头'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '内部推荐'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 社招/校招
|
||||||
|
hireSourceType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '社招'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '校招'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 新加
|
||||||
|
// 部门
|
||||||
|
departments: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '总裁办'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '研究院'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 职位状态
|
||||||
|
stausInfos: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '在职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '入职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '离职'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
206
src/api/constant/settings.js
Normal file
206
src/api/constant/settings.js
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
// 公司设置
|
||||||
|
export default {
|
||||||
|
// 所属行业
|
||||||
|
industryKind: [{
|
||||||
|
id: '1',
|
||||||
|
value: '互联网'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '游戏'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '软件'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '电子'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '通信'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '硬件'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '房地产'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
value: '建筑'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9',
|
||||||
|
value: '物业'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
value: '金融'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '11',
|
||||||
|
value: '消费品'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '12',
|
||||||
|
value: '汽车'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '13',
|
||||||
|
value: '机械'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '14',
|
||||||
|
value: '制造'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '15',
|
||||||
|
value: '服务'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '16',
|
||||||
|
value: '外包'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '17',
|
||||||
|
value: '中介'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '18',
|
||||||
|
value: '广告'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '19',
|
||||||
|
value: '传媒'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '20',
|
||||||
|
value: '教育'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '21',
|
||||||
|
value: '文化'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '22',
|
||||||
|
value: '交通'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '23',
|
||||||
|
value: '贸易'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '24',
|
||||||
|
value: '物流'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '25',
|
||||||
|
value: '制药'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '26',
|
||||||
|
value: '医疗'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '27',
|
||||||
|
value: '能源'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '28',
|
||||||
|
value: '化工'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '29',
|
||||||
|
value: '环保'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '30',
|
||||||
|
value: '政府'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '31',
|
||||||
|
value: '农林牧渔'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '32',
|
||||||
|
value: '其他'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 系统模块表
|
||||||
|
systemModules: [{
|
||||||
|
id: 'organizations',
|
||||||
|
value: '组织架构'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'accounts',
|
||||||
|
value: '账户'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'settings',
|
||||||
|
value: '公司设置'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'employees',
|
||||||
|
value: '员工'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'salarys',
|
||||||
|
value: '工资'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'social_securitys',
|
||||||
|
value: '社保'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'attendances',
|
||||||
|
value: '考勤'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'recruits',
|
||||||
|
value: '招聘'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'approvals',
|
||||||
|
value: '审批'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'notices',
|
||||||
|
value: '公告'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 公司规模
|
||||||
|
companySize: [{
|
||||||
|
id: '1',
|
||||||
|
value: '10人以下'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
value: '10-20人'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
value: '20-50人'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
value: '50-100人'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
value: '100-200人'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
value: '200-500人'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
value: '500人以上'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
37
src/api/constant/user.js
Normal file
37
src/api/constant/user.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 员工端
|
||||||
|
export default {
|
||||||
|
// 假期类型
|
||||||
|
holidayType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '事假'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
value: '调休'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 假期类型
|
||||||
|
leaveType: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
value: '请假'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
value: '调休'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 假期类型
|
||||||
|
applyType: [
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
value: '离职'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 15,
|
||||||
|
value: '加班'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -5,3 +5,46 @@ export function getEmployeeSimple() {
|
|||||||
url: '/sys/user/simple'
|
url: '/sys/user/simple'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取员工的综合列表数据
|
||||||
|
* ***/
|
||||||
|
export function getEmployeeList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/sys/user',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除员工接口
|
||||||
|
* ****/
|
||||||
|
export function delEmployee(id) {
|
||||||
|
return request({
|
||||||
|
url: `/sys/user/${id}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** **
|
||||||
|
* 新增员工的接口
|
||||||
|
* **/
|
||||||
|
export function addEmployee(data) {
|
||||||
|
return request({
|
||||||
|
method: 'post',
|
||||||
|
url: '/sys/user',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** *
|
||||||
|
* 批量导入员工的接口
|
||||||
|
*
|
||||||
|
* ***/
|
||||||
|
export function importEmployee(data) {
|
||||||
|
return request({
|
||||||
|
url: '/sys/user/batch',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
147
src/components/UploadExcel/index.vue
Normal file
147
src/components/UploadExcel/index.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<div class="upload-excel">
|
||||||
|
<div class="btn-upload">
|
||||||
|
<el-button :loading="loading" size="mini" type="primary" @click="handleUpload">
|
||||||
|
点击上传
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
|
||||||
|
<div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
|
||||||
|
<i class="el-icon-upload" />
|
||||||
|
<span>将文件拖到此处</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import XLSX from 'xlsx'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
beforeUpload: Function, // eslint-disable-line
|
||||||
|
onSuccess: Function// eslint-disable-line
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
excelData: {
|
||||||
|
header: null,
|
||||||
|
results: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
generateData({ header, results }) {
|
||||||
|
this.excelData.header = header
|
||||||
|
this.excelData.results = results
|
||||||
|
this.onSuccess && this.onSuccess(this.excelData)
|
||||||
|
},
|
||||||
|
handleDrop(e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
if (this.loading) return
|
||||||
|
const files = e.dataTransfer.files
|
||||||
|
if (files.length !== 1) {
|
||||||
|
this.$message.error('Only support uploading one file!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rawFile = files[0] // only use files[0]
|
||||||
|
if (!this.isExcel(rawFile)) {
|
||||||
|
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.upload(rawFile)
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
},
|
||||||
|
handleDragover(e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
e.dataTransfer.dropEffect = 'copy'
|
||||||
|
},
|
||||||
|
handleUpload() {
|
||||||
|
this.$refs['excel-upload-input'].click()
|
||||||
|
},
|
||||||
|
handleClick(e) {
|
||||||
|
const files = e.target.files
|
||||||
|
const rawFile = files[0] // only use files[0]
|
||||||
|
if (!rawFile) return
|
||||||
|
this.upload(rawFile)
|
||||||
|
},
|
||||||
|
upload(rawFile) {
|
||||||
|
this.$refs['excel-upload-input'].value = null // fix can't select the same excel
|
||||||
|
if (!this.beforeUpload) {
|
||||||
|
this.readerData(rawFile)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const before = this.beforeUpload(rawFile)
|
||||||
|
if (before) {
|
||||||
|
this.readerData(rawFile)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readerData(rawFile) {
|
||||||
|
this.loading = true
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = e => {
|
||||||
|
const data = e.target.result
|
||||||
|
const workbook = XLSX.read(data, { type: 'array' })
|
||||||
|
const firstSheetName = workbook.SheetNames[0]
|
||||||
|
const worksheet = workbook.Sheets[firstSheetName]
|
||||||
|
const header = this.getHeaderRow(worksheet)
|
||||||
|
const results = XLSX.utils.sheet_to_json(worksheet)
|
||||||
|
this.generateData({ header, results })
|
||||||
|
this.loading = false
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
reader.readAsArrayBuffer(rawFile)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getHeaderRow(sheet) {
|
||||||
|
const headers = []
|
||||||
|
const range = XLSX.utils.decode_range(sheet['!ref'])
|
||||||
|
let C
|
||||||
|
const R = range.s.r
|
||||||
|
/* start in the first row */
|
||||||
|
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
|
||||||
|
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
|
||||||
|
/* find the cell in the first row */
|
||||||
|
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
|
||||||
|
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
|
||||||
|
headers.push(hdr)
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
},
|
||||||
|
isExcel(file) {
|
||||||
|
return /\.(xlsx|xls|csv)$/.test(file.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.upload-excel {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 100px;
|
||||||
|
.excel-upload-input{
|
||||||
|
display: none;
|
||||||
|
z-index: -9999;
|
||||||
|
}
|
||||||
|
.btn-upload , .drop{
|
||||||
|
border: 1px dashed #bbb;
|
||||||
|
width: 350px;
|
||||||
|
height: 160px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 160px;
|
||||||
|
}
|
||||||
|
.drop{
|
||||||
|
line-height: 80px;
|
||||||
|
color: #bbb;
|
||||||
|
i {
|
||||||
|
font-size: 60px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,10 +1,12 @@
|
|||||||
// 该文件负责所有的公共的组件的全局注册 Vue.use
|
// 该文件负责所有的公共的组件的全局注册 Vue.use
|
||||||
import PageTools from './PageTools'
|
import PageTools from './PageTools'
|
||||||
|
import UploadExcel from './UploadExcel'
|
||||||
export default {
|
export default {
|
||||||
// 为vue准备的第三方包, 必须有install方法
|
// 为vue准备的第三方包, 必须有install方法
|
||||||
// 这里方法可以自动接收一个形参, 就是Vue包
|
// 这里方法可以自动接收一个形参, 就是Vue包
|
||||||
install(Vue) {
|
install(Vue) {
|
||||||
// 注册全局的通用栏组件对象
|
// 注册全局的通用栏组件对象
|
||||||
Vue.component('PageTools', PageTools)
|
Vue.component('PageTools', PageTools)
|
||||||
|
Vue.component('UploadExcel', UploadExcel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
399
src/filters/index.js
Normal file
399
src/filters/index.js
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
// import parseTime, formatTime and set to filter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show plural label if time is plural number
|
||||||
|
* @param {number} time
|
||||||
|
* @param {string} label
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
function pluralize(time, label) {
|
||||||
|
if (time === 1) {
|
||||||
|
return time + label
|
||||||
|
}
|
||||||
|
return time + label + 's'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} time
|
||||||
|
*/
|
||||||
|
export function timeAgo(time) {
|
||||||
|
const between = Date.now() / 1000 - Number(time)
|
||||||
|
if (between < 3600) {
|
||||||
|
return pluralize(~~(between / 60), ' minute')
|
||||||
|
} else if (between < 86400) {
|
||||||
|
return pluralize(~~(between / 3600), ' hour')
|
||||||
|
} else {
|
||||||
|
return pluralize(~~(between / 86400), ' day')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number formatting
|
||||||
|
* like 10000 => 10k
|
||||||
|
* @param {number} num
|
||||||
|
* @param {number} digits
|
||||||
|
*/
|
||||||
|
export function numberFormatter(num, digits) {
|
||||||
|
const si = [
|
||||||
|
{ value: 1E18, symbol: 'E' },
|
||||||
|
{ value: 1E15, symbol: 'P' },
|
||||||
|
{ value: 1E12, symbol: 'T' },
|
||||||
|
{ value: 1E9, symbol: 'G' },
|
||||||
|
{ value: 1E6, symbol: 'M' },
|
||||||
|
{ value: 1E3, symbol: 'k' }
|
||||||
|
]
|
||||||
|
for (let i = 0; i < si.length; i++) {
|
||||||
|
if (num >= si[i].value) {
|
||||||
|
return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 10000 => "10,000"
|
||||||
|
* @param {number} num
|
||||||
|
*/
|
||||||
|
export function toThousandFilter(num) {
|
||||||
|
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upper case first char
|
||||||
|
* @param {String} string
|
||||||
|
*/
|
||||||
|
export function uppercaseFirst(string) {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseTime(time, cFormat) {
|
||||||
|
if (arguments.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((time + '').length === 10) {
|
||||||
|
time = +time * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||||
|
let date
|
||||||
|
if (typeof time === 'object') {
|
||||||
|
date = time
|
||||||
|
} else {
|
||||||
|
date = new Date(parseInt(time))
|
||||||
|
}
|
||||||
|
const formatObj = {
|
||||||
|
y: date.getFullYear(),
|
||||||
|
m: date.getMonth() + 1,
|
||||||
|
d: date.getDate(),
|
||||||
|
h: date.getHours(),
|
||||||
|
i: date.getMinutes(),
|
||||||
|
s: date.getSeconds(),
|
||||||
|
a: date.getDay()
|
||||||
|
}
|
||||||
|
const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||||
|
let value = formatObj[key]
|
||||||
|
if (key === 'a') {
|
||||||
|
return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
|
||||||
|
}
|
||||||
|
if (result.length > 0 && value < 10) {
|
||||||
|
value = '0' + value
|
||||||
|
}
|
||||||
|
return value || 0
|
||||||
|
})
|
||||||
|
return timeStr
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatTime(time, option) {
|
||||||
|
time = +time * 1000
|
||||||
|
const d = new Date(time)
|
||||||
|
const now = Date.now()
|
||||||
|
|
||||||
|
const diff = (now - d) / 1000
|
||||||
|
|
||||||
|
if (diff < 30) {
|
||||||
|
return '刚刚'
|
||||||
|
} else if (diff < 3600) {
|
||||||
|
// less 1 hour
|
||||||
|
return Math.ceil(diff / 60) + '分钟前'
|
||||||
|
} else if (diff < 3600 * 24) {
|
||||||
|
return Math.ceil(diff / 3600) + '小时前'
|
||||||
|
} else if (diff < 3600 * 24 * 2) {
|
||||||
|
return '1天前'
|
||||||
|
}
|
||||||
|
if (option) {
|
||||||
|
return parseTime(time, option)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
d.getMonth() +
|
||||||
|
1 +
|
||||||
|
'月' +
|
||||||
|
d.getDate() +
|
||||||
|
'日' +
|
||||||
|
d.getHours() +
|
||||||
|
'时' +
|
||||||
|
d.getMinutes() +
|
||||||
|
'分'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getNowFormatDate() {
|
||||||
|
var date = new Date()
|
||||||
|
var seperator1 = '-'
|
||||||
|
var year = date.getFullYear()
|
||||||
|
var month = date.getMonth() + 1
|
||||||
|
var strDate = date.getDate()
|
||||||
|
if (month >= 1 && month <= 9) {
|
||||||
|
month = '0' + month
|
||||||
|
}
|
||||||
|
if (strDate >= 0 && strDate <= 9) {
|
||||||
|
strDate = '0' + strDate
|
||||||
|
}
|
||||||
|
var currentdate = year + seperator1 + month + seperator1 + strDate
|
||||||
|
return currentdate
|
||||||
|
}
|
||||||
|
/* 数字 格式化 */
|
||||||
|
export function nFormatter(num, digits) {
|
||||||
|
const si = [{
|
||||||
|
value: 1e18,
|
||||||
|
symbol: 'E'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1e15,
|
||||||
|
symbol: 'P'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1e12,
|
||||||
|
symbol: 'T'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1e9,
|
||||||
|
symbol: 'G'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1e6,
|
||||||
|
symbol: 'M'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1e3,
|
||||||
|
symbol: 'k'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for (let i = 0; i < si.length; i++) {
|
||||||
|
if (num >= si[i].value) {
|
||||||
|
return (
|
||||||
|
(num / si[i].value + 0.1)
|
||||||
|
.toFixed(digits)
|
||||||
|
.replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function html2Text(val) {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.innerHTML = val
|
||||||
|
return div.textContent || div.innerText
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toThousandslsFilter(num) {
|
||||||
|
return (+num || 0)
|
||||||
|
.toString()
|
||||||
|
.replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
||||||
|
}
|
||||||
|
// 验证手机号
|
||||||
|
export function checkPhone(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('手机号不能为空'))
|
||||||
|
} else {
|
||||||
|
const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
|
||||||
|
if (reg.test(value)) {
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
return callback(new Error('请输入正确的手机号'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function checkPassword(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('密码不能为空'))
|
||||||
|
} else if (value.length < 6) {
|
||||||
|
callback(new Error('请至少输入 6 个字符。请不要使用容易被猜到的密码'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 手机号证验证
|
||||||
|
export function checkTel(value, callback) {
|
||||||
|
var reg = /^1[3|4|5|7|8][0-9]\d{8}$/
|
||||||
|
return reg.test(value)
|
||||||
|
}
|
||||||
|
// 身份证验证
|
||||||
|
export function checkiDNumber(value, callback) {
|
||||||
|
var reg = /\d{17}[\d|x]|\d{15}/
|
||||||
|
return reg.test(value)
|
||||||
|
}
|
||||||
|
// 身份证验证
|
||||||
|
export function checkEmails(value, callback) {
|
||||||
|
var reg = /^[A-Za-zd]+([-_.][A-Za-zd]+)*@([A-Za-zd]+[-.])+[A-Za-zd]{2,5}$/
|
||||||
|
return reg.test(value)
|
||||||
|
}
|
||||||
|
// 邮箱验证
|
||||||
|
export function checkEmail(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('邮箱不能为空'))
|
||||||
|
} else {
|
||||||
|
var reg = /^[A-Za-zd]+([-_.][A-Za-zd]+)*@([A-Za-zd]+[-.])+[A-Za-zd]{2,5}$/
|
||||||
|
if (reg.test(value)) {
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
return callback(new Error('请输入正确的邮箱'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 英文验证
|
||||||
|
export function checkCode(value, callback) {
|
||||||
|
var reg = /^[A-Za-z]+$/g
|
||||||
|
return reg.test(value)
|
||||||
|
}
|
||||||
|
// qq验证
|
||||||
|
export function checkQq(value, callback) {
|
||||||
|
var reg = /^[0-9]+$/g
|
||||||
|
return reg.test(value)
|
||||||
|
}
|
||||||
|
// 银行卡号
|
||||||
|
export function formatBankNo(BankNo, callback) {
|
||||||
|
var strBin = '10,18,30,35,37,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,60,62,65,68,69,84,87,88,94,95,98,99'
|
||||||
|
return strBin
|
||||||
|
}
|
||||||
|
export function getStrleng(str, max) {
|
||||||
|
var myLen = 0
|
||||||
|
for (var i = 0; i < str.length && myLen <= max * 2; i++) {
|
||||||
|
if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {
|
||||||
|
myLen++
|
||||||
|
} else myLen += 2
|
||||||
|
}
|
||||||
|
return myLen
|
||||||
|
}
|
||||||
|
// 上传图片格式控制
|
||||||
|
export function updatedImg(file, obj, callback, func) {
|
||||||
|
if (file.size < 10100000) {
|
||||||
|
var fileName = file.name
|
||||||
|
var suffix = fileName
|
||||||
|
.substring(fileName.lastIndexOf('.') + 1)
|
||||||
|
.toUpperCase()
|
||||||
|
if (
|
||||||
|
suffix === 'PDF' ||
|
||||||
|
suffix === 'JPG' ||
|
||||||
|
suffix === 'JPEG' ||
|
||||||
|
suffix === 'PNG' ||
|
||||||
|
suffix === 'GIF'
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
var tipType = '文件类型不正确,请重新上传'
|
||||||
|
callback(tipType)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var tipSize = '文件大小超过5M,请重新上传'
|
||||||
|
callback(tipSize)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 上传文档格式控制
|
||||||
|
export function updatedFile(file, obj, callback, func) {
|
||||||
|
if (file.size < 10100000) {
|
||||||
|
var fileName = file.name
|
||||||
|
var suffix = fileName
|
||||||
|
.substring(fileName.lastIndexOf('.') + 1)
|
||||||
|
.toUpperCase()
|
||||||
|
if (
|
||||||
|
suffix === 'DOC' ||
|
||||||
|
suffix === 'DOCX' ||
|
||||||
|
suffix === 'XLS' ||
|
||||||
|
suffix === 'XLSX' ||
|
||||||
|
suffix === 'PDF' ||
|
||||||
|
suffix === 'ZIP' ||
|
||||||
|
suffix === 'RAR'
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
var tipType = '文件类型不正确,请重新上传'
|
||||||
|
callback(tipType)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var tipSize = '文件大小超过5M,请重新上传'
|
||||||
|
callback(tipSize)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function importFile(file, obj, callback, func) {
|
||||||
|
if (file.size < 10100000) {
|
||||||
|
var fileName = file.name
|
||||||
|
var suffix = fileName
|
||||||
|
.substring(fileName.lastIndexOf('.') + 1)
|
||||||
|
.toUpperCase()
|
||||||
|
if (
|
||||||
|
suffix === 'XLS' ||
|
||||||
|
suffix === 'XLSX'
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
var tipType = '文件类型不正确,请重新上传'
|
||||||
|
callback(tipType)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var tipSize = '文件大小超过10M,请重新上传'
|
||||||
|
callback(tipSize)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function minHeight(resfile) {
|
||||||
|
return document.body.clientHeight - 180 + 'px'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDate(date, fmt = 'yyyy-MM-dd') {
|
||||||
|
if (!(date instanceof Array)) {
|
||||||
|
date = new Date(date)
|
||||||
|
}
|
||||||
|
if (/(y+)/.test(fmt)) {
|
||||||
|
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||||
|
}
|
||||||
|
const o = {
|
||||||
|
'M+': date.getMonth() + 1,
|
||||||
|
'd+': date.getDate(),
|
||||||
|
'h+': date.getHours(),
|
||||||
|
'm+': date.getMinutes(),
|
||||||
|
's+': date.getSeconds()
|
||||||
|
}
|
||||||
|
for (const k in o) {
|
||||||
|
if (new RegExp(`(${k})`).test(fmt)) {
|
||||||
|
const str = o[k] + ''
|
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt
|
||||||
|
}
|
||||||
|
|
||||||
|
function padLeftZero(str) {
|
||||||
|
return ('00' + str).substr(str.length)
|
||||||
|
}
|
||||||
|
export function getBlob(response) {
|
||||||
|
const blob = new Blob([response.data], {
|
||||||
|
type: 'application/vnd.ms-excel'
|
||||||
|
})
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = window.URL.createObjectURL(blob)
|
||||||
|
var filename = decodeURI(response.headers.filename)
|
||||||
|
// link.download = filename + '.xls'
|
||||||
|
link.download = filename
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
// 图片 blob 流转化为可用 src
|
||||||
|
export function imgHandle(obj) {
|
||||||
|
return window.URL.createObjectURL(obj)
|
||||||
|
}
|
@ -16,9 +16,17 @@ import router from './router'
|
|||||||
import '@/icons' // icon
|
import '@/icons' // icon
|
||||||
import '@/permission' // permission control
|
import '@/permission' // permission control
|
||||||
|
|
||||||
|
// 第三方组件全局注册
|
||||||
import Component from '@/components'
|
import Component from '@/components'
|
||||||
Vue.use(Component)
|
Vue.use(Component)
|
||||||
|
|
||||||
|
// 批量注册
|
||||||
|
import * as myfilter from '@/filters'
|
||||||
|
// 遍历注册
|
||||||
|
for (const key in myfilter) {
|
||||||
|
Vue.filter(key, myfilter[key])
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you don't want to use mock-server
|
* If you don't want to use mock-server
|
||||||
* you want to use MockJs for mock api
|
* you want to use MockJs for mock api
|
||||||
|
@ -40,6 +40,16 @@ export const constantRoutes = [
|
|||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/import',
|
||||||
|
component: Layout,
|
||||||
|
hidden: true, // 隐藏在左侧菜单中
|
||||||
|
children: [{
|
||||||
|
path: '', // 二级路由path什么都不写 表示二级默认路由
|
||||||
|
component: () => import('@/views/import')
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|
||||||
// 404 page must be placed at the end !!!
|
// 404 page must be placed at the end !!!
|
||||||
{ path: '*', redirect: '/404', hidden: true }
|
{ path: '*', redirect: '/404', hidden: true }
|
||||||
]
|
]
|
||||||
@ -57,9 +67,9 @@ export const asyncRoutes = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const createRouter = () => new Router({
|
const createRouter = () => new Router({
|
||||||
// mode: 'history', // require service support
|
// mode: 'history', // 需要服务器支持, 默认使用hash模式
|
||||||
scrollBehavior: () => ({ y: 0 }), // 管理滚动行为 如果出现滚动 切换就让 让页面回到顶部
|
scrollBehavior: () => ({ y: 0 }), // 切换路由时, 让页面回到顶部
|
||||||
routes: [...constantRoutes, ...asyncRoutes]
|
routes: [...constantRoutes, ...asyncRoutes] // 合并静态路由和动态路由
|
||||||
})
|
})
|
||||||
|
|
||||||
const router = createRouter()
|
const router = createRouter()
|
||||||
|
220
src/vendor/Export2Excel.js
vendored
Normal file
220
src/vendor/Export2Excel.js
vendored
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
import { saveAs } from 'file-saver'
|
||||||
|
import XLSX from 'xlsx'
|
||||||
|
|
||||||
|
function generateArray(table) {
|
||||||
|
var out = [];
|
||||||
|
var rows = table.querySelectorAll('tr');
|
||||||
|
var ranges = [];
|
||||||
|
for (var R = 0; R < rows.length; ++R) {
|
||||||
|
var outRow = [];
|
||||||
|
var row = rows[R];
|
||||||
|
var columns = row.querySelectorAll('td');
|
||||||
|
for (var C = 0; C < columns.length; ++C) {
|
||||||
|
var cell = columns[C];
|
||||||
|
var colspan = cell.getAttribute('colspan');
|
||||||
|
var rowspan = cell.getAttribute('rowspan');
|
||||||
|
var cellValue = cell.innerText;
|
||||||
|
if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
|
||||||
|
|
||||||
|
//Skip ranges
|
||||||
|
ranges.forEach(function (range) {
|
||||||
|
if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
|
||||||
|
for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Handle Row Span
|
||||||
|
if (rowspan || colspan) {
|
||||||
|
rowspan = rowspan || 1;
|
||||||
|
colspan = colspan || 1;
|
||||||
|
ranges.push({
|
||||||
|
s: {
|
||||||
|
r: R,
|
||||||
|
c: outRow.length
|
||||||
|
},
|
||||||
|
e: {
|
||||||
|
r: R + rowspan - 1,
|
||||||
|
c: outRow.length + colspan - 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//Handle Value
|
||||||
|
outRow.push(cellValue !== "" ? cellValue : null);
|
||||||
|
|
||||||
|
//Handle Colspan
|
||||||
|
if (colspan)
|
||||||
|
for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
|
||||||
|
}
|
||||||
|
out.push(outRow);
|
||||||
|
}
|
||||||
|
return [out, ranges];
|
||||||
|
};
|
||||||
|
|
||||||
|
function datenum(v, date1904) {
|
||||||
|
if (date1904) v += 1462;
|
||||||
|
var epoch = Date.parse(v);
|
||||||
|
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sheet_from_array_of_arrays(data, opts) {
|
||||||
|
var ws = {};
|
||||||
|
var range = {
|
||||||
|
s: {
|
||||||
|
c: 10000000,
|
||||||
|
r: 10000000
|
||||||
|
},
|
||||||
|
e: {
|
||||||
|
c: 0,
|
||||||
|
r: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (var R = 0; R != data.length; ++R) {
|
||||||
|
for (var C = 0; C != data[R].length; ++C) {
|
||||||
|
if (range.s.r > R) range.s.r = R;
|
||||||
|
if (range.s.c > C) range.s.c = C;
|
||||||
|
if (range.e.r < R) range.e.r = R;
|
||||||
|
if (range.e.c < C) range.e.c = C;
|
||||||
|
var cell = {
|
||||||
|
v: data[R][C]
|
||||||
|
};
|
||||||
|
if (cell.v == null) continue;
|
||||||
|
var cell_ref = XLSX.utils.encode_cell({
|
||||||
|
c: C,
|
||||||
|
r: R
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof cell.v === 'number') cell.t = 'n';
|
||||||
|
else if (typeof cell.v === 'boolean') cell.t = 'b';
|
||||||
|
else if (cell.v instanceof Date) {
|
||||||
|
cell.t = 'n';
|
||||||
|
cell.z = XLSX.SSF._table[14];
|
||||||
|
cell.v = datenum(cell.v);
|
||||||
|
} else cell.t = 's';
|
||||||
|
|
||||||
|
ws[cell_ref] = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Workbook() {
|
||||||
|
if (!(this instanceof Workbook)) return new Workbook();
|
||||||
|
this.SheetNames = [];
|
||||||
|
this.Sheets = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function s2ab(s) {
|
||||||
|
var buf = new ArrayBuffer(s.length);
|
||||||
|
var view = new Uint8Array(buf);
|
||||||
|
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function export_table_to_excel(id) {
|
||||||
|
var theTable = document.getElementById(id);
|
||||||
|
var oo = generateArray(theTable);
|
||||||
|
var ranges = oo[1];
|
||||||
|
|
||||||
|
/* original data */
|
||||||
|
var data = oo[0];
|
||||||
|
var ws_name = "SheetJS";
|
||||||
|
|
||||||
|
var wb = new Workbook(),
|
||||||
|
ws = sheet_from_array_of_arrays(data);
|
||||||
|
|
||||||
|
/* add ranges to worksheet */
|
||||||
|
// ws['!cols'] = ['apple', 'banan'];
|
||||||
|
ws['!merges'] = ranges;
|
||||||
|
|
||||||
|
/* add worksheet to workbook */
|
||||||
|
wb.SheetNames.push(ws_name);
|
||||||
|
wb.Sheets[ws_name] = ws;
|
||||||
|
|
||||||
|
var wbout = XLSX.write(wb, {
|
||||||
|
bookType: 'xlsx',
|
||||||
|
bookSST: false,
|
||||||
|
type: 'binary'
|
||||||
|
});
|
||||||
|
|
||||||
|
saveAs(new Blob([s2ab(wbout)], {
|
||||||
|
type: "application/octet-stream"
|
||||||
|
}), "test.xlsx")
|
||||||
|
}
|
||||||
|
|
||||||
|
export function export_json_to_excel({
|
||||||
|
multiHeader = [],
|
||||||
|
header,
|
||||||
|
data,
|
||||||
|
filename,
|
||||||
|
merges = [],
|
||||||
|
autoWidth = true,
|
||||||
|
bookType = 'xlsx'
|
||||||
|
} = {}) {
|
||||||
|
/* original data */
|
||||||
|
filename = filename || 'excel-list'
|
||||||
|
data = [...data]
|
||||||
|
data.unshift(header);
|
||||||
|
|
||||||
|
for (let i = multiHeader.length - 1; i > -1; i--) {
|
||||||
|
data.unshift(multiHeader[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
var ws_name = "SheetJS";
|
||||||
|
var wb = new Workbook(),
|
||||||
|
ws = sheet_from_array_of_arrays(data);
|
||||||
|
|
||||||
|
if (merges.length > 0) {
|
||||||
|
if (!ws['!merges']) ws['!merges'] = [];
|
||||||
|
merges.forEach(item => {
|
||||||
|
ws['!merges'].push(XLSX.utils.decode_range(item))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoWidth) {
|
||||||
|
/*设置worksheet每列的最大宽度*/
|
||||||
|
const colWidth = data.map(row => row.map(val => {
|
||||||
|
/*先判断是否为null/undefined*/
|
||||||
|
if (val == null) {
|
||||||
|
return {
|
||||||
|
'wch': 10
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/*再判断是否为中文*/
|
||||||
|
else if (val.toString().charCodeAt(0) > 255) {
|
||||||
|
return {
|
||||||
|
'wch': val.toString().length * 2
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'wch': val.toString().length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
/*以第一行为初始值*/
|
||||||
|
let result = colWidth[0];
|
||||||
|
for (let i = 1; i < colWidth.length; i++) {
|
||||||
|
for (let j = 0; j < colWidth[i].length; j++) {
|
||||||
|
if (result[j]['wch'] < colWidth[i][j]['wch']) {
|
||||||
|
result[j]['wch'] = colWidth[i][j]['wch'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws['!cols'] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add worksheet to workbook */
|
||||||
|
wb.SheetNames.push(ws_name);
|
||||||
|
wb.Sheets[ws_name] = ws;
|
||||||
|
|
||||||
|
var wbout = XLSX.write(wb, {
|
||||||
|
bookType: bookType,
|
||||||
|
bookSST: false,
|
||||||
|
type: 'binary'
|
||||||
|
});
|
||||||
|
saveAs(new Blob([s2ab(wbout)], {
|
||||||
|
type: "application/octet-stream"
|
||||||
|
}), `${filename}.${bookType}`);
|
||||||
|
}
|
24
src/vendor/Export2Zip.js
vendored
Normal file
24
src/vendor/Export2Zip.js
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
import { saveAs } from 'file-saver'
|
||||||
|
import JSZip from 'jszip'
|
||||||
|
|
||||||
|
export function export_txt_to_zip(th, jsonData, txtName, zipName) {
|
||||||
|
const zip = new JSZip()
|
||||||
|
const txt_name = txtName || 'file'
|
||||||
|
const zip_name = zipName || 'file'
|
||||||
|
const data = jsonData
|
||||||
|
let txtData = `${th}\r\n`
|
||||||
|
data.forEach((row) => {
|
||||||
|
let tempStr = ''
|
||||||
|
tempStr = row.toString()
|
||||||
|
txtData += `${tempStr}\r\n`
|
||||||
|
})
|
||||||
|
zip.file(`${txt_name}.txt`, txtData)
|
||||||
|
zip.generateAsync({
|
||||||
|
type: "blob"
|
||||||
|
}).then((blob) => {
|
||||||
|
saveAs(blob, `${zip_name}.zip`)
|
||||||
|
}, (err) => {
|
||||||
|
alert('导出失败')
|
||||||
|
})
|
||||||
|
}
|
136
src/views/employees/components/add-employee.vue
Normal file
136
src/views/employees/components/add-employee.vue
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog title="新增员工" :visible="showDialog" @close="btnCancel">
|
||||||
|
<!-- 表单 -->
|
||||||
|
<el-form ref="addEmployee" label-width="120px" :model="formData" :rules="rules">
|
||||||
|
<el-form-item label="姓名" prop="username">
|
||||||
|
<el-input v-model="formData.username" style="width:50%" placeholder="请输入姓名" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机" prop="mobile">
|
||||||
|
<el-input v-model="formData.mobile" style="width:50%" placeholder="请输入手机号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="入职时间" prop="timeOfEntry">
|
||||||
|
<el-date-picker v-model="formData.timeOfEntry" style="width:50%" placeholder="请选择入职时间" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="聘用形式" prop="formOfEmployment">
|
||||||
|
<el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="请选择">
|
||||||
|
<!-- 遍历枚举类型 -->
|
||||||
|
<el-option v-for="item in EmployeeEnum.hireType" :key="item.id" :label="item.value" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="工号" prop="workNumber">
|
||||||
|
<el-input v-model="formData.workNumber" style="width:50%" placeholder="请输入工号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门" prop="departmentName">
|
||||||
|
<el-input v-model="formData.departmentName" style="width:50%" placeholder="请选择部门" @focus="getDepartments" />
|
||||||
|
<!-- 树形控件 -->
|
||||||
|
<el-tree v-if="treeData.length > 0 " :data="treeData" :props="{ label: 'name' }" :default-expand-all="true" @node-click="selectNode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="转正时间" prop="correctionTime">
|
||||||
|
<el-date-picker v-model="formData.correctionTime" style="width:50%" placeholder="请选择转正时间" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<!-- footer插槽 -->
|
||||||
|
<template v-slot:footer>
|
||||||
|
<el-row type="flex" justify="center">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-button size="small" @click="btnCancel">取消</el-button>
|
||||||
|
<el-button type="primary" size="small" @click="btnOK">确定</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { addEmployee } from '@/api/employees'
|
||||||
|
import { getDepartments } from '@/api/departments'
|
||||||
|
import { listToTreeData } from '@/utils/list-to-treedata'
|
||||||
|
import EmployeeEnum from '@/api/constant/employees'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
showDialog: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
EmployeeEnum, // 聘用形式枚举
|
||||||
|
loading: false,
|
||||||
|
formData: {
|
||||||
|
username: '',
|
||||||
|
mobile: '',
|
||||||
|
formOfEmployment: '',
|
||||||
|
workNumber: '',
|
||||||
|
departmentName: '',
|
||||||
|
timeOfEntry: '',
|
||||||
|
correctionTime: ''
|
||||||
|
},
|
||||||
|
treeData: [], // 部门树形数据
|
||||||
|
rules: {
|
||||||
|
username: [
|
||||||
|
{ required: true, message: '用户姓名不能为空', trigger: 'blur' },
|
||||||
|
{ min: 1, max: 4, message: '用户姓名为1-4位' }
|
||||||
|
],
|
||||||
|
mobile: [
|
||||||
|
{ required: true, message: '手机号不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
formOfEmployment: [{ required: true, message: '聘用形式不能为空', trigger: 'blur' }],
|
||||||
|
workNumber: [{ required: true, message: '工号不能为空', trigger: 'blur' }],
|
||||||
|
departmentName: [{ required: true, message: '部门不能为空', trigger: 'change' }],
|
||||||
|
timeOfEntry: [{ required: true, message: '入职时间', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getDepartments() {
|
||||||
|
this.showTree = true
|
||||||
|
this.loading = true
|
||||||
|
const { depts } = await getDepartments()
|
||||||
|
this.treeData = listToTreeData(depts, '')
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
// 选择部门事件回调
|
||||||
|
selectNode(node) {
|
||||||
|
this.formData.departmentName = node.name
|
||||||
|
this.treeData = {}
|
||||||
|
},
|
||||||
|
// 点击确定
|
||||||
|
async btnOK() {
|
||||||
|
try {
|
||||||
|
await this.$refs.addEmployee.validate()
|
||||||
|
// 调用新增接口
|
||||||
|
await addEmployee(this.formData) // 新增员工
|
||||||
|
// 告诉父组件更新数据
|
||||||
|
// this.$parent 可以直接调用到父组件的实例 实际上就是父组件this
|
||||||
|
// this.$emit
|
||||||
|
this.$parent.getEmployeeList()
|
||||||
|
this.$parent.showDialog = false
|
||||||
|
this.$message.success('添加员工成功')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
btnCancel() {
|
||||||
|
// 重置原来的数据
|
||||||
|
this.formData = {
|
||||||
|
username: '',
|
||||||
|
mobile: '',
|
||||||
|
formOfEmployment: '',
|
||||||
|
workNumber: '',
|
||||||
|
departmentName: '',
|
||||||
|
timeOfEntry: '',
|
||||||
|
correctionTime: ''
|
||||||
|
}
|
||||||
|
this.$refs.addEmployee.resetFields() // 重置校验结果
|
||||||
|
this.$emit('update:showDialog', false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
@ -1,16 +1,124 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dashboard-container">
|
<div class="dashboard-container">
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<h2>
|
<page-tools :show-before="true">
|
||||||
员工
|
<span slot="before">共166条记录</span>
|
||||||
</h2>
|
<template slot="after">
|
||||||
|
<el-button size="small" type="warning" @click="$router.push('/import?type=employees')">导入</el-button>
|
||||||
|
<el-button size="small" type="danger" @click="exportExcel">导出</el-button>
|
||||||
|
<el-button size="small" type="primary" @click="showDialog = true">新增员工</el-button>
|
||||||
|
</template>
|
||||||
|
</page-tools>
|
||||||
|
<!-- 放置表格和分页 -->
|
||||||
|
<el-card v-loading="loading">
|
||||||
|
<el-table border :data="list" :default-sort="{prop:'workNumber',order:'ascending'}">
|
||||||
|
<el-table-column label="序号" sortable="" type="index" />
|
||||||
|
<el-table-column label="姓名" sortable="" prop="username" />
|
||||||
|
<el-table-column label="工号" sortable prop="workNumber" />
|
||||||
|
<el-table-column label="手机号" sortable="" prop="mobile" />
|
||||||
|
<el-table-column label="聘用形式" sortable="" prop="formOfEmployment" :formatter="formatEmployment" />
|
||||||
|
<el-table-column label="部门" sortable="" prop="departmentName" />
|
||||||
|
<el-table-column label="入职时间" sortable="">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
{{ row.timeOfEntry | formatDate }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="账户状态" sortable="">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-switch :value="row.enableState === 1" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="280">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button type="text" size="small">查看</el-button>
|
||||||
|
<el-button type="text" size="small">转正</el-button>
|
||||||
|
<el-button type="text" size="small">调岗</el-button>
|
||||||
|
<el-button type="text" size="small">离职</el-button>
|
||||||
|
<el-button type="text" size="small">角色</el-button>
|
||||||
|
<el-button type="text" size="small" @click="delEmployee(row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<el-row type="flex" justify="center" align="middle" style="height: 60px">
|
||||||
|
<el-pagination layout="prev, pager, next" :page-size="page.size" :current-page="page.page" :total="page.total" @current-change="changePage" />
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 新增/编辑 弹窗 -->
|
||||||
|
<add-employee :show-dialog.sync="showDialog" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getEmployeeList, delEmployee } from '@/api/employees'
|
||||||
|
import EmployeeEnum from '@/api/constant/employees'
|
||||||
|
import AddEmployee from './components/add-employee'
|
||||||
export default {
|
export default {
|
||||||
|
components: { AddEmployee },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: [], // 员工列表
|
||||||
|
page: {
|
||||||
|
page: 1, // 当前页码
|
||||||
|
size: 10, // 每页条数
|
||||||
|
total: 0 // 总数
|
||||||
|
},
|
||||||
|
showDialog: false // 弹窗
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getEmployeeList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 翻页
|
||||||
|
changePage(newPage) {
|
||||||
|
this.page.page = newPage
|
||||||
|
this.getEmployeeList()
|
||||||
|
},
|
||||||
|
// 获取员工列表
|
||||||
|
async getEmployeeList() {
|
||||||
|
this.loading = true
|
||||||
|
const { total, rows } = await getEmployeeList(this.page)
|
||||||
|
this.page.total = total
|
||||||
|
this.list = rows
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
// 格式化聘用形式
|
||||||
|
formatEmployment(row, column, cellValue, index) {
|
||||||
|
// 要去找1所对应的值
|
||||||
|
const obj = EmployeeEnum.hireType.find(item => item.id === cellValue)
|
||||||
|
// 把需要的格式return出去
|
||||||
|
return obj ? obj.value : '未知'
|
||||||
|
},
|
||||||
|
// 删除员工
|
||||||
|
async delEmployee(id) {
|
||||||
|
try {
|
||||||
|
await this.$confirm('确定删除该员工吗?')
|
||||||
|
await delEmployee(id)
|
||||||
|
// 如果是不是第一页并且只有一条, 向前翻页
|
||||||
|
if (this.list.length === 1 && this.page.page > 1) {
|
||||||
|
this.page.page -= 1
|
||||||
|
}
|
||||||
|
this.getEmployeeList()
|
||||||
|
this.$message.success('删除员工成功')
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 导出按钮
|
||||||
|
exportExcel() {
|
||||||
|
import('@/vendor/Export2Excel').then(excel => {
|
||||||
|
excel.export_json_to_excel({
|
||||||
|
header: tHeader, // 表头 必填
|
||||||
|
data, // 具体数据 必填
|
||||||
|
filename: 'excel-list', // 非必填
|
||||||
|
autoWidth: true, // 非必填
|
||||||
|
bookType: 'xlsx' // 非必填
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
72
src/views/import/index.vue
Normal file
72
src/views/import/index.vue
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 公共导入组件 -->
|
||||||
|
<upload-excel :on-success="onSuccess" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { importEmployee } from '@/api/employees'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async onSuccess(data) {
|
||||||
|
try {
|
||||||
|
console.log(data)
|
||||||
|
if (this.$route.query.type === 'employees') {
|
||||||
|
const oldUserDate = data.results
|
||||||
|
// 字典
|
||||||
|
const dict = {
|
||||||
|
'入职日期': 'timeOfEntry',
|
||||||
|
'手机号': 'mobile',
|
||||||
|
'姓名': 'username',
|
||||||
|
'转正日期': 'correctionTime',
|
||||||
|
'工号': 'workNumber'
|
||||||
|
}
|
||||||
|
// 遍历数组, 每次操作一个对象
|
||||||
|
const userData = oldUserDate.map(user => {
|
||||||
|
// 空对象存放新数据
|
||||||
|
const obj = {}
|
||||||
|
// 遍历一个对象, 对key进行替换
|
||||||
|
for (const cnKey in user) {
|
||||||
|
const enKey = dict[cnKey]
|
||||||
|
let value = user[cnKey]
|
||||||
|
// 特殊: 日期转换
|
||||||
|
if (enKey === 'timeOfEntry' || enKey === 'correctionTime') {
|
||||||
|
value = new Date(this.formatDate(value, '/'))
|
||||||
|
}
|
||||||
|
obj[enKey] = value
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
})
|
||||||
|
console.log(userData)
|
||||||
|
await importEmployee(userData)
|
||||||
|
this.$message.success('导入成功')
|
||||||
|
this.$router.back()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 转换excel日期
|
||||||
|
formatDate(numb, format) {
|
||||||
|
const time = new Date((numb - 1) * 24 * 3600000 + 1)
|
||||||
|
time.setYear(time.getFullYear() - 70)
|
||||||
|
const year = time.getFullYear() + ''
|
||||||
|
const month = time.getMonth() + 1 + ''
|
||||||
|
const date = time.getDate() - 1 + ''
|
||||||
|
if (format && format.length === 1) {
|
||||||
|
return year + format + month + format + date
|
||||||
|
}
|
||||||
|
return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user