Files
yudao-dev/src/views/group/Schedule/index.vue
2025-11-05 13:57:58 +08:00

602 lines
13 KiB
Vue

<!--
* @Author: zwq
* @Date: 2025-10-13 15:07:24
* @LastEditors: zwq
* @LastEditTime: 2025-11-05 08:51:13
* @Description:
-->
<template>
<div class="app-container">
<div class="searchBarBox">
<el-form
:inline="true"
ref="searchBarForm"
:model="formInline"
class="searchBar">
<span class="blue-block" />
<el-form-item label="计划编号" prop="code">
<el-input
v-model="formInline.code"
clearable
size="small"
placeholder="请输入计划编号" />
</el-form-item>
<el-form-item label="计划名称" prop="name">
<el-input
v-model="formInline.name"
clearable
size="small"
placeholder="请输入计划名称" />
</el-form-item>
<el-form-item label="开始时间" prop="startDay">
<el-date-picker
v-model="formInline.startDay"
size="small"
type="datetime"
placeholder="选择日期时间"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endDay">
<el-date-picker
v-model="formInline.endDay"
size="small"
type="datetime"
placeholder="选择日期时间"></el-date-picker>
</el-form-item>
<el-form-item label="部门" prop="deptId">
<dept-select
style="width: 200px"
ref="deptSelect"
@DeptId="setDeptId"></dept-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="formInline.status"
size="small"
clearable
placeholder="请选择状态">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="small"
v-hasPermi="['base:group-scheduling-plan:query']"
@click="buttonClick({ btnName: 'search' })">
查询
</el-button>
</el-form-item>
<el-form-item>
<span
class="separateStyle"
v-hasPermi="['base:group-scheduling-plan:query']"></span>
</el-form-item>
<el-form-item>
<el-button size="small" @click="buttonClick({ btnName: 'reset' })">
重置
</el-button>
</el-form-item>
<el-form-item>
<span
class="separateStyle"
v-hasPermi="['base:group-scheduling-plan:create']"></span>
</el-form-item>
<el-form-item>
<el-button
type="success"
size="small"
:plain="true"
v-hasPermi="['base:group-scheduling-plan:create']"
@click="buttonClick({ btnName: 'add' })">
新增
</el-button>
</el-form-item>
<el-form-item>
<el-button
type="warning"
plain
size="small"
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['base:group-scheduling-plan:export']">
导出
</el-button>
</el-form-item>
</el-form>
</div>
<base-table
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="tableData"
@emitFun="getDataList">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="270"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="addOrUpdateVisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
:destroy-on-close="true"
append-to-body
width="60%">
<add-or-update
ref="addOrUpdate"
@setSN="setStepNum"
@refreshDataList="successSubmit"></add-or-update>
<template #footer>
<slot name="footer">
<el-row slot="footer" type="flex" justify="end">
<el-col :span="24">
<el-button
v-if="stepNum > 1"
size="small"
class="btnTextStyle"
@click="handleConfirm('up')">
上一步
</el-button>
<el-button
size="small"
class="btnTextStyle"
@click="handleCancel">
取消
</el-button>
<el-button
v-if="stepNum == 3"
type="primary"
class="btnTextStyle"
size="small"
plain
@click="successSubmit">
保存草稿
</el-button>
<el-button
type="primary"
class="btnTextStyle"
size="small"
@click="handleConfirm">
{{ stepNum < 3 ? '下一步' : '确认并执行' }}
</el-button>
</el-col>
</el-row>
</slot>
</template>
</base-dialog>
<base-dialog
:dialogTitle="'排班计划详情'"
:dialogVisible="detailVisible"
@cancel="detailCancel"
:before-close="detailCancel"
:destroy-on-close="true"
append-to-body
width="50%">
<detail ref="detailRef"></detail>
<template #footer>
<slot name="footer">
<el-row slot="footer" type="flex" justify="end">
<el-col :span="24">
<el-button
size="small"
class="btnTextStyle"
@click="detailCancel">
取消
</el-button>
</el-col>
</el-row>
</slot>
</template>
</base-dialog>
</div>
</template>
<script>
import AddOrUpdate from './add-or-updata';
import deptSelect from './../deptSelect.vue';
import basicPage from '@/mixins/basic-page';
import subSpan from './subSpan.vue';
import subStatus from './subStatus.vue';
import detail from './detail.vue';
import { parseTime } from '@/filter/code-filter';
import {
getGroupPlanPage,
deleteGroupPlan,
copyPlan,
disablePlan,
updateScheduleLater,
exportExcel,
} from '@/api/group/Schedule';
const tableProps = [
{
prop: 'code',
label: '计划编号',
width: 140,
},
{
prop: 'name',
label: '计划名称',
width: 100,
},
{
prop: 'startDay',
label: '开始时间',
filter: parseTime,
width: 150,
},
{
prop: 'endDay',
label: '结束时间',
filter: parseTime,
width: 150,
},
{
prop: 'shiftType',
label: '倒班方式',
filter: (val) => {
return val ? ['', '长白班', '两班倒', '三班倒'][val] : '-';
},
width: 110,
},
{
prop: 'shiftSustainedNum',
label: '同班次连排',
width: 110,
subcomponent: subSpan,
},
{
prop: 'deptName',
label: '部门',
},
{
prop: 'status',
label: '计划状态',
width: 110,
subcomponent: subStatus,
},
{
prop: 'createTime',
label: '创建时间',
filter: parseTime,
width: 150,
},
];
export default {
mixins: [basicPage],
data() {
return {
urlOptions: {
getDataListURL: getGroupPlanPage,
deleteURL: deleteGroupPlan,
},
tableProps,
tableBtn: [
this.$auth.hasPermi('base:group-scheduling-plan:update')
? {
type: 'edit',
btnName: '编辑',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 1,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-plan:delete')
? {
type: 'delete',
btnName: '删除',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 1,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-plan:query')
? {
type: 'detail',
btnName: '查看',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'status',
value: 1,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-plan:delete')
? {
type: 'cancel',
btnName: '作废',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 2,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-holiday:update')
? {
type: 'sync',
btnName: '同步节假日',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 2,
},
{
type: 'equal',
name: 'updateFlag',
value: true,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-plan:create')
? {
type: 'copy',
btnName: '复制',
}
: undefined,
].filter((v) => v),
tableData: [],
options: [
{
value: '1',
label: '草稿',
},
{
value: '2',
label: '已确认',
},
{
value: '3',
label: '已作废',
},
],
formInline: {
code: '',
name: '',
startDay: '',
endDay: '',
deptId: '',
status: '',
},
stepNum: 1, // 新增编辑时当前第几步
detailVisible: false,
// 导出遮罩层
exportLoading: false,
};
},
components: {
AddOrUpdate,
deptSelect,
detail,
},
created() {},
methods: {
buttonClick(val) {
switch (val.btnName) {
case 'search':
const date1 = new Date(this.formInline.startDay).getTime();
const date2 = new Date(this.formInline.endDay).getTime();
if (date1 > date2) {
this.$message('开始时间不得晚于结束时间');
return;
}
this.listQuery = {
pageNo: 1,
pageSize: 10,
total: 1,
...this.formInline,
};
this.getDataList();
break;
case 'reset':
this.formInline.name = null;
this.formInline.code = null;
this.formInline.deptId = null;
this.$refs.deptSelect.clear();
this.formInline.status = null;
this.listQuery = {
pageSize: 10,
pageNo: 1,
total: 1,
};
this.getDataList();
break;
case 'add':
this.addOrEditTitle = '添加排班计划';
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init();
});
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
setDeptId(val) {
this.formInline.deptId = val;
},
setStepNum(val) {
this.stepNum = val;
},
successSubmit() {
this.addOrUpdateVisible = false;
this.addOrEditTitle = '';
this.stepNum = 1;
this.getDataList();
},
// dialog取消
handleCancel() {
this.$refs.addOrUpdate.cancelStep();
},
handleConfirm(val) {
if (val == 'up') {
this.$refs.addOrUpdate.upSubmit();
} else {
this.$refs.addOrUpdate.nextSubmit();
}
},
//tableBtn点击
handleClick(val) {
if (val.type === 'edit') {
this.addOrUpdateVisible = true;
this.addOrEditTitle = '编辑';
this.$nextTick(() => {
this.$refs.addOrUpdate.init(val.data.id);
});
} else if (val.type === 'delete') {
this.deleteHandle(val.data.id, val.data.name, val.data._pageIndex);
} else if (val.type === 'detail') {
this.detailVisible = true;
this.$nextTick(() => {
this.$refs.detailRef.init(val.data.id);
});
} else if (val.type === 'cancel') {
disablePlan(val.data.id).then((res) => {
this.$modal.msgSuccess('作废成功');
this.getDataList();
});
} else if (val.type === 'sync') {
updateScheduleLater({
planId: val.data.id,
logId: val.data.updateLogId,
}).then((res) => {
this.$modal.msgSuccess('同步节假日成功');
this.getDataList();
});
} else if (val.type === 'copy') {
copyPlan(val.data.id).then((res) => {
this.$modal.msgSuccess('复制成功');
this.getDataList();
});
}
},
detailCancel() {
this.detailVisible = false;
},
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.formInline };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal
.confirm('是否确认导出所有数据项?')
.then(() => {
this.exportLoading = true;
return exportExcel(params);
})
.then((response) => {
this.$download.excel(response, '排班计划.xls');
this.exportLoading = false;
})
.catch(() => {});
},
},
};
</script>
<style scope>
.searchBarBox {
width: 100%;
position: relative;
margin-bottom: 8px;
}
.searchBarBox::after {
content: '';
display: block;
clear: both;
}
.searchBar .blue-block {
display: inline-block;
float: left;
width: 4px;
height: 16px;
background-color: #0b58ff;
border-radius: 1px;
margin-right: 8px;
margin-top: 12px;
}
.searchBar .el-form-item {
margin-bottom: 4px;
}
.searchBar .separateStyle {
display: inline-block;
width: 1px;
height: 24px;
background: #e8e8e8;
vertical-align: middle;
}
.searchBar .vue-treeselect__control {
height: 32px !important;
line-height: 32px !important;
margin: 4px 0;
}
body .el-dialog__header {
font-size: 16px;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
padding: 13px 24px;
border-bottom: 1px solid #e9e9e9;
}
body .el-dialog__header .titleStyle::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background-color: #0b58ff;
border-radius: 1px;
margin-right: 8px;
position: relative;
top: 2px;
}
</style>