Commit 9aad480f by yubin

离职时间添加

parent 30a96ce8
...@@ -60,3 +60,12 @@ export const getUserMultiSelectorList = (param) => { ...@@ -60,3 +60,12 @@ export const getUserMultiSelectorList = (param) => {
data: param data: param
}) })
} }
// 根据ID获取单个用户信息
export const getDmUserById = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUser/getById',
method: 'post',
data: param
})
}
\ No newline at end of file
...@@ -1035,13 +1035,13 @@ export default { ...@@ -1035,13 +1035,13 @@ export default {
user_ids: userIds user_ids: userIds
}).then(ret => { }).then(ret => {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
this.fetchList("org") this.fetchList('org')
this.$Message.success('保存成功') this.$Message.success('保存成功')
this.userAssignModal.visible = false this.userAssignModal.visible = false
} else { } else {
this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg }) this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg })
} }
}).finally(() => { }) }).finally(() => { })
} }
} }
} }
......
<template> <template>
<div class="key-dm-leave-wrapper"> <div class="key-dm-leave-wrapper">
<div v-if="pendingCount > 0" class="pushCls">
<div class="pushIconCls"></div>
</div>
<Tabs v-model="activeTab" @on-click="handleTabChange" class="tabsCls"> <Tabs v-model="activeTab" @on-click="handleTabChange" class="tabsCls">
<TabPane label="请假申请" name="apply"> <TabPane label="请假申请" name="apply">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" class="mt8"> <Row type="flex" :gutter="16" class="mt8">
<Col span="20"> <Col span="12">
<span>开始:</span> <span>开始:</span>
<DatePicker v-model="filters.apply.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.apply.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span> <span>结束:</span>
<DatePicker v-model="filters.apply.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.apply.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span> <span>状态:</span>
<Select v-model="filters.apply.status" style="width: 150px"> <Select v-model="filters.apply.status" style="width: 60%">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option> <Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="4" class="text-right"> <Col span="4" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('apply')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('apply')">搜索</Button>
<Button type="primary" class="mr10" @click="handleReset('apply')">重置</Button> <Button class="mr10" @click="handleReset('apply')">重置</Button>
<Button type="primary" @click="openApplyModal">申请</Button> <Button type="success" @click="openApplyModal">申请</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -36,12 +41,7 @@ ...@@ -36,12 +41,7 @@
show-total show-sizer @on-change="pageChange('apply', $event)" @on-page-size-change="sizeChange('apply', $event)" /> show-total show-sizer @on-change="pageChange('apply', $event)" @on-page-size-change="sizeChange('apply', $event)" />
</TabPane> </TabPane>
<TabPane name="pending"> <TabPane :label="'请假待审核'" name="pending">
<template slot="label">
<span class="tab-label">请假待审核
<span v-if="pendingCount > 0" class="exclaim-inline"></span>
</span>
</template>
<Table border :loading="loading.pending" :columns="pendingColumns" :data="tables.pending"> <Table border :loading="loading.pending" :columns="pendingColumns" :data="tables.pending">
<template slot="action" slot-scope="{ row }"> <template slot="action" slot-scope="{ row }">
<div class="action-buttons"> <div class="action-buttons">
...@@ -56,19 +56,21 @@ ...@@ -56,19 +56,21 @@
<TabPane label="审核历史查询" name="history"> <TabPane label="审核历史查询" name="history">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col span="20"> <Col span="12">
<span>开始:</span> <span>开始:</span>
<DatePicker v-model="filters.history.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.history.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span> <span>结束:</span>
<DatePicker v-model="filters.history.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.history.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span> <span>状态:</span>
<Select v-model="filters.history.status" style="width: 150px" class="mr10"> <Select v-model="filters.history.status" style="width: 60%">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option> <Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="4" class="text-right"> <Col span="4" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('history')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('history')">搜索</Button>
<Button type="primary" @click="handleReset('history')">重置</Button> <Button @click="handleReset('history')">重置</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -84,19 +86,21 @@ ...@@ -84,19 +86,21 @@
<TabPane label="请假申请查询" name="query"> <TabPane label="请假申请查询" name="query">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col span="16"> <Col span="12">
<span>开始:</span> <span>开始:</span>
<DatePicker v-model="filters.query.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.query.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span> <span>结束:</span>
<DatePicker v-model="filters.query.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="filters.query.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span> <span>状态:</span>
<Select v-model="filters.query.status" style="width: 150px"> <Select v-model="filters.query.status" style="width: 60%">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option> <Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="8" class="text-right"> <Col span="4" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('query')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('query')">搜索</Button>
<Button type="primary" @click="handleReset('query')">重置</Button> <Button @click="handleReset('query')">重置</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -117,12 +121,11 @@ ...@@ -117,12 +121,11 @@
<DatePicker v-model="statsStart" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="statsStart" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span> <span>结束:</span>
<DatePicker v-model="statsEnd" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" /> <DatePicker v-model="statsEnd" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
<span>部门:</span>
<Input v-model="statsDept" placeholder="请输入部门名称" style="width: 200px" />
</Col> </Col>
<Col span="8" class="text-right"> <Col span="8" class="text-right">
<Button type="primary" class="mr10" @click="loadStats">统计</Button> <Button type="primary" class="mr10" @click="loadStats">统计</Button>
<Button type="primary" @click="resetStats">重置</Button> <Button @click="resetStats">重置</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -132,7 +135,7 @@ ...@@ -132,7 +135,7 @@
<!-- 申请弹窗 --> <!-- 申请弹窗 -->
<Modal v-model="applyModal.visible" :title="applyModal.isEdit ? '修改请假' : '新增请假'" width="700"> <Modal v-model="applyModal.visible" :title="applyModal.isEdit ? '修改请假' : '新增请假'" width="700">
<Form :model="applyModal.form" :label-width="120" ref="applyForm"> <Form :model="applyModal.form" :rules="applyRules" :label-width="120" ref="applyForm">
<FormItem label="请假类型" prop="leave_type_id"> <FormItem label="请假类型" prop="leave_type_id">
<Select v-model="applyModal.form.leave_type_id" style="width: 60%"> <Select v-model="applyModal.form.leave_type_id" style="width: 60%">
<Option v-for="opt in leaveTypes" :key="opt.id" :value="opt.id">{{ opt.type_name }}</Option> <Option v-for="opt in leaveTypes" :key="opt.id" :value="opt.id">{{ opt.type_name }}</Option>
...@@ -150,7 +153,7 @@ ...@@ -150,7 +153,7 @@
<FormItem label="紧急联系人"> <FormItem label="紧急联系人">
<Input v-model="applyModal.form.emergency_contact" /> <Input v-model="applyModal.form.emergency_contact" />
</FormItem> </FormItem>
<FormItem label="紧急电话"> <FormItem label="紧急电话" prop="emergency_phone">
<Input v-model="applyModal.form.emergency_phone" /> <Input v-model="applyModal.form.emergency_phone" />
</FormItem> </FormItem>
<FormItem label="指定审批人" prop="approver_id"> <FormItem label="指定审批人" prop="approver_id">
...@@ -312,10 +315,10 @@ export default { ...@@ -312,10 +315,10 @@ export default {
{ title: '申请人', key: 'user_name', align: 'center' }, { title: '申请人', key: 'user_name', align: 'center' },
{ title: '部门', key: 'department_name', align: 'center' }, { title: '部门', key: 'department_name', align: 'center' },
{ title: '请假类型', key: 'leave_type_name', align: 'center' }, { title: '请假类型', key: 'leave_type_name', align: 'center' },
{ title: '起止时间', key: 'start_time', align: 'center', render: (h, { row }) => h('span', `${row.start_time || '-'} ~ ${row.end_time || '-'}`) }, { title: '起止时间', key: 'start_time',width: 300, align: 'center', render: (h, { row }) => h('span', `${row.start_time || '-'} ~ ${row.end_time || '-'}`) },
{ title: '时长', key: 'duration', align: 'center' }, { title: '时长', key: 'duration', align: 'center' },
{ title: '状态', key: 'status', align: 'center', render: (h, { row }) => h('span', this.mapStatusText(row.status)) }, { title: '状态', key: 'status', align: 'center', render: (h, { row }) => h('span', this.mapStatusText(row.status)) },
{ title: '操作', slot: 'action', align: 'center', width: 320 } { title: '操作', slot: 'action', align: 'center', width: 160 }
], ],
pendingColumns: [ pendingColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
...@@ -342,8 +345,8 @@ export default { ...@@ -342,8 +345,8 @@ export default {
], ],
statsColumns: [ statsColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '人员', key: 'user_name', align: 'center' },
{ title: '部门', key: 'department_name', align: 'center' }, { title: '部门', key: 'department_name', align: 'center' },
{ title: '人员', key: 'user_name', align: 'center' },
{ title: '已通过天数', key: 'passed_days', align: 'center' } { title: '已通过天数', key: 'passed_days', align: 'center' }
], ],
detailApprovalColumns: [ detailApprovalColumns: [
...@@ -376,7 +379,30 @@ export default { ...@@ -376,7 +379,30 @@ export default {
detailModal: { visible: false, loading: false, data: {}, approvals: [] }, detailModal: { visible: false, loading: false, data: {}, approvals: [] },
statsStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1), statsStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
statsEnd: new Date(), statsEnd: new Date(),
statsDept: '' statsDept: '',
// 表单验证规则
applyRules: {
leave_type_id: [
{ required: true, message: '请选择请假类型', trigger: 'change' }
],
start_time: [
{ required: true, message: '请选择开始时间', trigger: 'change', type: 'date' }
],
end_time: [
{ required: true, message: '请选择结束时间', trigger: 'change', type: 'date' }
],
approver_id: [
{ required: true, message: '请选择指定审批人', trigger: 'change' }
],
emergency_phone: [
{ message: '请输入紧急电话', trigger: 'blur' },
{
pattern: /^(1[3-9]\d{9})|((0\d{2,3}-?)?\d{7,8})$/,
message: '请输入有效的电话号码',
trigger: 'blur'
}
]
}
} }
}, },
created () { created () {
...@@ -419,7 +445,6 @@ export default { ...@@ -419,7 +445,6 @@ export default {
if (name === 'pending') this.fetchList('pending') if (name === 'pending') this.fetchList('pending')
if (name === 'history') this.fetchList('history') if (name === 'history') this.fetchList('history')
if (name === 'query') this.fetchList('query') if (name === 'query') this.fetchList('query')
if (name === 'stats') this.loadStats()
}, },
fetchList (tab) { fetchList (tab) {
const apiMap = { apply: getLeaveListByUserId, pending: getPendingList, history: getApprovalHistory, query: getLeaveList } const apiMap = { apply: getLeaveListByUserId, pending: getPendingList, history: getApprovalHistory, query: getLeaveList }
...@@ -519,6 +544,8 @@ export default { ...@@ -519,6 +544,8 @@ export default {
* Prepare query params: normalize start_time/end_time into DB datetime strings. * Prepare query params: normalize start_time/end_time into DB datetime strings.
* - If start_time exists, set to 00:00:00 of that day. * - If start_time exists, set to 00:00:00 of that day.
* - If end_time exists, set to 23:59:59 of that day. * - If end_time exists, set to 23:59:59 of that day.
* - If only end_time is selected, set start_time to a very early date (e.g., 1970-01-01)
* to ensure backend queries records before the end_time.
* Returns a shallow copy of filters[tab] with formatted strings. * Returns a shallow copy of filters[tab] with formatted strings.
*/ */
prepareQueryParams (tab) { prepareQueryParams (tab) {
...@@ -532,15 +559,21 @@ export default { ...@@ -532,15 +559,21 @@ export default {
return isNaN(d.getTime()) ? null : d return isNaN(d.getTime()) ? null : d
} catch (e) { return null } } catch (e) { return null }
} }
// Handle start_time
if (raw.start_time) { if (raw.start_time) {
const sd = parseToDate(raw.start_time) const sd = parseToDate(raw.start_time)
if (sd) { if (sd) {
sd.setHours(0, 0, 0, 0) sd.setHours(0, 0, 0, 0)
raw.start_time = this.formatForDbDatetime(sd) raw.start_time = this.formatForDbDatetime(sd)
} }
} else if (raw.end_time && !raw.start_time) {
// If only end_time is selected, set start_time to a very early date
// to ensure backend queries all records before the end_time
raw.start_time = '1970-01-01 00:00:00'
} }
// 只有当用户选择了结束时间时,才设置结束时间的查询条件
// 如果没有选择结束时间,则不设置 end_time,让后端查询从开始时间之后的所有记录 // Handle end_time
if (raw.end_time) { if (raw.end_time) {
const ed = parseToDate(raw.end_time) const ed = parseToDate(raw.end_time)
if (ed) { if (ed) {
...@@ -600,6 +633,7 @@ export default { ...@@ -600,6 +633,7 @@ export default {
}, },
loadLeaveApprovalOptions () { loadLeaveApprovalOptions () {
// 从后端获取有请假审批权限的机构/人员列表,并映射为 { id, name } 供 Select 使用 // 从后端获取有请假审批权限的机构/人员列表,并映射为 { id, name } 供 Select 使用
// 如果返回数据中存在 leader===1 的条目,则默认将 selectedApprovalUser 设为该 id(优先使用 leader 标记的审批人)
getLeaveApprovalPermission().then(res => { getLeaveApprovalPermission().then(res => {
const d = res && res.data const d = res && res.data
let results = [] let results = []
...@@ -610,6 +644,17 @@ export default { ...@@ -610,6 +644,17 @@ export default {
else if (d.data && Array.isArray(d.data.results)) results = d.data.results else if (d.data && Array.isArray(d.data.results)) results = d.data.results
} }
// 先尝试找到 leader === 1 的条目(支持数字或字符串)
let leaderId = ''
for (let it of (results || [])) {
if (!it) continue
if (it.leader === 1 || it.leader === '1') {
const rawId = it.user_id || it.id || it.userId || ''
leaderId = rawId === null || rawId === undefined ? '' : String(rawId)
break
}
}
// 统一将 id 转为字符串,避免类型不一致导致 Select 无法正确匹配显示 // 统一将 id 转为字符串,避免类型不一致导致 Select 无法正确匹配显示
this.leaveApprovalOptions = (results || []).map(it => { this.leaveApprovalOptions = (results || []).map(it => {
const rawId = it.user_id || it.id || it.userId || '' const rawId = it.user_id || it.id || it.userId || ''
...@@ -618,6 +663,14 @@ export default { ...@@ -618,6 +663,14 @@ export default {
name: it.user_name || it.name || it.userName || it.nick || '' name: it.user_name || it.name || it.userName || it.nick || ''
} }
}) })
// 如果存在 leader,默认选中该用户(不覆盖已有已选值,除非为空)
if (leaderId) {
// 仅在当前未有已选审批人时设置默认值,避免影响编辑场景
if (!this.selectedApprovalUser || String(this.selectedApprovalUser).trim() === '') {
this.selectedApprovalUser = leaderId
}
}
}).catch(err => { }).catch(err => {
console.error('loadLeaveApprovalOptions error', err) console.error('loadLeaveApprovalOptions error', err)
}) })
...@@ -674,9 +727,12 @@ export default { ...@@ -674,9 +727,12 @@ export default {
this.applyModal.visible = true this.applyModal.visible = true
}, },
saveApply () { saveApply () {
this.applyModal.saving = true this.$refs.applyForm.validate((valid) => {
if (!valid) {
return false
}
// 验证开始/结束时间:结束时间必须大于开始时间 // 验证开始/结束时间:结束时间必须大于开始时间
const form = this.applyModal.form || {} const form = this.applyModal.form || {}
const parseToDate = (v) => { const parseToDate = (v) => {
if (v === null || v === undefined || v === '') return null if (v === null || v === undefined || v === '') return null
...@@ -702,22 +758,24 @@ export default { ...@@ -702,22 +758,24 @@ export default {
} }
} }
// 拷贝表单并格式化开始/结束时间为数据库 datetime 字符串 // 拷贝表单并格式化开始/结束时间为数据库 datetime 字符串
const payload = Object.assign({}, this.applyModal.form) const payload = Object.assign({}, this.applyModal.form)
// 同时把审批人姓名一并传回后端(优先使用表单中的 approver_id,否则使用页面选中的 selectedApprovalUser) // 同时把审批人姓名一并传回后端(优先使用表单中的 approver_id,否则使用页面选中的 selectedApprovalUser)
const approverId = payload.approver_id || this.selectedApprovalUser || '' const approverId = payload.approver_id || this.selectedApprovalUser || ''
const approverOption = (this.leaveApprovalOptions || []).find(opt => opt.id === approverId) const approverOption = (this.leaveApprovalOptions || []).find(opt => opt.id === approverId)
payload.approver_name = approverOption ? approverOption.name : (payload.approver_name || '') payload.approver_name = approverOption ? approverOption.name : (payload.approver_name || '')
if (payload.start_time) payload.start_time = this.formatForDbDatetime(payload.start_time) if (payload.start_time) payload.start_time = this.formatForDbDatetime(payload.start_time)
if (payload.end_time) payload.end_time = this.formatForDbDatetime(payload.end_time) if (payload.end_time) payload.end_time = this.formatForDbDatetime(payload.end_time)
saveLeaveApplication(payload).then(ret => { this.applyModal.saving = true
saveLeaveApplication(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功') this.$Message.success('保存成功')
this.applyModal.visible = false this.applyModal.visible = false
this.fetchList('apply') this.fetchList('apply')
} else this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg }) } else this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.applyModal.saving = false }) }).finally(() => { this.applyModal.saving = false })
})
}, },
canEdit (row) { canEdit (row) {
const status = row && row.status !== null && row.status !== undefined ? Number(row.status) : null const status = row && row.status !== null && row.status !== undefined ? Number(row.status) : null
...@@ -1005,13 +1063,44 @@ export default { ...@@ -1005,13 +1063,44 @@ export default {
text-align: center; text-align: center;
} }
.tab-label { display: inline-flex; align-items: center; gap: 6px; } .tab-label { display: inline-flex; align-items: center; gap: 6px; }
.exclaim-inline {
color: #ff4d4f; /* badge positioning (like key-person-dual) */
font-weight: 700; .pushCls {
display: inline-block; position: absolute;
z-index: 10;
left: 202px;
top: 10px;
}
.pushIconCls {
position: relative;
z-index: 11;
cursor: pointer;
color: red;
font-weight: bold;
font-size: 16px; font-size: 16px;
margin-left: 6px;
transform: translateY(-6px);
line-height: 16px; line-height: 16px;
} }
</style> </style>
<style>
/* ensure tab label content from slot (rendered by Tabs component) is visible */
.tab-label {
display: inline-flex;
align-items: center;
gap: 6px;
color: #333 !important;
font-weight: 500;
}
.exclaim-badge {
background: #ff4d4f !important;
color: #fff !important;
border-radius: 10px !important;
padding: 0 6px !important;
font-weight: 700 !important;
display: inline-block !important;
line-height: 18px !important;
margin-left: 6px;
min-width: 14px;
text-align: center;
font-size: 12px;
}
</style>
...@@ -61,11 +61,14 @@ ...@@ -61,11 +61,14 @@
<Input v-model="editModal.form.leader_name" readonly placeholder="点击选择直属领导" @click.native="selectLeader" style="cursor: pointer" /> <Input v-model="editModal.form.leader_name" readonly placeholder="点击选择直属领导" @click.native="selectLeader" style="cursor: pointer" />
</FormItem> </FormItem>
<FormItem label="是否离职"> <FormItem label="是否离职">
<Select v-model="editModal.form.is_leave" style="width: 160px"> <Select v-model="editModal.form.is_leave" style="width: 160px" @on-change="onIsLeaveChange">
<Option :value="0">未离职</Option> <Option :value="0">未离职</Option>
<Option :value="1">离职</Option> <Option :value="1">离职</Option>
</Select> </Select>
</FormItem> </FormItem>
<FormItem v-if="editModal.form.is_leave === 1" label="离职时间">
<Input v-model="editModal.form.leave_time" type="datetime" placeholder="请选择离职时间" format="yyyy-MM-dd HH:mm:ss" disabled />
</FormItem>
</Form> </Form>
<div slot="footer"> <div slot="footer">
<Button @click="editModal.visible = false">取消</Button> <Button @click="editModal.visible = false">取消</Button>
...@@ -127,6 +130,52 @@ export default { ...@@ -127,6 +130,52 @@ export default {
renderIsExt (h, { row }) { renderIsExt (h, { row }) {
return row.is_ext === 1 ? '系统同步' : '手工录入' return row.is_ext === 1 ? '系统同步' : '手工录入'
}, },
formatLeaveTime (leaveTime) {
if (!leaveTime || leaveTime === null || leaveTime === '') return '-'
// 如果是数字时间戳
if (typeof leaveTime === 'number') {
return this.formatDateTime(new Date(leaveTime))
}
// 如果是字符串
if (typeof leaveTime === 'string') {
// 处理纯数字字符串(可能是时间戳)
if (/^\d+$/.test(leaveTime)) {
try {
return this.formatDateTime(new Date(Number(leaveTime)))
} catch (e) {
return leaveTime
}
}
// 处理带T的ISO字符串或其他可解析字符串
if (leaveTime.includes('T')) {
return this.formatDateTime(leaveTime)
}
// 尝试直接解析
const parsed = new Date(leaveTime)
if (!isNaN(parsed.getTime())) {
return this.formatDateTime(parsed)
}
}
// 尝试解析为Date对象
const parsed = new Date(leaveTime)
if (!isNaN(parsed.getTime())) {
return this.formatDateTime(parsed)
}
return leaveTime
},
formatDateTime (date) {
if (!date) return '-'
const d = date instanceof Date ? date : new Date(date)
if (isNaN(d.getTime())) return '-'
const pad = (n) => (n < 10 ? '0' + n : String(n))
return d.getFullYear() + '-' +
pad(d.getMonth() + 1) + '-' +
pad(d.getDate()) + ' ' +
pad(d.getHours()) + ':' +
pad(d.getMinutes()) + ':' +
pad(d.getSeconds())
},
fetchList () { fetchList () {
this.loading = true this.loading = true
const payload = Object.assign({}, { pageNo: this.pager.pageNo, pageSize: this.pager.pageSize }, this.filters) const payload = Object.assign({}, { pageNo: this.pager.pageNo, pageSize: this.pager.pageSize }, this.filters)
...@@ -195,12 +244,25 @@ export default { ...@@ -195,12 +244,25 @@ export default {
// 直接拷贝记录用于编辑,并保证小写 id 可用 // 直接拷贝记录用于编辑,并保证小写 id 可用
const copy = Object.assign({}, row) const copy = Object.assign({}, row)
if (copy.Id != null && copy.id == null) copy.id = copy.Id if (copy.Id != null && copy.id == null) copy.id = copy.Id
// 保存原始离职时间用于提交(保持后端原始格式),并将 leave_time 转为供前端显示的格式化字符串(disabled Input)
copy._raw_leave_time = copy.leave_time
copy.leave_time = this.formatLeaveTime(copy.leave_time)
this.editModal.form = copy this.editModal.form = copy
this.editModal.visible = true this.editModal.visible = true
}, },
selectLeader () { selectLeader () {
this.userSelectorVisible = true this.userSelectorVisible = true
}, },
onIsLeaveChange (value) {
// 当切换为未离职,清理离职时间的显示与临时原始值,避免在提交时带上旧值
if (value !== 1) {
if (this.editModal && this.editModal.form) {
// 保证字段存在再删除
if (this.editModal.form.leave_time !== undefined) delete this.editModal.form.leave_time
if (this.editModal.form._raw_leave_time !== undefined) delete this.editModal.form._raw_leave_time
}
}
},
handleLeaderSelected (user) { handleLeaderSelected (user) {
this.editModal.form.leader = user.id this.editModal.form.leader = user.id
this.editModal.form.leader_name = user.name this.editModal.form.leader_name = user.name
...@@ -210,8 +272,34 @@ export default { ...@@ -210,8 +272,34 @@ export default {
saveEdit () { saveEdit () {
this.$refs.editForm.validate(valid => { this.$refs.editForm.validate(valid => {
// no strict validation here, just save // no strict validation here, just save
const formData = Object.assign({}, this.editModal.form)
// 如果当前为未离职状态,不提交离职时间字段
if (formData.is_leave !== 1) {
if (formData.leave_time !== undefined) delete formData.leave_time
if (formData._raw_leave_time !== undefined) delete formData._raw_leave_time
} else {
// is_leave === 1 时按原逻辑处理离职时间
if (formData._raw_leave_time !== undefined) {
formData.leave_time = formData._raw_leave_time
} else if (formData.leave_time && typeof formData.leave_time === 'string') {
// 纯数字字符串(时间戳)
if (/^\d+$/.test(formData.leave_time)) {
formData.leave_time = Number(formData.leave_time)
} else {
// 尝试将常见格式 yyyy-MM-dd HH:mm:ss 转为 ISO 再解析
const parsed = new Date(formData.leave_time.replace(' ', 'T'))
if (!isNaN(parsed.getTime())) {
formData.leave_time = parsed.getTime()
}
}
} else if (formData.leave_time instanceof Date) {
formData.leave_time = formData.leave_time.getTime()
}
// 清理临时字段
if (formData._raw_leave_time !== undefined) delete formData._raw_leave_time
}
this.editModal.saving = true this.editModal.saving = true
saveDmUser(this.editModal.form).then(ret => { saveDmUser(formData).then(ret => {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功') this.$Message.success('保存成功')
this.editModal.visible = false this.editModal.visible = false
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论