更新班组

This commit is contained in:
2025-10-19 00:38:48 +08:00
parent 6c46083d4a
commit 4e801873b9
23 changed files with 3332 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
<!--
* @Author: zwq
* @Date: 2023-08-01 15:27:31
* @LastEditors: zwq
* @LastEditTime: 2023-08-01 16:25:54
* @Description:
-->
<template>
<div :class="[className, { 'p-0': noPadding }]">
<slot />
</div>
</template>
<script>
export default {
props: {
size: {
// 取值范围: xl lg md sm
type: String,
default: 'de',
validator: function (val) {
return ['xl', 'lg', 'de', 'md', 'sm'].indexOf(val) !== -1;
},
},
noPadding: {
type: Boolean,
default: false,
},
},
computed: {
className: function () {
return `${this.size}-title`;
},
},
};
</script>
<style lang="scss" scoped>
$pxls: (xl, 28px) (lg, 24px) (de, 20px) (md, 18px) (sm, 16px);
$mgr: 8px;
@each $size, $height in $pxls {
.#{$size}-title {
font-size: $height;
line-height: $height;
color: #000;
font-weight: 500;
font-family: '微软雅黑', 'Microsoft YaHei', Arial, Helvetica, sans-serif;
&::before {
content: '';
display: inline-block;
vertical-align: top;
width: 4px;
height: $height + 2px;
border-radius: 1px;
margin-right: $mgr;
background-color: #0b58ff;
}
}
}
.p-0 {
padding: 0;
}
</style>

View File

@@ -0,0 +1,125 @@
<!--
* @Author: zwq
* @Date: 2025-10-11 14:27:37
* @LastEditors: zwq
* @LastEditTime: 2025-10-15 16:47:28
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<base-table
:selectWidth="55"
@selection-change="selectChange"
:table-props="tableProps"
:page="1"
:limit="999"
:table-data="tableData"></base-table>
</div>
</template>
<script>
import { listByDeptId } from '@/api/group/Schedule';
const tableProps = [
{
prop: 'code',
label: '班组编号',
width: 140,
},
{
prop: 'name',
label: '班组名称',
width: 100,
},
{
prop: 'deptId',
label: '所属部门',
},
{
prop: 'leaderName',
label: '组长',
},
{
prop: 'remark',
label: '备注',
},
];
export default {
data() {
return {
urlOptions: {
getDataListURL: listByDeptId,
},
tableProps,
tableData: [],
formConfig: [
{
type: 'input',
label: '班组编号',
placeholder: '班组编号',
param: 'code',
},
{
type: 'input',
label: '班组名称',
placeholder: '班组名称',
param: 'name',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
],
formInline: {
pageNo: 1,
pageSize: 100,
code: '',
name: '',
},
selectedList: [],
deptId: undefined
};
},
created() {},
methods: {
init(id){
this.deptId = id
this.getDataList()
},
// 获取数据列表
getDataList() {
this.urlOptions
.getDataListURL(this.deptId)
.then((response) => {
this.tableData = response.data;
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.formInline.name = val.name;
this.formInline.code = val.code;
this.getDataList();
break;
default:
console.log(val);
}
},
selectChange(val) {
this.selectedList = val;
},
dataFormSubmit() {
if (this.selectedList && this.selectedList.length > 0) {
this.$emit('refreshTableData', this.selectedList);
}
},
},
};
</script>

View File

@@ -0,0 +1,806 @@
<!--
* @Author: zwq
* @Date: 2025-10-13 15:07:24
* @LastEditors: zwq
* @LastEditTime: 2025-10-17 17:01:35
* @Description:
-->
<template>
<div>
<!-- 产线信息-工艺工序圆圈 -->
<div class="circle-container">
<div v-for="(item, index) in dotArr" :key="index" class="circle-wrapper">
<div
class="circle"
:style="{
background: stepNum == index + 1 ? '#0B58FF' : '',
}">
{{ index + 1 }}
</div>
<div
class="circle-text"
:style="{
color: stepNum == index + 1 ? '#0B58FF' : '',
}">
{{ item.name }}
</div>
<!-- 圆点后面的虚线 -->
<div v-if="index < 2" class="connector" />
</div>
</div>
<div v-if="stepNum == 1">
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-position="top"
label-width="80px">
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="计划编号" prop="code">
<el-input
v-model="dataForm.code"
clearable
placeholder="请输入计划编号" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="计划名称" prop="name">
<el-input
v-model="dataForm.name"
clearable
placeholder="请输入计划名称" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="部门">
<dept-select
style="width: 100%"
ref="deptSelect"
@DeptId="setDeptId"></dept-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="周末休假方式" prop="weekType">
<el-select
style="width: 100%"
v-model="dataForm.weekType"
placeholder="请选择周末休假方式">
<el-option
v-for="item in options1"
:key="item.value"
:label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="开始时间" prop="startDay">
<el-date-picker
style="width: 100%"
v-model="dataForm.startDay"
type="datetime"
value-format="timestamp"
placeholder="选择日期时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="结束时间" prop="endDay">
<el-date-picker
style="width: 100%"
v-model="dataForm.endDay"
type="datetime"
value-format="timestamp"
placeholder="选择日期时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="倒班方式" prop="shiftType">
<el-select
style="width: 100%"
v-model="dataForm.shiftType"
placeholder="请选择倒班方式">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="同班次连排" prop="shiftSustainedNum">
<el-input
v-model="dataForm.shiftSustainedNum"
oninput="value=value.replace(/^(0+)|[^\d]+/g,'')">
<el-select
style="width: 80px"
v-model="dataForm.shiftSustainedType"
slot="append">
<el-option label="日" :value="1"></el-option>
<el-option label="周" :value="2"></el-option>
<el-option label="月" :value="3"></el-option>
<el-option label="季" :value="4"></el-option>
</el-select>
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
clearable
placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div v-if="stepNum == 2">
<small-title style="margin: 16px 0" size="sm" :no-padding="true">
班次
</small-title>
<base-table
:table-props="tableProps1"
:page="1"
:limit="10"
:table-data="tableData1">
<method-btn
v-if="tableBtn1.length"
slot="handleBtn"
:width="80"
label="操作"
:method-list="tableBtn1"
@clickBtn="handleClick1" />
</base-table>
<small-title style="margin: 16px 0" size="sm" :no-padding="true">
班组
</small-title>
<base-table
:table-props="tableProps2"
:page="1"
:limit="10"
:table-data="tableData2"
:add-button-show="'新增'"
@emitButtonClick="addNewGroup">
<method-btn
v-if="tableBtn2.length"
slot="handleBtn"
:width="110"
label="操作"
:method-list="tableBtn2"
@clickBtn="handleClick2" />
</base-table>
</div>
<div v-if="stepNum == 3">
<small-title style="margin: 16px 0" size="sm" :no-padding="true">
排班计划预览
<span style="font-size: 14px; color: #ff1c15">
系统将根据以下设置按班组轮班顺序依次循环每日班次生成正式排班计划请确认
<el-popover
placement="right"
title="比如三班两倒同班次连排2天不休周末排班如下"
width="300"
trigger="hover">
<el-table :data="gridData">
<el-table-column property="date"></el-table-column>
<el-table-column
property="class1"
label="班次一"></el-table-column>
<el-table-column
property="class2"
label="班次二"></el-table-column>
</el-table>
<i
slot="reference"
class="el-icon-warning-outline"
style="color: #ff1c15"></i>
</el-popover>
</span>
</small-title>
<el-tag>
{{
'计划时间:' +
parseTime(dataForm.startDay) +
' 至 ' +
parseTime(dataForm.endDay)
}}
</el-tag>
<div
style="
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 10px;
margin: 15px;
">
<div style="display: grid; grid-template-columns: 40px auto; gap: 10px">
<div class="daobanpng" />
<div>
<div style="color: rgba(0, 0, 0, 0.6)">倒班方式</div>
<div style="color: #000000">
{{ ['长白班', '两班倒', '三班倒'][dataForm.shiftType - 1] }}
</div>
</div>
</div>
<div style="display: grid; grid-template-columns: 40px auto; gap: 10px">
<div class="lianpaipng" />
<div>
<div style="color: rgba(0, 0, 0, 0.6)">同班次连排</div>
<div style="color: #000000">
{{
dataForm.shiftSustainedNum +
['日', '周', '月', '季'][dataForm.shiftSustainedType - 1]
}}
</div>
</div>
</div>
<div style="display: grid; grid-template-columns: 40px auto; gap: 10px">
<div class="xiujiapng" />
<div>
<div style="color: rgba(0, 0, 0, 0.6)">周末休假方式</div>
<div style="color: #000000">
{{ ['双休', '周六休', '周日休', '不休'][dataForm.weekType - 1] }}
</div>
</div>
</div>
<div style="display: grid; grid-template-columns: 40px auto; gap: 10px">
<div class="banzupng" />
<div>
<div style="color: rgba(0, 0, 0, 0.6)">参与班组</div>
<div style="color: #000000">
{{
tableData2
.map((item) => {
return item.name;
})
.join('/')
}}
</div>
</div>
</div>
</div>
</div>
<base-dialog
:dialogTitle="'修改班次'"
:dialogVisible="addOrUpdateVisible1"
@cancel="cancel1"
@confirm="handleConfirm1"
:destroy-on-close="true"
append-to-body
width="40%">
<edit-class
ref="editClassRef"
@refreshTableData="refreshTableData1"></edit-class>
</base-dialog>
<base-dialog
:dialogTitle="'班组选择'"
:dialogVisible="addOrUpdateVisible2"
@cancel="cancel2"
@confirm="handleConfirm2"
:destroy-on-close="true"
append-to-body
width="40%">
<add-group
ref="addGroupRef"
@refreshTableData="refreshTableData2"></add-group>
</base-dialog>
<base-dialog
:dialogTitle="'绑定产线'"
:dialogVisible="addOrUpdateVisible3"
@cancel="cancel3"
@confirm="handleConfirm3"
:destroy-on-close="true"
append-to-body
width="50%">
<bind-line
ref="bindLineRef"
@refreshTableData="refreshTableData3"></bind-line>
</base-dialog>
</div>
</template>
<script>
import deptSelect from './../deptSelect.vue';
import SmallTitle from './SmallTitle';
import { parseTime } from '@/filter/code-filter';
import editClass from './edit-class.vue';
import addGroup from './add-group.vue';
import bindLine from './bind-line.vue';
import { getCode, createStepOne, returnStepOne } from '@/api/group/Schedule';
const tableProps1 = [
{
prop: 'name',
label: '班次名称',
},
{
prop: 'startDay',
label: '开始时间',
// filter: (val) => {
// parseTime(val, '{H}:{mm}');
// },
},
{
prop: 'endDay',
label: '结束时间',
// filter: (val) => {
// parseTime(val, '{H}:{mm}');
// },
},
{
prop: 'remark',
label: '备注',
},
];
const tableProps2 = [
{
prop: 'code',
label: '班组编号',
width: 140,
},
{
prop: 'name',
label: '班组名称',
},
{
prop: 'isProduction',
label: '是否生产班组',
filter: (val) => {
return val ? '是' : '否';
},
width: 110,
},
{
prop: 'code1',
label: '产线及工段',
},
];
export default {
components: {
deptSelect,
SmallTitle,
editClass,
addGroup,
bindLine,
},
data() {
return {
dotArr: [
{
name: '基础信息',
},
{
name: '班组班次',
},
{
name: '计划确认',
},
],
stepNum: 1, // 当前第几步
//第一步参数
dataForm: {
id: undefined,
code: undefined,
name: undefined,
startDay: undefined,
endDay: undefined,
deptId: undefined,
weekType: undefined,
shiftType: undefined,
shiftSustainedNum: undefined,
shiftSustainedType: 1,
remark: undefined,
},
options1: [
{
value: 1,
label: '双休',
},
{
value: 2,
label: '周六休',
},
{
value: 3,
label: '周日休',
},
{
value: 4,
label: '不休',
},
],
options2: [
{
value: 1,
label: '长白班',
},
{
value: 2,
label: '两班倒',
},
{
value: 3,
label: '三班倒',
},
],
dataRule: {
code: [
{ required: true, message: '计划编号不能为空', trigger: 'blur' },
],
name: [
{ required: true, message: '计划名称不能为空', trigger: 'blur' },
],
startDay: [
{ required: true, message: '开始时间不能为空', trigger: 'change' },
],
endDay: [
{ required: true, message: '结束时间不能为空', trigger: 'change' },
],
weekType: [
{
required: true,
message: '周末休假方式不能为空',
trigger: 'change',
},
],
shiftType: [
{
required: true,
message: '倒班方式方式不能为空',
trigger: 'change',
},
],
shiftSustainedNum: [
{ required: true, message: '同班次连排不能为空', trigger: 'blur' },
],
},
//第二步参数
tableProps1,
tableBtn1: [
{
type: 'edit',
btnName: '编辑',
},
].filter((v) => v),
tableData1: [],
tableProps2,
tableBtn2: [
{
type: 'bind',
btnName: '绑定产线',
},
{
type: 'delete',
btnName: '删除',
},
].filter((v) => v),
tableData2: [],
addOrUpdateVisible1: false,
addOrUpdateVisible2: false,
addOrUpdateVisible3: false,
//第三步参数
gridData: [
{
date: '第1天',
class1: 'A',
class2: 'B',
},
{
date: '第2天',
class1: 'A',
class2: 'B',
},
{
date: '第3天',
class1: 'C',
class2: 'A',
},
{
date: '第4天',
class1: 'C',
class2: 'A',
},
{
date: '第5天',
class1: 'B',
class2: 'C',
},
{
date: '第6天',
class1: 'B',
class2: 'C',
},
{
date: '第7天',
class1: 'A',
class2: 'B',
},
{
date: '第8天',
class1: 'A',
class2: 'B',
},
],
};
},
methods: {
//子组件获取的部门id
setDeptId(val) {
this.dataForm.deptId = val;
},
//详情时传给子组件的部门id
setDataForm() {
this.$refs.deptSelect.setID(this.dataForm.deptId);
},
init() {
this.$nextTick(() => {
this.$refs['dataForm'].resetFields();
getCode().then((res) => {
this.dataForm.code = res.data;
});
});
},
handleClick1(val) {
this.addOrUpdateVisible1 = true;
this.$nextTick(() => {
this.$refs.editClassRef.init(val.data);
});
},
handleClick2(val) {
if (val.type === 'bind') {
this.addOrUpdateVisible3 = true;
this.$nextTick(() => {
this.$refs.bindLineRef.init(val.data.id);
});
} else if (val.type === 'delete') {
this.tableData2.splice(val.data._pageIndex - 1, 1);
}
},
upSubmit() {
if (this.stepNum == 2) {
returnStepOne(this.dataForm.id).then((res) => {
this.stepNum -= 1;
this.$emit('setSN', this.stepNum);
this.$nextTick(() => {
this.setDataForm();
});
});
}
},
nextSubmit() {
if (this.stepNum == 1) {
this.$refs['dataForm'].validate((valid) => {
if (!valid) {
return false;
}
if (!this.dataForm.deptId) {
this.$message('部门不能为空');
return;
}
createStepOne(this.dataForm).then((res) => {
this.dataForm.id = res.data;
this.stepNum += 1;
this.$emit('setSN', this.stepNum);
this.setTWOclass(); // 第一步提交后,根据倒班方式设置第二部班次
});
});
return;
}
if (this.stepNum == 2) {
let data = {}
data.planId = this.dataForm.id
data.groupPlanClassesBaseVOList = [] //排班-班次信息list
this.tableData1.forEach((item,index)=>{
const obj = {
sort: index+1,
name : item.name,
remark: item.remark,
startTime: {
hour:item.startDay.split(':')[0],
minute:item.startDay.split(':')[1],
},
endTime: {
hour:item.endDay.split(':')[0],
minute:item.endDay.split(':')[1],
}
}
data.groupPlanClassesBaseVOList.push(obj)
})
data.groupPlanTeamBaseVOList = [] //排班-班组信息list
this.tableData2.forEach(item=>{
const obj = {
teamId:item.id,
bindData: ''
}
data.groupPlanTeamBaseVOList.push(obj)
})
this.stepNum += 1;
this.$emit('setSN', this.stepNum);
return;
}
if (this.stepNum == 3) {
this.stepNum = 1;
this.$emit('setSN', this.stepNum);
return;
}
},
//设置第二部班次
setTWOclass() {
this.tableData1 = [];
if (this.dataForm.shiftType == 1) {
const obj = {
name: '长白班',
startDay: '8:00',
endDay: '17:00',
};
this.tableData1.push(obj);
} else if (this.dataForm.shiftType == 2) {
const obj1 = {
name: '白班',
startDay: '8:00',
endDay: '20:00',
};
const obj2 = {
name: '夜班',
startDay: '20:00',
endDay: '8:00',
};
this.tableData1.push(obj1, obj2);
} else if (this.dataForm.shiftType == 3) {
const obj1 = {
name: '早班',
startDay: '8:00',
endDay: '16:00',
};
const obj2 = {
name: '中班',
startDay: '16:00',
endDay: '00:00',
};
const obj3 = {
name: '夜班',
startDay: '00:00',
endDay: '8:00',
};
this.tableData1.push(obj1, obj2, obj3);
}
},
// 新增班组
addNewGroup() {
this.addOrUpdateVisible2 = true;
this.$nextTick(() => {
this.$refs.addGroupRef.init(this.dataForm.deptId);
});
},
cancel1() {
this.addOrUpdateVisible1 = false;
},
cancel2() {
this.addOrUpdateVisible2 = false;
},
cancel3() {
this.addOrUpdateVisible3 = false;
},
handleConfirm1() {
this.$refs.editClassRef.dataFormSubmit();
},
handleConfirm2() {
this.$refs.addGroupRef.dataFormSubmit();
},
handleConfirm3() {
this.$refs.bindLineRef.dataFormSubmit();
},
refreshTableData1(index, val) {
this.tableData1.splice(index, 1, val);
this.cancel1();
},
refreshTableData2(val) {
this.tableData2.push(...val);
this.cancel2();
},
refreshTableData3(val) {
console.log(val);
this.cancel3();
},
},
};
</script>
<style scoped>
.daobanpng {
width: 40px;
height: 40px;
background-image: url('~@/assets/images/daoban.png');
background-size: 100% 100%;
}
.lianpaipng {
width: 40px;
height: 40px;
background-image: url('~@/assets/images/lianpai.png');
background-size: 100% 100%;
}
.xiujiapng {
width: 40px;
height: 40px;
background-image: url('~@/assets/images/xiujia.png');
background-size: 100% 100%;
}
.banzupng {
width: 40px;
height: 40px;
background-image: url('~@/assets/images/banzu.png');
background-size: 100% 100%;
}
</style>
<!-- //序号圆点 -->
<style scoped>
.circle-container {
height: 110px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
width: 90%;
overflow-x: auto;
margin: auto;
}
.circle-wrapper {
position: relative;
display: flex;
align-items: center;
}
.circle {
width: 52px;
height: 52px;
border-radius: 50%;
background: #8db1ff;
font-weight: 500;
font-size: 31px;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
position: relative;
z-index: 2;
cursor: pointer;
}
.circle-text {
position: absolute;
top: 60px;
left: -15px;
color: #8db1ff;
width: 82px;
text-align: center;
}
/* 下半圆虚线边框 */
.circle::after {
content: '';
position: absolute;
bottom: -6px; /* 2px边框 + 2px间隙 */
left: -4px;
right: -4px;
height: 30px; /* 半圆高度 */
border-radius: 0 0 60px 60px;
border: 1px dashed #0b58ff;
border-top: none;
z-index: 1;
}
.connector {
width: 160px; /* 计算连接线长度 */
height: 2px;
border-bottom: 1px dashed rgb(11, 88, 255, 1);
margin: 0 5px;
z-index: 1;
}
</style>

View File

@@ -0,0 +1,69 @@
<!--
* @Author: zwq
* @Date: 2021-11-18 14:16:25
* @LastEditors: zwq
* @LastEditTime: 2025-10-16 16:37:40
* @Description:
-->
<template>
<div style="width: 100%; display: flex; justify-content: center">
<tree-transfer
:title="title"
:from_data="fromData"
:to_data="toData"
@add-btn="add"
@remove-btn="remove"
pid="pid"
:defaultProps="{ label: 'name' }"
height="450px"
style="padding-bottom:20px"
:mode="mode"
filter
openAll></tree-transfer>
</div>
</template>
<script>
import treeTransfer from 'el-tree-transfer';
import { getGroupPlanTree } from '@/api/group/Schedule';
export default {
components: { treeTransfer },
data() {
return {
groupId: undefined,
title: ['待选', '已选'],
mode: 'transfer',
fromData: [], //左边内容
toData: [], //右边已选内容
};
},
methods: {
init(id) {
this.fromData = [];
this.toData = [];
this.groupId = id;
getGroupPlanTree().then((res) => {
this.fromData = res.data;
this.fromData.forEach((item) => {
item.productionLineId = 0;
});
});
},
// 监听穿梭框组件添加
add(fromData, toData, obj) {
console.log('fromData:', fromData);
console.log('toData:', toData,obj);
},
// 监听穿梭框组件移除
remove(fromData, toData, obj) {
console.log('fromData:', fromData);
console.log('toData:', toData);
},
// 表单提交
dataFormSubmit() {
this.$emit('refreshTableData',this.toData);
},
},
};
</script>

View File

@@ -0,0 +1,114 @@
<!--
* @Author: zwq
* @Date: 2021-11-18 14:16:25
* @LastEditors: zwq
* @LastEditTime: 2025-10-15 16:31:11
* @Description:
-->
<template>
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-position="top"
label-width="80px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="序号" prop="index">
<el-input-number
v-model="dataForm.index"
:step="1"
:min="1"
step-strictly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班次名称" prop="name">
<el-input
v-model="dataForm.name"
clearable
placeholder="请输入班次名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开始时间" prop="startDay">
<el-time-picker
style="width: 100%"
format="H:mm"
value-format="H:mm"
v-model="dataForm.startDay"
placeholder="选择日期时间"></el-time-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束时间" prop="endDay">
<el-time-picker
style="width: 100%"
format="H:mm"
value-format="H:mm"
v-model="dataForm.endDay"
placeholder="选择日期时间"></el-time-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
clearable
placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
components: {},
data() {
return {
dataForm: {
id: undefined,
index: undefined,
name: undefined,
startDay: undefined,
endDay: undefined,
remark: undefined,
},
_pageIndex: 1,
dataRule: {
index: [{ required: true, message: '序号不能为空', trigger: 'blur' }],
name: [
{ required: true, message: '班次名称不能为空', trigger: 'blur' },
],
startDay: [
{ required: true, message: '开始时间不能为空', trigger: 'change' },
],
endDay: [
{ required: true, message: '结束时间不能为空', trigger: 'change' },
],
},
};
},
methods: {
init(val) {
this._pageIndex = val._pageIndex-1;
this.dataForm.index = val._pageIndex || 1;
this.dataForm.name = val.name || undefined;
this.dataForm.startDay = val.startDay || undefined;
this.dataForm.endDay = val.endDay || undefined;
this.dataForm.remark = val.remark || undefined;
},
// 表单提交
dataFormSubmit() {
this.$refs['dataForm'].validate((valid) => {
if (!valid) {
return false;
}
this.$emit('refreshTableData', this._pageIndex, this.dataForm);
});
},
},
};
</script>

View File

@@ -0,0 +1,469 @@
<!--
* @Author: zwq
* @Date: 2025-10-11 14:27:37
* @LastEditors: zwq
* @LastEditTime: 2025-10-15 16:42:28
* @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"
type="datetime"
placeholder="选择日期时间"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endDay">
<el-date-picker
v-model="formInline.endDay"
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="leaderName">
<el-select v-model="formInline.status" 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"
@click="buttonClick({ btnName: 'search' })">
查询
</el-button>
</el-form-item>
<el-form-item>
<span class="separateStyle"></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"></span>
</el-form-item>
<el-form-item>
<el-button
type="success"
size="small"
:plain="true"
@click="buttonClick({ btnName: 'add' })">
新增
</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="80"
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="handleConfirm">
保存草稿
</el-button>
<el-button
type="primary"
class="btnTextStyle"
size="small"
@click="handleConfirm">
{{ stepNum < 3 ? '下一步' : '确认并执行' }}
</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 { parseTime } from '@/filter/code-filter';
import { getGroupPlanPage, deleteGroupPlan } 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: 'deptId',
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: [
{
type: 'edit',
btnName: '编辑',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 1,
},
],
},
},
{
type: 'delete',
btnName: '删除',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 1,
},
],
},
},
{
type: 'detail',
btnName: '查看',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'status',
value: 1,
},
],
},
},
{
type: 'cancel',
btnName: '作废',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 2,
},
],
},
},
{
type: 'sync',
btnName: '同步节假日',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: 2,
},
{
type: 'updateFlag',
name: 'status',
value: true,
},
],
},
},
{
type: 'copy',
btnName: '复制',
},
].filter((v) => v),
tableData: [],
options: [
{
value: '1',
label: '草稿',
},
{
value: '2',
label: '已确认',
},
{
value: '3',
label: '已作废',
},
],
formInline: {
code: '',
name: '',
startDay: '',
endDay: '',
deptId: '',
status: '',
},
stepNum: 1, // 新增编辑时当前第几步
};
},
components: {
AddOrUpdate,
deptSelect,
},
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.leaderName = 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;
},
// dialog取消
handleCancel() {
this.addOrUpdateVisible = false;
this.addOrEditTitle = '';
},
handleConfirm(val) {
if (val == 'up') {
this.$refs.addOrUpdate.upSubmit();
} else {
this.$refs.addOrUpdate.nextSubmit();
}
},
},
};
</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>

View File

@@ -0,0 +1,26 @@
<template>
<span>
{{
injectData.shiftSustainedNum +
(injectDatashiftSustainedType
? ['', '日', '周', '月', '季'][injectDatashiftSustainedType]
: '')
}}
</span>
</template>
<script>
export default {
props: {
injectData: {
type: Object,
default: () => ({}),
},
},
data() {
return {};
},
created() {},
methods: {},
};
</script>

View File

@@ -0,0 +1,31 @@
<!--
* @Author: zwq
* @Date: 2025-10-13 16:40:08
* @LastEditors: zwq
* @LastEditTime: 2025-10-13 16:43:11
* @Description:
-->
<template>
<el-tag
v-if="injectData.status"
size="medium"
:type="['', '', 'success', 'warning'][injectData.status]">
{{ ['', '草稿', '已确认', '已作废'][injectData.status] }}
</el-tag>
</template>
<script>
export default {
props: {
injectData: {
type: Object,
default: () => ({}),
},
},
data() {
return {};
},
created() {},
methods: {},
};
</script>