Commit e6fdd1fc by yubin

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/view/key-person/key_dm_leave/index.vue
parents 8a78816c ff3b6f3b
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
> >
<Button icon="ios-cloud-upload-outline">上传图片</Button> <Button icon="ios-cloud-upload-outline">上传图片</Button>
</Upload> </Upload>
</Upload> <!-- </Upload> -->
<!-- <div class="upload-tips">支持多张图片上传,单张图片不超过5MB</div> <!-- <div class="upload-tips">支持多张图片上传,单张图片不超过5MB</div>
<div v-if="visitModal.form.visit_img_list.length" class="upload-preview"> <div v-if="visitModal.form.visit_img_list.length" class="upload-preview">
<div <div
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,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 label="办公用品待审核" name="pending"> <TabPane label="办公用品待审核" name="pending" v-if="power.supply_approval">
<Table :data="tables.pending" :loading="loading.pending" :columns="pendingColumns" border> <Table :data="tables.pending" :loading="loading.pending" :columns="pendingColumns" border>
<template slot="action" slot-scope="{ row }"> <template slot="action" slot-scope="{ row }">
<Button size="small" type="primary" @click="openApproveModal(row)">处理</Button> <Button size="small" type="primary" @click="openApproveModal(row)">处理</Button>
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
show-total show-sizer @on-change="pageChange('pending', $event)" @on-page-size-change="sizeChange('pending', $event)" /> show-total show-sizer @on-change="pageChange('pending', $event)" @on-page-size-change="sizeChange('pending', $event)" />
</TabPane> </TabPane>
<TabPane label="办公用品审核历史查询" name="history"> <TabPane label="办公用品审核历史查询" name="history" v-if="power.supply_view">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="18"> <Col span="18">
...@@ -158,7 +158,7 @@ ...@@ -158,7 +158,7 @@
show-total show-sizer @on-change="pageChange('history', $event)" @on-page-size-change="sizeChange('history', $event)" /> show-total show-sizer @on-change="pageChange('history', $event)" @on-page-size-change="sizeChange('history', $event)" />
</TabPane> </TabPane>
<TabPane label="办公用品入库" name="inbound"> <TabPane label="办公用品入库" name="inbound" v-if="power.inventory_manager">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="18"> <Col span="18">
...@@ -246,7 +246,7 @@ ...@@ -246,7 +246,7 @@
show-total show-sizer @on-change="pageChange('inbound', $event)" @on-page-size-change="sizeChange('inbound', $event)" /> show-total show-sizer @on-change="pageChange('inbound', $event)" @on-page-size-change="sizeChange('inbound', $event)" />
</TabPane> </TabPane>
<TabPane label="办公用品归还" name="return"> <TabPane label="办公用品归还" name="return" v-if="power.inventory_manager">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="18"> <Col span="18">
...@@ -280,7 +280,7 @@ ...@@ -280,7 +280,7 @@
show-total show-sizer @on-change="pageChange('return', $event)" @on-page-size-change="sizeChange('return', $event)" /> show-total show-sizer @on-change="pageChange('return', $event)" @on-page-size-change="sizeChange('return', $event)" />
</TabPane> </TabPane>
<TabPane label="库存查询" name="inventory"> <TabPane label="库存查询" name="inventory" v-if="power.inventory_manager">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="18"> <Col span="18">
...@@ -424,12 +424,12 @@ ...@@ -424,12 +424,12 @@
<h4>明细(从物料库选择) <h4>明细(从物料库选择)
<div style="float: right;"> <div style="float: right;">
<Button size="small" class="mr5" type="primary" @click="showMaterialSelector = true">添加</Button> <Button size="small" class="mr5" type="primary" @click="showInboundMaterialSelector = true">添加</Button>
<Button size="small" type="error" @click="deleteSelectedInboundDetails">删除</Button> <Button size="small" type="error" @click="deleteSelectedInboundDetails">删除</Button>
</div> </div>
</h4> </h4>
<Table :data="inboundModal.details" :columns="inboundDetailColumns" size="small" border @on-selection-change="onInboundDetailSelectionChange" style="width: 100%" /> <Table :data="inboundModal.details" :columns="inboundDetailColumns" size="small" border @on-selection-change="onInboundDetailSelectionChange" style="width: 100%" />
<MaterialSelector v-model="showMaterialSelector" :selected="[]" @on-ok="handleInboundMaterialSelectorOk" @cancel="showMaterialSelector = false" /> <MaterialSelector v-model="showInboundMaterialSelector" :selected="[]" @on-ok="handleInboundMaterialSelectorOk" @cancel="showInboundMaterialSelector = false" />
</Form> </Form>
<div slot="footer"> <div slot="footer">
<Button @click="inboundModal.visible=false">取消</Button> <Button @click="inboundModal.visible=false">取消</Button>
...@@ -544,7 +544,8 @@ import { ...@@ -544,7 +544,8 @@ import {
getInventoryList, getInventoryList,
getInboundById, getInboundById,
getPendingReturnById, getPendingReturnById,
importInbound importInbound,
getUserDmPermissionList
} from '@/api/key-dm' } from '@/api/key-dm'
import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue' import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue'
import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js' import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js'
...@@ -587,7 +588,6 @@ export default { ...@@ -587,7 +588,6 @@ export default {
editingCellField: '', editingCellField: '',
// 审批状态映射字典 // 审批状态映射字典
approvalStatusMap: { '0': '待提交', '1': '审核中', '9': '审核通过', '-1': '驳回' }, approvalStatusMap: { '0': '待提交', '1': '审核中', '9': '审核通过', '-1': '驳回' },
opTypeMap: { '1': '入库', '2': '出库' },
activeTab: 'apply', activeTab: 'apply',
filters: { filters: {
apply: { application_no: '', applicant_name: '', approval_status: null, startDate: null, endDate: null }, apply: { application_no: '', applicant_name: '', approval_status: null, startDate: null, endDate: null },
...@@ -792,7 +792,13 @@ export default { ...@@ -792,7 +792,13 @@ export default {
{ title: '物料名称', key: 'material_name' }, { title: '物料名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' }, { title: '申请数量', key: 'apply_quantity' },
{ title: '单位', key: 'unit' }, { title: '单位', key: 'unit' },
{ title: '可用库存', key: 'available_quantity' } {
title: '可用库存',
key: 'available_quantity',
render: (h, { row }) => {
return h('span', row.available_quantity || 0)
}
}
], ],
detailDetailColumns: [ detailDetailColumns: [
{ title: '物料编码', key: 'material_code' }, { title: '物料编码', key: 'material_code' },
...@@ -973,6 +979,7 @@ export default { ...@@ -973,6 +979,7 @@ export default {
], ],
// 选择器控制与已选明细 // 选择器控制与已选明细
showMaterialSelector: false, showMaterialSelector: false,
showInboundMaterialSelector: false,
applySelectedDetails: [], applySelectedDetails: [],
applyModal: { visible: false, isEdit: false, saving: false, form: {}, details: [], isEditing: false }, applyModal: { visible: false, isEdit: false, saving: false, form: {}, details: [], isEditing: false },
approveModal: { visible: false, record: {}, details: [], opinion: '', submitting: false }, approveModal: { visible: false, record: {}, details: [], opinion: '', submitting: false },
...@@ -987,14 +994,38 @@ export default { ...@@ -987,14 +994,38 @@ export default {
inboundSelectedDetails: [], inboundSelectedDetails: [],
inboundModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] }, inboundModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] },
returnModal: { visible: false, record: {}, details: [], saving: false }, returnModal: { visible: false, record: {}, details: [], saving: false },
inboundDetailModal: { visible: false, loading: false, data: {}, details: [], logs: [] } inboundDetailModal: { visible: false, loading: false, data: {}, details: [], logs: [] },
power: {
leave_approval: false, // 请假审核
leave_view: false, // 请假查询(统计)
supply_approval: false, // 用品申领审核
supply_view: false, // 用品查询(统计)
inventory_manager: false // 库存管理
}
} }
}, },
created () { created () {
this.fetchList('apply') this.fetchList('apply')
this.fetchApproverList() this.fetchApproverList()
this.getUserDmPermission()
}, },
methods: { methods: {
getUserDmPermission () {
getUserDmPermissionList({}).then(ret => {
console.log('ret', ret)
if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || []
for (let i = 0; i < data.length; i++) {
var ele = data[i]
if (this.power.hasOwnProperty(ele.code)) {
this.power[ele.code] = true
}
}
} else {
this.$Notice.error({ title: '查询失败', desc: ret.data.errmsg || '请稍后重试' })
}
})
},
// 新增:获取审批人列表 // 新增:获取审批人列表
async fetchApproverList () { async fetchApproverList () {
await getSupplyApproval().then(ret => { await getSupplyApproval().then(ret => {
...@@ -1201,6 +1232,7 @@ export default { ...@@ -1201,6 +1232,7 @@ export default {
return return
} }
selectedRows.forEach(sel => { selectedRows.forEach(sel => {
console.log(sel)
const code = sel.material_code const code = sel.material_code
const exist = this.applyModal.details.find(d => d.material_code === code) const exist = this.applyModal.details.find(d => d.material_code === code)
if (exist) { if (exist) {
...@@ -1282,10 +1314,12 @@ export default { ...@@ -1282,10 +1314,12 @@ export default {
return (row.approval_status === 1 && row.applicant_id === userId) return (row.approval_status === 1 && row.applicant_id === userId)
}, },
submit (row) { submit (row) {
console.log(row)
// 暂存当前申请ID // 暂存当前申请ID
this.approverModal.currentBorrowId = row.id this.approverModal.currentBorrowId = row.id
// 清空上次选择的审批人 // 清空上次选择的审批人
this.approverModal.form.approver_id = '' this.approverModal.form.approver_id = ''
this.approverModal.form.approver_id = row.approver_id
// 获取审批人列表 // 获取审批人列表
this.fetchApproverList() this.fetchApproverList()
// 打开审批人选择弹窗 // 打开审批人选择弹窗
...@@ -1295,7 +1329,6 @@ export default { ...@@ -1295,7 +1329,6 @@ export default {
// 新增:确认选择审批人后提交 // 新增:确认选择审批人后提交
confirmSubmitWithApprover () { confirmSubmitWithApprover () {
const approverId = this.approverModal.form.approver_id const approverId = this.approverModal.form.approver_id
this.approverModal.submitting = true this.approverModal.submitting = true
// 调用提交接口,携带审批人ID(需后端接口支持) // 调用提交接口,携带审批人ID(需后端接口支持)
submitBorrow({ submitBorrow({
...@@ -1426,13 +1459,6 @@ export default { ...@@ -1426,13 +1459,6 @@ export default {
}) })
} }
}, },
getTodayDate () {
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
openInboundModal () { openInboundModal () {
this.inboundModal.isEdit = false this.inboundModal.isEdit = false
this.inboundModal.form = { inbound_no: '', batch_no: '', inbound_date: this.getTodayDate(), inbound_type: 1, storage_location: '', remark: '' } this.inboundModal.form = { inbound_no: '', batch_no: '', inbound_date: this.getTodayDate(), inbound_type: 1, storage_location: '', remark: '' }
...@@ -1464,7 +1490,7 @@ export default { ...@@ -1464,7 +1490,7 @@ export default {
}) })
} }
}) })
this.showMaterialSelector = false this.showInboundMaterialSelector = false
}, },
deleteSelectedInboundDetails () { deleteSelectedInboundDetails () {
if (!this.inboundSelectedDetails || this.inboundSelectedDetails.length === 0) { if (!this.inboundSelectedDetails || this.inboundSelectedDetails.length === 0) {
...@@ -1534,7 +1560,7 @@ export default { ...@@ -1534,7 +1560,7 @@ export default {
} else { } else {
this.$Notice.error({ this.$Notice.error({
title: '保存失败', title: '保存失败',
desc: ret.data && ret.data.errmsg || '未知错误' desc: ret.data & ret.data.errmsg || '未知错误'
}) })
} }
}).catch(error => { }).catch(error => {
......
...@@ -28,9 +28,7 @@ ...@@ -28,9 +28,7 @@
<template slot="action" slot-scope="{ row }"> <template slot="action" slot-scope="{ row }">
<Button size="small" class="mr10" @click="openDetail(row)">详细</Button> <Button size="small" class="mr10" @click="openDetail(row)">详细</Button>
<Button size="small" type="primary" class="mr10" @click="openEdit(row)" v-if="canEdit(row)">修改</Button> <Button size="small" type="primary" class="mr10" @click="openEdit(row)" v-if="canEdit(row)">修改</Button>
<Poptip confirm title="确认提交此请假申请进入审批流程?" transfer @on-ok="submit(row)" v-if="canSubmit(row)"> <Button size="small" type="success" class="mr10" @click="submit(row)" v-if="canSubmit(row)">提交</Button>
<Button size="small" type="success" class="mr10">提交</Button>
</Poptip>
<Poptip confirm title="确认删除?" transfer @on-ok="deleteApply(row)" v-if="canDelete(row)"> <Poptip confirm title="确认删除?" transfer @on-ok="deleteApply(row)" v-if="canDelete(row)">
<Button size="small" type="error" class="mr10">删除</Button> <Button size="small" type="error" class="mr10">删除</Button>
</Poptip> </Poptip>
...@@ -44,7 +42,7 @@ ...@@ -44,7 +42,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 :label="'请假待审核'" name="pending" v-if="power.leave_approval"> <TabPane :label="'请假待审核'" name="pending">
<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,7 +54,7 @@ ...@@ -56,7 +54,7 @@
show-total show-sizer @on-change="pageChange('pending', $event)" @on-page-size-change="sizeChange('pending', $event)" /> show-total show-sizer @on-change="pageChange('pending', $event)" @on-page-size-change="sizeChange('pending', $event)" />
</TabPane> </TabPane>
<TabPane label="审核历史查询" name="history" v-if="power.leave_view"> <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="18"> <Col span="18">
...@@ -64,8 +62,10 @@ ...@@ -64,8 +62,10 @@
<DatePicker v-model="filters.history.start_time" type="date" placeholder="开始日期" style="width: 200px" class="mr10" /> <DatePicker v-model="filters.history.start_time" type="date" placeholder="开始日期" style="width: 200px" class="mr10" />
<span>结束:</span> <span>结束:</span>
<DatePicker v-model="filters.history.end_time" type="date" placeholder="结束日期" style="width: 200px" class="mr10" /> <DatePicker v-model="filters.history.end_time" type="date" placeholder="结束日期" style="width: 200px" class="mr10" />
<span>审批人:</span> <span>状态:</span>
<Input v-model="filters.history.approver_name" placeholder="请输入审批人姓名" style="width: 200px" /> <Select v-model="filters.history.status" style="width: 200px">
<Option v-for="opt in statusOptionsFor('history')" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select>
</Col> </Col>
<Col span="6" class="text-right"> <Col span="6" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('history')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('history')">搜索</Button>
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
show-total show-sizer @on-change="pageChange('history', $event)" @on-page-size-change="sizeChange('history', $event)" /> show-total show-sizer @on-change="pageChange('history', $event)" @on-page-size-change="sizeChange('history', $event)" />
</TabPane> </TabPane>
<TabPane label="请假申请查询" name="query" v-if="power.leave_view"> <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="18"> <Col span="18">
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
show-total show-sizer @on-change="pageChange('query', $event)" @on-page-size-change="sizeChange('query', $event)" /> show-total show-sizer @on-change="pageChange('query', $event)" @on-page-size-change="sizeChange('query', $event)" />
</TabPane> </TabPane>
<TabPane label="请假统计" name="stats" v-if="power.leave_view"> <TabPane label="请假统计" name="stats">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col span="18"> <Col span="18">
...@@ -156,7 +156,7 @@ ...@@ -156,7 +156,7 @@
<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">
<Select v-if="leaveApprovalOptions.length > 0" v-model="applyModal.form.approver_id" style="width: 60%" filterable> <Select v-if="leaveApprovalOptions.length > 0" v-model="applyModal.form.approver_id" style="width: 60%">
<Option v-for="opt in leaveApprovalOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option> <Option v-for="opt in leaveApprovalOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select> </Select>
<span v-else style="color: #999; font-style: italic;">请先进行审批人配置</span> <span v-else style="color: #999; font-style: italic;">请先进行审批人配置</span>
...@@ -180,9 +180,6 @@ ...@@ -180,9 +180,6 @@
<FormItem label="起止时间"> <FormItem label="起止时间">
<span>{{ formatDatetime(approveModal.record.start_time) }} - {{ formatDatetime(approveModal.record.end_time) }}</span> <span>{{ formatDatetime(approveModal.record.start_time) }} - {{ formatDatetime(approveModal.record.end_time) }}</span>
</FormItem> </FormItem>
<FormItem label="请假时长(天)">
<span>{{ approveModal.record.duration || '-' }}</span>
</FormItem>
<FormItem label="请假事由"> <FormItem label="请假事由">
<span>{{ approveModal.record.reason }}</span> <span>{{ approveModal.record.reason }}</span>
</FormItem> </FormItem>
...@@ -206,7 +203,7 @@ ...@@ -206,7 +203,7 @@
<Checkbox v-model="approveModal.transferEnabled">转审核</Checkbox> <Checkbox v-model="approveModal.transferEnabled">转审核</Checkbox>
</FormItem> </FormItem>
<FormItem v-if="approveModal.transferEnabled" label="选择审批人" prop="transferApprover"> <FormItem v-if="approveModal.transferEnabled" label="选择审批人" prop="transferApprover">
<Select v-if="leaveApprovalOptions.length > 0" v-model="approveModal.transferApprover" style="width: 60%" placeholder="请选择审批人" filterable> <Select v-if="leaveApprovalOptions.length > 0" v-model="approveModal.transferApprover" style="width: 60%" placeholder="请选择审批人">
<Option v-for="opt in leaveApprovalOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option> <Option v-for="opt in leaveApprovalOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select> </Select>
<span v-else style="color: #999; font-style: italic;">请先进行审批人配置</span> <span v-else style="color: #999; font-style: italic;">请先进行审批人配置</span>
...@@ -238,7 +235,6 @@ ...@@ -238,7 +235,6 @@
</Row> </Row>
<Row class="mt8"><Col span="24"><p><strong>请假类型:</strong>{{ detailModal.data.leave_type_name || '-' }}</p></Col></Row> <Row class="mt8"><Col span="24"><p><strong>请假类型:</strong>{{ detailModal.data.leave_type_name || '-' }}</p></Col></Row>
<Row class="mt8"><Col span="24"><p><strong>起止时间:</strong>{{ formatDatetime(detailModal.data.start_time) }} - {{ formatDatetime(detailModal.data.end_time) }}</p></Col></Row> <Row class="mt8"><Col span="24"><p><strong>起止时间:</strong>{{ formatDatetime(detailModal.data.start_time) }} - {{ formatDatetime(detailModal.data.end_time) }}</p></Col></Row>
<Row class="mt8"><Col span="24"><p><strong>请假时长(天):</strong>{{ detailModal.data.duration || '-' }}</p></Col></Row>
<Row class="mt8"><Col span="24"><p><strong>请假事由:</strong>{{ detailModal.data.reason || '-' }}</p></Col></Row> <Row class="mt8"><Col span="24"><p><strong>请假事由:</strong>{{ detailModal.data.reason || '-' }}</p></Col></Row>
<Row class="mt8"><Col span="24"><p><strong>状态:</strong>{{ mapStatusText(detailModal.data.status) }}</p></Col></Row> <Row class="mt8"><Col span="24"><p><strong>状态:</strong>{{ mapStatusText(detailModal.data.status) }}</p></Col></Row>
<Row v-if="detailModal.data.status === -1 || String(detailModal.data.status) === '-1'" class="mt8"><Col span="24"><p><strong>驳回理由:</strong>{{ detailModal.data.back_reason || detailModal.data.backReason || '-' }}</p></Col></Row> <Row v-if="detailModal.data.status === -1 || String(detailModal.data.status) === '-1'" class="mt8"><Col span="24"><p><strong>驳回理由:</strong>{{ detailModal.data.back_reason || detailModal.data.backReason || '-' }}</p></Col></Row>
...@@ -286,7 +282,6 @@ import { ...@@ -286,7 +282,6 @@ import {
getLeaveById, getLeaveById,
getLeaveTypeList, getLeaveTypeList,
deleteLeaveById, deleteLeaveById,
getUserDmPermissionList,
selectTransferApprovalList, selectTransferApprovalList,
transferLeaveApproval, transferLeaveApproval,
getLeaveApprovalPermission getLeaveApprovalPermission
...@@ -298,7 +293,7 @@ export default { ...@@ -298,7 +293,7 @@ export default {
data () { data () {
return { return {
activeTab: 'apply', activeTab: 'apply',
filters: { apply: { start_time: null, end_time: null, status: '' }, history: { start_time: null, end_time: null, approver_id: '' }, query: { start_time: null, end_time: null, status: '' } }, filters: { apply: { start_time: null, end_time: null, status: '' }, history: { start_time: null, end_time: null, status: '' }, query: { start_time: null, end_time: null, status: '' } },
// 下拉:请假审核权限可选人员 // 下拉:请假审核权限可选人员
leaveApprovalOptions: [], leaveApprovalOptions: [],
// 下拉:转审核审批人列表 // 下拉:转审核审批人列表
...@@ -341,16 +336,14 @@ export default { ...@@ -341,16 +336,14 @@ export default {
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '申请人', key: 'user_name', align: 'center' }, { title: '申请人', key: 'user_name', align: 'center' },
{ title: '请假类型', key: 'leave_type_name', align: 'center' }, { title: '请假类型', key: 'leave_type_name', align: 'center' },
{ title: '起止时间', key: 'start_time', align: 'center', width: 300, render: (h, { row }) => h('span', `${row.start_time || '-'} ~ ${row.end_time || '-'}`) }, { title: '起止时间', key: 'start_time', align: 'center', render: (h, { row }) => h('span', `${row.start_time || '-'} ~ ${row.end_time || '-'}`) },
{ title: '审批完成时间', key: 'approval_complete_time', align: 'center' }, { title: '审批完成时间', key: 'approval_complete_time', align: 'center' },
{ title: '处理结果', key: 'op_result', align: 'center', render: (h, { row }) => h('span', this.renderApproveResult(row.op_result)) },
{ title: '操作', slot: 'action', align: 'center', width: 100 } { title: '操作', slot: 'action', align: 'center', width: 100 }
], ],
queryColumns: [ queryColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '申请人', key: 'user_name', align: 'center' }, { title: '申请人', key: 'user_name', 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: '提交时间', key: 'submit_time', align: 'center' }, { title: '提交时间', key: 'submit_time', align: 'center' },
{ title: '操作', slot: 'action', align: 'center', width: 100 } { title: '操作', slot: 'action', align: 'center', width: 100 }
], ],
...@@ -385,43 +378,78 @@ export default { ...@@ -385,43 +378,78 @@ export default {
} }
], ],
applyModal: { visible: false, isEdit: false, saving: false, form: {} }, applyModal: { visible: false, isEdit: false, saving: false, form: {} },
// NOTE: 自动计算时长逻辑已移除,保留字段移除 // 控制是否在赋值时触发自动计算(true = 允许计算;false = 赋值时不计算)
suppressDurationCalc: false,
approveModal: { visible: false, record: {}, comment: '', submitting: false, transferEnabled: false, transferApprover: '', approvalFlow: [] }, approveModal: { visible: false, record: {}, comment: '', submitting: false, transferEnabled: false, transferApprover: '', approvalFlow: [] },
transferModal: { visible: false, selectedApprover: '', comment: '', processing: false, record: {} }, transferModal: { visible: false, selectedApprover: '', comment: '', processing: false, record: {} },
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: '',
power: {
leave_approval: false, // 请假审核
leave_view: false, // 请假查询(统计)
supply_approval: false, // 用品申领审核
supply_view: false, // 用品查询(统计)
inventory_manager: false // 库存管理
},
// 表单验证规则 // 表单验证规则
applyRules: { applyRules: {
leave_type_id: [ leave_type_id: [
{ required: true, message: '请选择请假类型', trigger: 'input' } { required: true, message: '请选择请假类型', trigger: 'change' }
], ],
start_time: [ start_time: [
{ required: true, message: '请选择开始时间', trigger: 'input', type: 'date' } { required: true, message: '请选择开始时间', trigger: 'change', type: 'date' }
], ],
end_time: [ end_time: [
{ required: true, message: '请选择结束时间', trigger: 'input', type: 'date' } { required: true, message: '请选择结束时间', trigger: 'change', type: 'date' }
], ],
duration: [ duration: [
{ {
required: true, validator: function (rule, value, callback) {
message: '请填写请假时长', const form = (this && this.applyModal && this.applyModal.form) ? this.applyModal.form : {}
trigger: 'input' const parseToDateLocal = (v) => {
}, if (v === null || v === undefined || v === '') return null
if (typeof v === 'number') return new Date(v)
if (typeof v === 'string') {
if (/^\d+$/.test(v)) return new Date(Number(v))
const s = v.includes('T') ? v : v.replace(' ', 'T')
const parsed = new Date(s)
return isNaN(parsed.getTime()) ? null : parsed
}
if (v instanceof Date) return isNaN(v.getTime()) ? null : v
const parsed = new Date(v)
return isNaN(parsed.getTime()) ? null : parsed
}
// 解析起止时间的整天差
const sd = parseToDateLocal(form.start_time)
const ed = parseToDateLocal(form.end_time)
let fullDays = 0
if (sd && ed) {
const diff = ed.getTime() - sd.getTime()
fullDays = Math.floor(diff / (1000 * 60 * 60 * 24))
}
// 如果不足整天,不校验(允许用户填写任意时长)
if (fullDays < 1) { callback(); return }
// 整天或以上时,必须填写且整数部分需与计算天数一致
if (value === null || value === undefined || String(value).trim() === '') {
callback(new Error('请填写请假时长')); return
}
const num = Number(value)
if (isNaN(num) || num <= 0) { callback(new Error('请假天数必须为大于 0 的数字')); return }
const integerPart = Math.floor(num)
if (integerPart !== fullDays) {
callback(new Error(`请假整数天应为 ${fullDays} 天,请确认`)); return
}
callback()
},
trigger: 'blur'
}
], ],
approver_id: [ approver_id: [
{ required: true, message: '请选择审批人', trigger: 'input' } { required: true, message: '请选择审批人', trigger: 'change' }
], ],
reason: [ reason: [
{ required: true, message: '请填写请假事由', trigger: 'input' } { required: true, message: '请填写请假事由', trigger: 'change' }
], ],
emergency_phone: [ emergency_phone: [
{ message: '请输入紧急电话', trigger: 'blur' }, { message: '请输入紧急电话', trigger: 'blur' },
...@@ -430,7 +458,7 @@ export default { ...@@ -430,7 +458,7 @@ export default {
message: '请输入有效的电话号码', message: '请输入有效的电话号码',
trigger: 'blur' trigger: 'blur'
} }
], ]
} }
} }
}, },
...@@ -440,11 +468,23 @@ export default { ...@@ -440,11 +468,23 @@ export default {
this.loadLeaveApprovalOptions() this.loadLeaveApprovalOptions()
// 加载待审批计数,用于页面顶部/选项卡徽章显示 // 加载待审批计数,用于页面顶部/选项卡徽章显示
this.loadPendingCount() this.loadPendingCount()
// 已移除自动计算时长,保留表单规则在 data 中定义(不在 created 中覆盖) // 将 duration 的 validator 绑定到组件实例的方法,确保内部能访问 this.applyModal.form
this.getUserDmPermission() this.applyRules.duration = [{ validator: this.validateDuration, trigger: 'blur' }]
}, },
watch: { watch: {
// 自动计算时长逻辑已移除:开始/结束时间变化不再自动修改 duration 字段 // 监听开始时间和结束时间变化,自动计算天数
'applyModal.form.start_time' (newVal) {
if (this.suppressDurationCalc) return
// 用户修改起始时间时,先清空已有时长(避免与新时间不符),再进行自动计算
if (this.applyModal && this.applyModal.form) this.applyModal.form.duration = ''
this.calculateDuration()
},
'applyModal.form.end_time' (newVal) {
if (this.suppressDurationCalc) return
// 用户修改结束时间时,先清空已有时长(避免与新时间不符),再进行自动计算
if (this.applyModal && this.applyModal.form) this.applyModal.form.duration = ''
this.calculateDuration()
},
// 当弹窗关闭时清理选择的审批人,确保下次打开时下拉框能正确刷新显示 // 当弹窗关闭时清理选择的审批人,确保下次打开时下拉框能正确刷新显示
'applyModal.visible' (val) { 'applyModal.visible' (val) {
if (!val && this.applyModal && this.applyModal.form) { if (!val && this.applyModal && this.applyModal.form) {
...@@ -472,22 +512,7 @@ export default { ...@@ -472,22 +512,7 @@ export default {
} }
}, },
methods: { methods: {
getUserDmPermission () { // validator 方法:确保能通过 this 访问组件数据
getUserDmPermissionList({}).then(ret => {
console.log('ret', ret)
if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || []
for (let i = 0; i < data.length; i++) {
var ele = data[i]
if (this.power.hasOwnProperty(ele.code)) {
this.power[ele.code] = true
}
}
} else {
this.$Notice.error({ title: '查询失败', desc: ret.data.errmsg || '请稍后重试' })
}
})
},
validateDuration (rule, value, callback) { validateDuration (rule, value, callback) {
const form = this.applyModal && this.applyModal.form ? this.applyModal.form : {} const form = this.applyModal && this.applyModal.form ? this.applyModal.form : {}
const parseToDateLocal = (v) => { const parseToDateLocal = (v) => {
...@@ -535,13 +560,36 @@ export default { ...@@ -535,13 +560,36 @@ export default {
// 过滤掉 id 为 '0' 或 0 的未提交选项 // 过滤掉 id 为 '0' 或 0 的未提交选项
return (this.statusOptions || []).filter(opt => String(opt.id) !== '0') return (this.statusOptions || []).filter(opt => String(opt.id) !== '0')
}, },
// 自动计算请假时长逻辑已移除,duration 由用户手动填写/后端计算 // 计算请假天数(只计算整天,忽略零点几部分)
calculateDuration () {
const form = this.applyModal.form
if (!form || !form.start_time || !form.end_time) return
const startDate = new Date(form.start_time)
const endDate = new Date(form.end_time)
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) return
if (endDate.getTime() <= startDate.getTime()) return
// 计算整天数(向下取整),只要整天 >=1 则自动填充为整数天
const diffTime = endDate.getTime() - startDate.getTime()
const fullDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))
const existing = form.duration !== null && form.duration !== undefined && String(form.duration).trim() !== ''
if (fullDays >= 1) {
// 只有当表单中尚未填写时才自动填充,避免覆盖后端/用户已有值
if (!existing) form.duration = String(fullDays)
} else {
// 少于整天时不自动计算,交由用户手动填写(例如半天、几小时)
// 不覆盖已有用户填写的值
if (!existing) form.duration = ''
}
},
handleTabChange (name) { handleTabChange (name) {
this.activeTab = name this.activeTab = name
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: getPendingLeaveList, history: getLeaveApprovalHistory, query: getLeaveList } const apiMap = { apply: getLeaveListByUserId, pending: getPendingLeaveList, history: getLeaveApprovalHistory, query: getLeaveList }
...@@ -701,15 +749,7 @@ export default { ...@@ -701,15 +749,7 @@ export default {
return String(status) return String(status)
}, },
handleSearch (tab) { (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) }, handleSearch (tab) { (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
handleReset (tab) { handleReset (tab) { this.filters[tab] = {}; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
if (tab === 'history') {
this.filters.history = { start_time: null, end_time: null, approver_id: '' }
} else {
this.filters[tab] = {}
}
(this.pagers[tab] || {}).pageNo = 1
this.fetchList(tab)
},
pageChange (tab, pageNo) { (this.pagers[tab] || {}).pageNo = pageNo; this.fetchList(tab) }, pageChange (tab, pageNo) { (this.pagers[tab] || {}).pageNo = pageNo; this.fetchList(tab) },
sizeChange (tab, size) { (this.pagers[tab] || {}).pageSize = size; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) }, sizeChange (tab, size) { (this.pagers[tab] || {}).pageSize = size; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
loadLeaveTypes () { loadLeaveTypes () {
...@@ -815,14 +855,18 @@ export default { ...@@ -815,14 +855,18 @@ export default {
// 默认开始时间为当天(时分秒置为 0),精确到天 // 默认开始时间为当天(时分秒置为 0),精确到天
const today = new Date() const today = new Date()
today.setHours(0, 0, 0, 0) today.setHours(0, 0, 0, 0)
// 不再自动计算时长,表单由用户手动填写 duration // 在赋值期间禁止自动计算,直到下一个 tick 再恢复,避免渲染期间 watcher 覆盖表单值
this.suppressDurationCalc = true
this.applyModal.form = { user_id: '', user_name: '', leave_type_id: '', start_time: today, end_time: '', duration_unit: 2, duration: '', reason: '', emergency_contact: '', emergency_phone: '', approver_id: this.selectedApprovalUser || '' } this.applyModal.form = { user_id: '', user_name: '', leave_type_id: '', start_time: today, end_time: '', duration_unit: 2, duration: '', reason: '', emergency_contact: '', emergency_phone: '', approver_id: this.selectedApprovalUser || '' }
this.$nextTick(() => { this.suppressDurationCalc = false })
this.applyModal.visible = true this.applyModal.visible = true
}, },
openEdit (row) { openEdit (row) {
this.applyModal.isEdit = true this.applyModal.isEdit = true
// 编辑模式:直接将行数据赋值到表单,不再触发自动计算 // 在赋值期间禁止自动计算,直到渲染稳定后再恢复,避免覆盖已有 duration
this.suppressDurationCalc = true
this.applyModal.form = Object.assign({}, row) this.applyModal.form = Object.assign({}, row)
this.$nextTick(() => { this.suppressDurationCalc = false })
// ensure approver_id exists on form when editing // ensure approver_id exists on form when editing
if (!this.applyModal.form.approver_id) this.applyModal.form.approver_id = row.approver_id || row.approverId || row.transfer_to_id || '' if (!this.applyModal.form.approver_id) this.applyModal.form.approver_id = row.approver_id || row.approverId || row.transfer_to_id || ''
// 保证与 leaveApprovalOptions 中 id 的类型一致(字符串) // 保证与 leaveApprovalOptions 中 id 的类型一致(字符串)
...@@ -901,9 +945,13 @@ export default { ...@@ -901,9 +945,13 @@ export default {
return status === 0 return status === 0
}, },
submit (row) { submit (row) {
submitLeaveApplication({ id: row.id, leave_id: row.leave_id }).then(ret => { this.$Modal.confirm({ title: '确认提交',
if (ret.data && ret.data.errcode === 0) { this.$Message.success('提交成功'); this.fetchList('apply') } else this.$Notice.error({ title: '提交失败', desc: ret.data && ret.data.errmsg }) content: '确认提交此请假申请进入审批流程?',
}) onOk: () => {
submitLeaveApplication({ id: row.id, leave_id: row.leave_id }).then(ret => {
if (ret.data && ret.data.errcode === 0) { this.$Message.success('提交成功'); this.fetchList('apply') } else this.$Notice.error({ title: '提交失败', desc: ret.data && ret.data.errmsg })
})
} })
}, },
revoke (row) { revoke (row) {
revokeLeaveApplication({ id: row.id, leave_id: row.leave_id }).then(ret => { revokeLeaveApplication({ id: row.id, leave_id: row.leave_id }).then(ret => {
...@@ -1041,6 +1089,8 @@ export default { ...@@ -1041,6 +1089,8 @@ export default {
refillApply () { refillApply () {
// 将批准记录数据反显到申请表单,清除 id 和 leave_id // 将批准记录数据反显到申请表单,清除 id 和 leave_id
this.applyModal.isEdit = false this.applyModal.isEdit = false
// 在赋值期间禁止自动计算,直到渲染稳定后再恢复
this.suppressDurationCalc = true
this.applyModal.form = { this.applyModal.form = {
leave_type_id: this.approveModal.record.leave_type_id || '', leave_type_id: this.approveModal.record.leave_type_id || '',
start_time: this.approveModal.record.start_time || '', start_time: this.approveModal.record.start_time || '',
...@@ -1051,6 +1101,7 @@ export default { ...@@ -1051,6 +1101,7 @@ export default {
approver_id: this.approveModal.record.approver_id || this.selectedApprovalUser || '' approver_id: this.approveModal.record.approver_id || this.selectedApprovalUser || ''
} }
// 不保留 id 和 leave_id,保持为空 // 不保留 id 和 leave_id,保持为空
this.$nextTick(() => { this.suppressDurationCalc = false })
this.applyModal.visible = true this.applyModal.visible = true
// 关闭审批弹窗 // 关闭审批弹窗
this.approveModal.visible = false this.approveModal.visible = false
...@@ -1058,6 +1109,8 @@ export default { ...@@ -1058,6 +1109,8 @@ export default {
refillApplyDirect (row) { refillApplyDirect (row) {
// 直接从列表行数据进行重新填报,清除 id 和 leave_id // 直接从列表行数据进行重新填报,清除 id 和 leave_id
this.applyModal.isEdit = false this.applyModal.isEdit = false
// 在赋值期间禁止自动计算,直到渲染稳定后再恢复
this.suppressDurationCalc = true
this.applyModal.form = { this.applyModal.form = {
leave_type_id: row.leave_type_id || '', leave_type_id: row.leave_type_id || '',
start_time: row.start_time || '', start_time: row.start_time || '',
...@@ -1068,6 +1121,7 @@ export default { ...@@ -1068,6 +1121,7 @@ export default {
approver_id: row.approver_id || this.selectedApprovalUser || '' approver_id: row.approver_id || this.selectedApprovalUser || ''
} }
// 不保留 id 和 leave_id,保持为空 // 不保留 id 和 leave_id,保持为空
this.$nextTick(() => { this.suppressDurationCalc = false })
this.applyModal.visible = true this.applyModal.visible = true
}, },
openDetail (row) { openDetail (row) {
...@@ -1109,20 +1163,16 @@ export default { ...@@ -1109,20 +1163,16 @@ export default {
}).finally(() => { this.detailModal.loading = false }) }).finally(() => { this.detailModal.loading = false })
}, },
openHistoryDetail (row) { this.openDetail(row) }, openHistoryDetail (row) { this.openDetail(row) },
renderApproveResult (result) { renderApproveResult (h, { row }) { return row.approver_result === 1 ? '通过' : (row.approver_result === -1 ? '驳回' : '未处理') },
if (result === 1 || result === '1') return '通过'
if (result === -1 || result === '-1') return '驳回'
if (result === 2 || result === '2') return '转审'
return '未处理'
},
formatDatetime (val) { if (!val) return '-'; return String(val).replace('T', ' ') }, formatDatetime (val) { if (!val) return '-'; return String(val).replace('T', ' ') },
loadStats () { loadStats () {
this.loading.stats = true this.loading.stats = true
getLeaveStats({ const params = {
start: this.statsStart ? this.formatForDbDatetime(this.statsStart) : null, start: this.statsStart,
end: this.statsEnd ? this.formatForDbDatetime(this.statsEnd) : null, end: this.statsEnd,
department: this.statsDept department: this.statsDept
}).then(ret => { }
getLeaveStats({ params }).then(ret => {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
console.log('ret.data.data', ret.data.data) console.log('ret.data.data', ret.data.data)
this.tables.stats = ret.data.data || [] this.tables.stats = ret.data.data || []
...@@ -1132,10 +1182,10 @@ export default { ...@@ -1132,10 +1182,10 @@ export default {
}).finally(() => { this.loading.stats = false }) }).finally(() => { this.loading.stats = false })
}, },
resetStats () { resetStats () {
this.statsStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1) this.statsStart = null
this.statsEnd = new Date() this.statsEnd = null
this.statsDept = '' this.statsDept = ''
this.loadStats() this.tables.stats = []
}, },
deleteApply (row) { deleteApply (row) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论