班组bug #455

Merged
zwq merged 1 commits from projects/line-new-zwq into projects/line-new 2025-11-28 16:29:25 +08:00
15 changed files with 874 additions and 576 deletions
Showing only changes of commit ffa0b2e8dd - Show all commits

View File

@@ -26,6 +26,13 @@ export function getGroup(id) {
method: 'get' method: 'get'
}) })
} }
// 检查更新-生产班组
export function updateIsProduction(id) {
return request({
url: '/base/group-team/updateIsProduction?id=' + id,
method: 'get'
})
}
// 获得班组基础信息分页 // 获得班组基础信息分页
export function getGroupPage(query) { export function getGroupPage(query) {

View File

@@ -16,7 +16,7 @@ export default {
}, },
tableData: [], //table数据 tableData: [], //table数据
listQuery: { //分页 listQuery: { //分页
pageSize: 10, pageSize: 20,
pageNo: 1, pageNo: 1,
total: 1, total: 1,
}, },

View File

@@ -1,10 +1,10 @@
import axios from 'axios' import axios from 'axios'
import {Message, MessageBox, Notification, Loading} from 'element-ui' import { Message, MessageBox, Notification, Loading } from 'element-ui'
import store from '@/store' import store from '@/store'
import {getAccessToken, getRefreshToken, getTenantId, setToken} from '@/utils/auth' import { getAccessToken, getRefreshToken, getTenantId, setToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode' import errorCode from '@/utils/errorCode'
import {getPath, getTenantEnable} from "@/utils/ruoyi"; import { getPath, getTenantEnable } from "@/utils/ruoyi";
import {refreshToken} from "@/api/login"; import { refreshToken } from "@/api/login";
// 需要忽略的提示。忽略后,自动 Promise.reject('error') // 需要忽略的提示。忽略后,自动 Promise.reject('error')
const ignoreMsgs = [ const ignoreMsgs = [
@@ -86,7 +86,7 @@ service.interceptors.request.use(config => {
for (const propName of Object.keys(config.params)) { for (const propName of Object.keys(config.params)) {
const value = config.params[propName]; const value = config.params[propName];
const part = encodeURIComponent(propName) + '=' const part = encodeURIComponent(propName) + '='
if (value !== null && typeof(value) !== "undefined") { if (value !== null && typeof (value) !== "undefined") {
if (typeof value === 'object') { if (typeof value === 'object') {
for (const key of Object.keys(value)) { for (const key of Object.keys(value)) {
let params = propName + '[' + key + ']'; let params = propName + '[' + key + ']';
@@ -104,9 +104,9 @@ service.interceptors.request.use(config => {
} }
return config return config
}, error => { }, error => {
tryHideFullScreenLoading() tryHideFullScreenLoading()
console.log(error) console.log(error)
Promise.reject(error) Promise.reject(error)
}) })
// 响应拦截器 // 响应拦截器
@@ -176,36 +176,38 @@ service.interceptors.response.use(async res => {
+ '<div>5 分钟搭建本地环境</div>', + '<div>5 分钟搭建本地环境</div>',
}) })
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))
} else if (code === 400) {
//【班组管理】【排班计划】提交的校验按照原型图补充完整,排班计划是否重叠code400 有两个不同的返回信息
return res.data
} else if (code !== 200) { } else if (code !== 200) {
if (msg === '无效的刷新令牌') { // hard coding忽略这个提示直接登出 if (msg === '无效的刷新令牌') { // hard coding忽略这个提示直接登出
console.log(msg) console.log(msg)
} else { } else {
Notification.error({ //【班组管理】【排班计划】提交的校验按照原型图补充完整,排班计划是否重叠code400 有两个不同的返回信息
title: msg return res.data
})
} }
return Promise.reject('error') return Promise.reject('error')
} else { } else {
return res.data return res.data
} }
}, error => { }, error => {
tryHideFullScreenLoading() tryHideFullScreenLoading()
console.log('err' + error) console.log('err' + error)
let {message} = error; let { message } = error;
if (message === "Network Error") { if (message === "Network Error") {
message = "后端接口连接异常"; message = "后端接口连接异常";
} else if (message.includes("timeout")) { } else if (message.includes("timeout")) {
message = "系统接口请求超时"; message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
} }
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
) )
export function getBaseHeader() { export function getBaseHeader() {
@@ -219,10 +221,10 @@ function handleAuthorized() {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true; isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录', confirmButtonText: '重新登录',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
} }
).then(() => { ).then(() => {
isRelogin.show = false; isRelogin.show = false;
store.dispatch('LogOut').then(() => { store.dispatch('LogOut').then(() => {

View File

@@ -2,14 +2,14 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-23 13:43:55 * @Date: 2025-10-23 13:43:55
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-10 10:39:33 * @LastEditTime: 2025-11-14 21:13:10
* @Description: * @Description:
--> -->
<template> <template>
<div class="app-container" style="padding-top:0"> <div class="app-container" style="padding-top: 0">
<div v-for="item in groupClassArr" :key="item.planId"> <div v-for="item in groupClassArr" :key="item.planId">
<small-title style="margin: 16px 0" size="sm" :no-padding="true"> <small-title style="margin: 16px 0" size="sm" :no-padding="true">
{{item.deptName + ' - ' +item.planName}} {{ item.deptName + ' - ' + item.planName }}
</small-title> </small-title>
<base-table <base-table
:table-props="tableProps" :table-props="tableProps"
@@ -59,7 +59,7 @@ export default {
}, },
created() {}, created() {},
methods: { methods: {
init(det) { init(det, detSort) {
this.tableData = det; this.tableData = det;
//返回计划名和id //返回计划名和id
const arr = det.map((item) => { const arr = det.map((item) => {
@@ -77,7 +77,19 @@ export default {
map.set(item.planId, item); map.set(item.planId, item);
} }
}); });
this.groupClassArr = Array.from(map.values()); const newArr = Array.from(map.values());
// 创建B数组中id的顺序映射
const orderMap = new Map();
detSort.forEach((item, index) => {
orderMap.set(item, index);
});
// 根据B的顺序对A进行排序
this.groupClassArr = [...newArr].sort((a, b) => {
const orderA = orderMap.get(a.planId);
const orderB = orderMap.get(b.planId);
return orderA - orderB;
});
}, },
}, },
}; };

View File

@@ -2,212 +2,221 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-23 13:43:55 * @Date: 2025-10-23 13:43:55
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-10 10:40:13 * @LastEditTime: 2025-11-25 09:39:43
* @Description: * @Description:
--> -->
<template> <template>
<el-row :gutter="10" style="background-color: #f2f4f9"> <div
<!--部门数据--> class="app-container"
<el-col :span="4"> style="
<div class="head-container"> background-color: #f2f4f9;
<el-tabs v-model="activeName" stretch @tab-click="tabsClick"> padding: 0;
<el-tab-pane label="部门" name="first"></el-tab-pane> display: grid;
<el-tab-pane label="班组" name="second"></el-tab-pane> grid-template-columns: 1fr 5fr;
</el-tabs> gap: 10px;
<div v-if="activeName == 'first'"> ">
<el-input <div class="head-container">
v-model="deptName" <el-tabs v-model="activeName" stretch @tab-click="tabsClick">
placeholder="请输入部门名称" <el-tab-pane label="部门" name="first"></el-tab-pane>
clearable <el-tab-pane label="班组" name="second"></el-tab-pane>
size="small" </el-tabs>
prefix-icon="el-icon-search" <div v-if="activeName == 'first'">
style="margin-bottom: 20px" /> <el-input
<el-tree v-model="deptName"
:data="deptOptions" placeholder="请输入部门名称"
:props="defaultProps" clearable
:expand-on-click-node="false" size="small"
:filter-node-method="filterNode" prefix-icon="el-icon-search"
ref="tree" style="margin-bottom: 20px" />
default-expand-all <el-tree
highlight-current :data="deptOptions"
@node-click="handleNodeClick" /> :props="defaultProps"
</div> :expand-on-click-node="false"
<div v-else> :filter-node-method="filterNode"
<el-input ref="tree"
v-model="groupName" node-key="id"
placeholder="请输入班组名称" default-expand-all
clearable highlight-current
size="small" @node-click="handleNodeClick" />
prefix-icon="el-icon-search"
style="margin-bottom: 20px" />
<el-tree
:data="groupOptions"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree1"
default-expand-all
highlight-current
@node-click="handleNodeClick1" />
</div>
</div> </div>
</el-col> <div v-else>
<el-col :span="20"> <el-input
<div class="groupTeamScheduling"> v-model="groupName"
<div class="operationArea"> placeholder="请输入班组名称"
<el-form :inline="true" class="demo-form-inline"> clearable
<span class="blue-block"></span> size="small"
<el-form-item label="月份选择"> prefix-icon="el-icon-search"
<el-date-picker style="margin-bottom: 20px" />
v-model="startDay" <el-tree
type="month" :data="groupOptions"
placeholder="选择月" :props="defaultProps"
size="small" :expand-on-click-node="false"
@change="selectMonth" :filter-node-method="filterNode"
:clearable="false" ref="tree1"
style="width: 120px"></el-date-picker> node-key="id"
<span default-expand-all
style="color: #909399; font-size: 12px" highlight-current
v-if="activeName == 'first'"> @node-click="handleNodeClick1" />
提示排班日历仅展示当前选中部门的节假日设置若休假日中仍有排班则表示下级组织已通过自定义假期进行排班 </div>
</div>
<div class="groupTeamScheduling">
<div class="operationArea">
<el-form :inline="true" class="demo-form-inline">
<span class="blue-block"></span>
<el-form-item label="月份选择">
<el-date-picker
v-model="startDay"
type="month"
placeholder="选择月"
size="small"
@change="selectMonth"
:clearable="false"
style="width: 120px"></el-date-picker>
<span
style="color: #909399; font-size: 12px"
v-if="activeName == 'first'">
提示排班日历仅展示当前选中部门的节假日设置若休假日中仍有排班则表示下级组织已通过自定义假期进行排班
</span>
<span v-else style="margin-left: 10px">
组长:
<span style="font-weight: 600; margin: 0 10px">
{{ showTeamName?.leaderName || '-' }}
</span> </span>
<span v-else> 组长电话:
组长:{{ showTeamName?.leaderName || '-' }} 组长电话:{{ <span style="font-weight: 600; margin: 0 10px">
showTeamName?.leaderPhone || '-' {{ showTeamName?.leaderPhone || '-' }}
}}
</span> </span>
</el-form-item> </span>
<el-form-item style="float: right"> </el-form-item>
<el-button <el-form-item style="float: right">
size="small" <el-button
type="primary" size="small"
@click="(startDay = new Date()), getHolidayPage()"> type="primary"
跳转到今天 @click="(startDay = new Date()), getHolidayPage()">
</el-button> 跳转到今天
</el-form-item> </el-button>
</el-form> </el-form-item>
</div> </el-form>
<!-- 日历区域 --> </div>
<div class="calenderArea"> <!-- 日历区域 -->
<el-calendar v-model="startDay"> <div class="calenderArea">
<template slot="dateCell" slot-scope="{ data }"> <el-calendar v-model="startDay">
<div v-if="data.type === 'current-month'"> <template slot="dateCell" slot-scope="{ data }">
<!-- 日期 --> <div v-if="data.type === 'current-month'">
<div class="dateStyle"> <!-- 日期 -->
<el-row :gutter="20"> <div class="dateStyle">
<!-- 公历和农历 --> <el-row :gutter="20">
<el-col :span="18"> <!-- 公历和农历 -->
{{ Number(data.day.split('-')[2]) }} <el-col :span="18">
<div class="lunar-date">{{ getLunarDate(data.day) }}</div> {{ Number(data.day.split('-')[2]) }}
</el-col> <div class="lunar-date">{{ getLunarDate(data.day) }}</div>
<!-- 显示假或班 --> </el-col>
<el-col :span="6"> <!-- 显示假或班 -->
<div <el-col :span="6">
class="work-tip"
:style="{
backgroundColor: HolidayList[
Number(data.day.split('-')[2]) - 1
]?.isHoliday
? '#67C23A'
: '#409EFF',
}">
{{
HolidayList[Number(data.day.split('-')[2]) - 1]
?.isHoliday
? '假'
: '班'
}}
<!-- //变更节假日未更新排班计划的角标 -->
<div
class="subIcon"
v-if="
HolidayList[Number(data.day.split('-')[2]) - 1]
?.isUpdate
">
<el-tooltip
effect="dark"
content="本日节假日变更已影响当前排班计划,但尚未同步,请及时处理。"
placement="top">
<i
class="el-icon-warning"
style="color: #f56c6c"></i>
</el-tooltip>
</div>
</div>
</el-col>
<!-- 显示排班 -->
<div <div
v-if=" class="work-tip"
HolidayList[Number(data.day.split('-')[2]) - 1]?.det :style="{
.length > 0 backgroundColor: HolidayList[
">
<el-col
:span="24"
v-for="(item, index) in HolidayList[
Number(data.day.split('-')[2]) - 1 Number(data.day.split('-')[2]) - 1
]?.det.filter( ]?.isHoliday
(item) => ? '#67C23A'
item.schedulingPlanId == : '#409EFF',
HolidayList[Number(data.day.split('-')[2]) - 1] }">
?.schedulingPlanId {{
)" HolidayList[Number(data.day.split('-')[2]) - 1]
:key="index"> ?.isHoliday
? '假'
: '班'
}}
<!-- //变更节假日未更新排班计划的角标 -->
<div
class="subIcon"
v-if="
HolidayList[Number(data.day.split('-')[2]) - 1]
?.isUpdate
">
<el-tooltip <el-tooltip
effect="dark" effect="dark"
content="点击展示全部排班计划" content="本日节假日变更已影响当前排班计划,但尚未同步,请及时处理。"
placement="top-start"> placement="top">
<div <i class="el-icon-warning" style="color: #f56c6c"></i>
class="holiday-div"
:style="{
backgroundColor:
holidayDivColor[item?.classesCode],
}"
@click="
holidayLog(
HolidayList[Number(data.day.split('-')[2]) - 1]
?.det,
HolidayList[Number(data.day.split('-')[2]) - 1]
?.date,
)
"
:title="
item.classesName +
' | ' +
item.teamName +
' | ' +
item.workTime
">
{{
item.classesName +
' | ' +
item.teamName +
' | ' +
item.workTime
}}
</div>
</el-tooltip> </el-tooltip>
</el-col> </div>
</div> </div>
</el-row>
</div>
</div>
<div
v-else
style="font-size: 20px; font-weight: 500; text-align: left">
<el-row :gutter="20">
<el-col :span="24">
{{ Number(data.day.split('-')[2]) }}
<span style="font-size: 12px">
{{ getLunarDate(data.day) }}
</span>
</el-col> </el-col>
<!-- 显示排班 -->
<div
v-if="
HolidayList[Number(data.day.split('-')[2]) - 1]?.det
.length > 0
">
<el-col
:span="24"
v-for="(item, index) in HolidayList[
Number(data.day.split('-')[2]) - 1
]?.det.filter(
(item) =>
item.schedulingPlanId ==
HolidayList[Number(data.day.split('-')[2]) - 1]
?.schedulingPlanId
)"
:key="index">
<el-tooltip
effect="dark"
content="点击展示全部排班计划"
placement="top-start">
<div
class="holiday-div"
:style="{
backgroundColor: holidayDivColor[item?.classesCode],
}"
@click="
holidayLog(
HolidayList[Number(data.day.split('-')[2]) - 1]
?.det,
HolidayList[Number(data.day.split('-')[2]) - 1]
?.date,
HolidayList[Number(data.day.split('-')[2]) - 1]
?.detSort
)
"
:title="
item.classesName +
' | ' +
item.teamName +
' | ' +
item.workTime
">
{{
item.classesName +
' | ' +
item.teamName +
' | ' +
item.workTime
}}
</div>
</el-tooltip>
</el-col>
</div>
</el-row> </el-row>
</div> </div>
</template> </div>
</el-calendar> <div
</div> v-else
style="font-size: 20px; font-weight: 500; text-align: left">
<el-row :gutter="20">
<el-col :span="24">
{{ Number(data.day.split('-')[2]) }}
<span style="font-size: 12px">
{{ getLunarDate(data.day) }}
</span>
</el-col>
</el-row>
</div>
</template>
</el-calendar>
</div> </div>
</el-col> </div>
<base-dialog <base-dialog
:dialogTitle="dialogTitle" :dialogTitle="dialogTitle"
:dialogVisible="logVisible" :dialogVisible="logVisible"
@@ -228,7 +237,7 @@
</slot> </slot>
</template> </template>
</base-dialog> </base-dialog>
</el-row> </div>
</template> </template>
<script> <script>
@@ -339,13 +348,43 @@ export default {
getEnableData().then((response) => { getEnableData().then((response) => {
// 处理 deptOptions 参数 // 处理 deptOptions 参数
this.deptOptions = []; this.deptOptions = [];
this.deptOptions.push(...this.handleTree(response.data, 'id')); this.deptOptions.push(...this.handleTree1(response.data, 'id'));
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.deptId);
});
}); });
listByDeptId(this.topDept.id).then((response) => { listByDeptId(this.topDept.id).then((response) => {
this.groupOptions = []; this.groupOptions = [];
this.groupOptions.push(...response.data); this.groupOptions.push(...response.data);
}); });
}, },
//大整数精度丢失
handleTree1(data, fid) {
const id = fid || 'id';
const parentId = 'parentId';
const children = 'children';
const rootId =
data
.map((item) => item[parentId].toString())
.reduce((min, current) => {
if (current.length < min.length) return current;
if (current.length > min.length) return min;
return current < min ? current : min;
}) || 0;
//对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data));
//循环所有项
const treeData = cloneData.filter((father) => {
let branchArr = cloneData.filter((child) => {
//返回每一项的子级数组
return father[id] == child[parentId];
});
branchArr.length > 0 ? (father.children = branchArr) : '';
//返回第一层
return father[parentId] == rootId;
});
return treeData !== '' ? treeData : data;
},
// 筛选节点 // 筛选节点
filterNode(value, data) { filterNode(value, data) {
if (!value) return true; if (!value) return true;
@@ -358,8 +397,14 @@ export default {
leaderName: this.groupOptions[0].leaderName || '-', leaderName: this.groupOptions[0].leaderName || '-',
leaderPhone: this.groupOptions[0].leaderPhone || '-', leaderPhone: this.groupOptions[0].leaderPhone || '-',
}; };
this.$nextTick(() => {
this.$refs.tree1.setCurrentKey(this.teamId);
});
} else if (this.activeName == 'first') { } else if (this.activeName == 'first') {
this.deptId = this.topDept.id; this.deptId = this.topDept.id;
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.deptId);
});
} }
this.getHolidayPage(); this.getHolidayPage();
}, },
@@ -441,11 +486,11 @@ export default {
return ''; return '';
} }
}, },
holidayLog(det, date) { holidayLog(det, date, detSort) {
this.dialogTitle = this.showDeptName + '-' + date + '-排班详情'; this.dialogTitle = this.showDeptName + '-' + date + '-排班详情';
this.logVisible = true; this.logVisible = true;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.holidayLogRef.init(det); this.$refs.holidayLogRef.init(det, detSort);
}); });
}, },
cancelLog() { cancelLog() {
@@ -459,8 +504,8 @@ export default {
.head-container { .head-container {
padding: 20px 10px 0; padding: 20px 10px 0;
background-color: #fff; background-color: #fff;
min-height: calc(100vh - 120px - 8px);
border-radius: 8px; border-radius: 8px;
height: 100%;
} }
.groupTeamScheduling { .groupTeamScheduling {
.operationArea { .operationArea {

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-11 14:27:37 * @Date: 2025-10-11 14:27:37
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-10 16:20:13 * @LastEditTime: 2025-11-14 22:00:10
* @Description: * @Description:
--> -->
<template> <template>
@@ -104,7 +104,7 @@ export default {
// 获取数据列表 // 获取数据列表
getDataList() { getDataList() {
this.urlOptions.getDataListURL(this.formInline).then((response) => { this.urlOptions.getDataListURL(this.formInline).then((response) => {
this.tableData = response.data.list; this.tableData = response.data.list.filter(item=>item.enabled===1);
this.tableData.forEach(item=>item.teamId= item.id) this.tableData.forEach(item=>item.teamId= item.id)
this.$nextTick(() => { this.$nextTick(() => {
if (this.selectedArr.length > 0) { if (this.selectedArr.length > 0) {

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-13 15:07:24 * @Date: 2025-10-13 15:07:24
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-11 15:32:04 * @LastEditTime: 2025-11-27 14:41:59
* @Description: * @Description:
--> -->
<template> <template>
@@ -138,7 +138,14 @@
<el-tag type="warning" style="color: black" v-if="!isClassTimePass"> <el-tag type="warning" style="color: black" v-if="!isClassTimePass">
<i class="el-icon-warning" style="color: #ffbd02"></i> <i class="el-icon-warning" style="color: #ffbd02"></i>
两班倒和三班倒的班次设置时间 两班倒和三班倒的班次设置时间
<span style="color: red">不能重叠且必须连续覆盖24小时</span> <span style="color: red">不能重叠</span>
在24小时
</el-tag>
<el-tag type="warning" style="color: black" v-if="!covers24Hours">
<i class="el-icon-warning" style="color: #ffbd02"></i>
两班倒和三班倒的班次设置时间,班次时间
<span style="color: red">必须连续</span>
在24小时
</el-tag> </el-tag>
</small-title> </small-title>
<base-table <base-table
@@ -443,7 +450,7 @@ export default {
}, },
], ],
stepNum: 1, // 当前第几步 stepNum: 1, // 当前第几步
isEdit: false, //是否是编辑状态,编辑的时候,让前端上一步和取消都不用接口 isEdit: false, //是否是编辑状态,编辑的时候,让前端上一步和取消都不用接口
shiftTypeEdit: undefined, //该值为编辑时获取的shiftType到第二步判断dataForm.shiftType是否改变同时改变班次信息 shiftTypeEdit: undefined, //该值为编辑时获取的shiftType到第二步判断dataForm.shiftType是否改变同时改变班次信息
//第一步参数 //第一步参数
dataForm: { dataForm: {
@@ -531,7 +538,8 @@ export default {
btnName: '编辑', btnName: '编辑',
}, },
].filter((v) => v), ].filter((v) => v),
isClassTimePass: true, //修改班次时间后,需要判断时间是否有覆盖,且是否覆盖24小时 isClassTimePass: true, //修改班次时间后,需要判断时间是否有重叠,且是否24小时内 true是没问题的
covers24Hours: true, //修改班次时间后需要判断时间是否覆盖24小时连续的时间 true是没问题的
tableData1: [], tableData1: [],
tableProps2, tableProps2,
tableBtn2: [ tableBtn2: [
@@ -621,9 +629,9 @@ export default {
}; };
}, },
methods: { methods: {
init(id,isEdit) { init(id, isEdit) {
this.dataForm.id = id || undefined; this.dataForm.id = id || undefined;
this.isEdit = isEdit || false this.isEdit = isEdit || false;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['dataForm'].resetFields(); this.$refs['dataForm'].resetFields();
if (this.dataForm.id) { if (this.dataForm.id) {
@@ -638,8 +646,10 @@ export default {
if (item.isProduction) { if (item.isProduction) {
lineName = this.setLineName(item.bindLineTree); lineName = this.setLineName(item.bindLineTree);
} }
this.$set(this.tableData2[index], 'lineName', lineName); this.$set(this.tableData2[index], 'lineName', lineName.join(';'));
}); });
this.stepNum = 3;
this.getThreeGroup(7); // 第三步,进来加载预览排班,默认7天预览周期
}); });
} else { } else {
getCode().then((res) => { getCode().then((res) => {
@@ -757,7 +767,7 @@ export default {
} }
//班次验证 //班次验证
if (!this.isClassTimePass) { if (!this.isClassTimePass || !this.covers24Hours) {
this.$message('班次内时间有误,请重新填写!'); this.$message('班次内时间有误,请重新填写!');
return; return;
} }
@@ -777,9 +787,10 @@ export default {
data.groupPlanClassesBaseVOList.push(obj); data.groupPlanClassesBaseVOList.push(obj);
}); });
data.groupPlanTeamBaseVOList = []; //排班-班组信息list data.groupPlanTeamBaseVOList = []; //排班-班组信息list
this.tableData2.forEach((item) => { this.tableData2.forEach((item, index) => {
const obj = { const obj = {
teamId: item.id, sort: index + 1,
teamId: item.teamId || item.id,
name: item.name, name: item.name,
leaderName: item.leaderName, leaderName: item.leaderName,
leaderPhone: item.leaderPhone, leaderPhone: item.leaderPhone,
@@ -788,9 +799,13 @@ export default {
data.groupPlanTeamBaseVOList.push(obj); data.groupPlanTeamBaseVOList.push(obj);
}); });
createStepTwo(data).then((res) => { createStepTwo(data).then((res) => {
this.stepNum += 1; if (res.code === 200 || res.code === 0) {
this.$emit('setSN', this.stepNum); this.stepNum += 1;
this.getThreeGroup(7); // 第三步,进来加载预览排班,默认7天预览周期 this.$emit('setSN', this.stepNum);
this.getThreeGroup(7); // 第三步,进来加载预览排班,默认7天预览周期
} else {
this.$message(res.msg);
}
}); });
return; return;
} }
@@ -799,7 +814,7 @@ export default {
data.groupPlanTeamBaseVOList = []; //排班-班组信息list data.groupPlanTeamBaseVOList = []; //排班-班组信息list
this.tableData2.forEach((item) => { this.tableData2.forEach((item) => {
const obj = { const obj = {
teamId: item.id, teamId: item.teamId || item.id,
name: item.name, name: item.name,
bindData: JSON.stringify(item.bindLineTree), bindData: JSON.stringify(item.bindLineTree),
}; };
@@ -943,6 +958,57 @@ export default {
return start1Min < end2Min && end1Min > start2Min; return start1Min < end2Min && end1Min > start2Min;
} }
}, },
/**
* 检查多个班次是否连续覆盖24小时
* @param {Array} shifts - 班次数组每个班次包含startTime和endTime
* @returns {boolean} 是否连续覆盖24小时
*/
isCover24Hours(shifts) {
if (!shifts || shifts.length === 0) return false;
const totalMinutes = 24 * 60;
// 将班次转换为时间段对象
const intervals = shifts.map((shift) => ({
start: this.timeToMinutes(shift.startTime),
end: this.timeToMinutes(shift.endTime),
}));
// 处理跨天情况如果结束时间小于开始时间加上24小时
const normalizedIntervals = intervals.map((interval) => {
let { start, end } = interval;
if (end < start) {
end += totalMinutes;
}
return { start, end, originalEnd: interval.end };
});
// 按开始时间排序
normalizedIntervals.sort((a, b) => a.start - b.start);
// 检查是否连续覆盖
let coveredUntil = normalizedIntervals[0].end;
let hasGap = false;
for (let i = 1; i < normalizedIntervals.length; i++) {
const current = normalizedIntervals[i];
// 如果当前班次的开始时间大于已覆盖的结束时间,说明有间隔
if (current.start > coveredUntil) {
hasGap = true;
break;
}
// 更新已覆盖的结束时间
coveredUntil = Math.max(coveredUntil, current.end);
}
// 检查是否覆盖完整的24小时
const firstStart = normalizedIntervals[0].start;
// 判断条件没有间隔且覆盖时间达到24小时
return !hasGap && coveredUntil - firstStart >= totalMinutes;
},
//编辑班次 //编辑班次
handleClick1(val) { handleClick1(val) {
this.addOrUpdateVisible1 = true; this.addOrUpdateVisible1 = true;
@@ -1023,7 +1089,7 @@ export default {
this.tableData1.forEach((item, index) => { this.tableData1.forEach((item, index) => {
item.sort = index + 1; item.sort = index + 1;
}); });
//修改班次时间后,需要判断时间是否有覆盖,且是否覆盖24小时,isTimeOverlap方法返回false才是校验通过 //修改班次时间后,需要判断时间是否有重叠,且是否24小时,isTimeOverlap方法返回false才是校验通过
if (this.dataForm.shiftType == 2) { if (this.dataForm.shiftType == 2) {
const twoClass = this.tableData1.map(({ startTime, endTime }) => ({ const twoClass = this.tableData1.map(({ startTime, endTime }) => ({
startTime, startTime,
@@ -1061,6 +1127,11 @@ export default {
); );
this.isClassTimePass = !(result1 || result2 || result3); this.isClassTimePass = !(result1 || result2 || result3);
} }
//修改班次时间后两班倒和三班倒需要判断时间是否连续覆盖24小时内
if (this.dataForm.shiftType > 1) {
this.covers24Hours = this.isCover24Hours(this.tableData1);
console.log(1111, this.covers24Hours);
}
this.cancel1(); this.cancel1();
}, },
refreshTableData2(val) { refreshTableData2(val) {
@@ -1069,39 +1140,45 @@ export default {
}, },
refreshTableData3(index, val) { refreshTableData3(index, val) {
this.tableData2[index].bindLineTree = val; this.tableData2[index].bindLineTree = val;
let lineName = ''; let lineName = this.setLineName(val);
lineName = this.setLineName(val);
if (lineName) { if (lineName) {
this.$set(this.tableData2[index], 'lineName', lineName); this.$set(this.tableData2[index], 'lineName', lineName.join(';'));
} }
this.cancel3(); this.cancel3();
}, },
//提取绑定的产线工段名展示出来 //提取绑定的产线工段名展示出来
setLineName(val) { setLineName(data) {
if (!val || val.length === 0) return ''; const paths = [];
const currentLevelNames = val.map((item) => item.name); const processNode = (node, currentPath = []) => {
const newPath = [...currentPath, node.name];
// 处理当前层级显示 if (node.children && node.children.length > 0) {
let currentDisplay = ''; // 检查子节点是否都是叶子节点
if (currentLevelNames.length > 1) { const allChildrenAreLeaves = node.children.every(
currentDisplay = `(${currentLevelNames.join(' 、 ')})`; (child) => !child.children || child.children.length === 0
} else { );
currentDisplay = currentLevelNames[0];
}
// 查找所有子节点(取第一个有子节点的元素) if (allChildrenAreLeaves && node.children.length > 1) {
const childNode = val.find( // 如果所有子节点都是叶子节点且多于1个用括号合并显示
(item) => item.children && item.children.length > 0 const leafNames = node.children
); .map((child) => child.name)
if (childNode) { .join(' 、 ');
const childPath = this.setLineName(childNode.children); paths.push(`${newPath.join('/')}/(${leafNames})`);
if (childPath) { } else if (allChildrenAreLeaves && node.children.length === 1) {
return `${currentDisplay} / ${childPath}`; // 只有一个叶子子节点,用括号显示
paths.push(`${newPath.join('/')}/${node.children[0].name}`);
} else {
// 继续处理子节点
node.children.forEach((child) => processNode(child, newPath));
}
} else {
// 没有子节点的节点如原片产线1用括号显示
paths.push(`${currentPath.join('/')}/${node.name}`);
} }
} };
data.forEach((node) => processNode(node));
return currentDisplay; return paths;
}, },
//第三步 //第三步
// 进来加载预览排班 // 进来加载预览排班

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2021-11-18 14:16:25 * @Date: 2021-11-18 14:16:25
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-10 16:07:01 * @LastEditTime: 2025-11-25 15:49:17
* @Description: * @Description:
--> -->
<template> <template>
@@ -62,9 +62,9 @@ export default {
}, },
processNode(node) { processNode(node) {
// 创建唯一ID类型-原始ID // 创建唯一ID类型-原始ID
const uniqueId = node.id + node.type; const uniqueId = node.type+'L'+node.id;
if (node.type > 0) { if (node.type > 0) {
node.fid = node.pid + node.type - 1; node.fid = (node.type - 1)+'L'+node.pid;
} }
return { return {

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-21 14:27:23 * @Date: 2025-10-21 14:27:23
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-10 17:07:54 * @LastEditTime: 2025-11-25 15:14:53
* @Description: * @Description:
--> -->
<template> <template>
@@ -73,7 +73,7 @@
:limit="10" :limit="10"
:table-data="tableData1"></base-table> :table-data="tableData1"></base-table>
<base-table <base-table
v-else v-else
:table-props="tableProps2" :table-props="tableProps2"
:page="1" :page="1"
:limit="10" :limit="10"
@@ -150,25 +150,45 @@ export default {
this.infoData = {}; this.infoData = {};
getPlan(id).then((res) => { getPlan(id).then((res) => {
this.infoData = res.data || {}; this.infoData = res.data || {};
this.tableData1 = res.data?.groupPlanClassesBaseVOList.sort((a, b) => a.sort - b.sort); this.tableData1 = res.data?.groupPlanClassesBaseVOList.sort(
(a, b) => a.sort - b.sort
);
this.tableData2 = res.data?.groupPlanTeamBaseVOList; this.tableData2 = res.data?.groupPlanTeamBaseVOList;
this.tableData2.forEach((item, index) => { this.tableData2.forEach((item, index) => {
let lineName = ''; let lineName = '';
lineName = this.setLineName(item.bindLineTree, lineName); if (item.isProduction) {
this.$set(this.tableData2[index], 'lineName', lineName.slice(0, -1)); lineName = this.setLineName(item.bindLineTree);
}
this.$set(this.tableData2[index], 'lineName', lineName);
}); });
}); });
}, },
//提取绑定的产线工段名展示出来 //提取绑定的产线工段名展示出来
setLineName(val, lineName) { setLineName(val) {
val.forEach((item) => { if (!val || val.length === 0) return '';
lineName += item.name + '';
if (item.children && item.children.length > 0) { const currentLevelNames = val.map((item) => item.name);
const childName = this.setLineName(item.children, lineName);
lineName = childName; // 处理当前层级显示
let currentDisplay = '';
if (currentLevelNames.length > 1) {
currentDisplay = `(${currentLevelNames.join(' 、 ')})`;
} else {
currentDisplay = currentLevelNames[0];
}
// 查找所有子节点(取第一个有子节点的元素)
const childNode = val.find(
(item) => item.children && item.children.length > 0
);
if (childNode) {
const childPath = this.setLineName(childNode.children);
if (childPath) {
return `${currentDisplay} / ${childPath}`;
} }
}); }
return lineName;
return currentDisplay;
}, },
}, },
}; };

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-13 15:07:24 * @Date: 2025-10-13 15:07:24
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-05 08:51:13 * @LastEditTime: 2025-11-28 09:56:09
* @Description: * @Description:
--> -->
<template> <template>
@@ -33,6 +33,7 @@
v-model="formInline.startDay" v-model="formInline.startDay"
size="small" size="small"
type="datetime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期时间"></el-date-picker> placeholder="选择日期时间"></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item label="结束时间" prop="endDay"> <el-form-item label="结束时间" prop="endDay">
@@ -40,6 +41,7 @@
v-model="formInline.endDay" v-model="formInline.endDay"
size="small" size="small"
type="datetime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期时间"></el-date-picker> placeholder="选择日期时间"></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item label="部门" prop="deptId"> <el-form-item label="部门" prop="deptId">
@@ -396,12 +398,12 @@ export default {
}, },
], ],
formInline: { formInline: {
code: '', code: null,
name: '', name: null,
startDay: '', startDay: null,
endDay: '', endDay: null,
deptId: '', deptId: null,
status: '', status: null,
}, },
stepNum: 1, // 新增编辑时当前第几步 stepNum: 1, // 新增编辑时当前第几步
detailVisible: false, detailVisible: false,
@@ -419,29 +421,29 @@ export default {
buttonClick(val) { buttonClick(val) {
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
const date1 = new Date(this.formInline.startDay).getTime(); if (this.formInline.startDay > this.formInline.endDay) {
const date2 = new Date(this.formInline.endDay).getTime();
if (date1 > date2) {
this.$message('开始时间不得晚于结束时间'); this.$message('开始时间不得晚于结束时间');
return; return;
} }
this.listQuery = { this.listQuery = {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 20,
total: 1, total: 1,
...this.formInline, ...this.formInline,
}; };
this.getDataList(); this.getDataList();
break; break;
case 'reset': case 'reset':
this.$refs.searchBarForm.resetFields();
this.formInline.name = null; this.formInline.name = null;
this.formInline.code = null; this.formInline.code = null;
this.formInline.deptId = null; this.formInline.deptId = null;
this.$refs.deptSelect.clear(); this.$refs.deptSelect.clear();
this.formInline.status = null; this.formInline.status = null;
this.formInline.startDay = null;
this.formInline.endDay = null;
this.listQuery = { this.listQuery = {
pageSize: 10, pageSize: 20,
pageNo: 1, pageNo: 1,
total: 1, total: 1,
}; };
@@ -490,7 +492,8 @@ export default {
this.addOrUpdateVisible = true; this.addOrUpdateVisible = true;
this.addOrEditTitle = '编辑'; this.addOrEditTitle = '编辑';
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.addOrUpdate.init(val.data.id,true); this.stepNum = 3;
this.$refs.addOrUpdate.init(val.data.id, true);
}); });
} else if (val.type === 'delete') { } else if (val.type === 'delete') {
this.deleteHandle(val.data.id, val.data.name, val.data._pageIndex); this.deleteHandle(val.data.id, val.data.name, val.data._pageIndex);
@@ -505,13 +508,31 @@ export default {
this.getDataList(); this.getDataList();
}); });
} else if (val.type === 'sync') { } else if (val.type === 'sync') {
updateScheduleLater({ this.$confirm(
planId: val.data.id, '当前节假日包含尚未同步的节假日变更,是否立即将上述节假日同步更新到排班计划?',
logId: val.data.updateLogId, '同步节假日',
}).then((res) => { {
this.$modal.msgSuccess('同步节假日成功'); confirmButtonText: '确认同步',
this.getDataList(); cancelButtonText: '取消',
}); type: 'warning',
}
)
.then(() => {
updateScheduleLater({
planId: val.data.id,
logId: val.data.updateLogId,
}).then((res) => {
this.$modal.msgSuccess('同步节假日成功');
this.getDataList();
});
})
.catch((res) => {
this.getDataList();
this.$message({
type: 'info',
message: '已取消',
});
});
} else if (val.type === 'copy') { } else if (val.type === 'copy') {
copyPlan(val.data.id).then((res) => { copyPlan(val.data.id).then((res) => {
this.$modal.msgSuccess('复制成功'); this.$modal.msgSuccess('复制成功');

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2021-11-18 14:16:25 * @Date: 2021-11-18 14:16:25
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-10-31 15:47:16 * @LastEditTime: 2025-11-27 14:49:34
* @Description: * @Description:
--> -->
<template> <template>
@@ -25,6 +25,7 @@
<el-col :span="8"> <el-col :span="8">
<el-form-item label="班组名称" prop="name"> <el-form-item label="班组名称" prop="name">
<el-input <el-input
:disabled="nameDisable"
v-model="dataForm.name" v-model="dataForm.name"
clearable clearable
placeholder="请输入班组名称" /> placeholder="请输入班组名称" />
@@ -78,6 +79,7 @@
<el-form-item label="生产班组" prop="isProduction"> <el-form-item label="生产班组" prop="isProduction">
<el-select <el-select
style="width: 100%" style="width: 100%"
@change="setIsProduction"
v-model="dataForm.isProduction" v-model="dataForm.isProduction"
placeholder="请选择是否为生产班组"> placeholder="请选择是否为生产班组">
<el-option <el-option
@@ -109,6 +111,7 @@ import {
updateGroup, updateGroup,
getGroup, getGroup,
getCode, getCode,
updateIsProduction,
} from '@/api/group/groupSetting'; } from '@/api/group/groupSetting';
export default { export default {
@@ -139,6 +142,7 @@ export default {
remark: undefined, remark: undefined,
}, },
setData: true, setData: true,
nameDisable: false, //班组被使用时,班组名称不能修改
leaderArr: [], leaderArr: [],
options: [ options: [
{ {
@@ -157,9 +161,7 @@ export default {
name: [ name: [
{ required: true, message: '班组名称不能为空', trigger: 'blur' }, { required: true, message: '班组名称不能为空', trigger: 'blur' },
], ],
deptId: [ deptId: [{ required: true, message: '部门不能为空', trigger: 'blur' }],
{ required: true, message: '部门不能为空', trigger: 'blur' },
],
leaderId: [ leaderId: [
{ required: true, message: '组长不能为空', trigger: 'change' }, { required: true, message: '组长不能为空', trigger: 'change' },
], ],
@@ -191,6 +193,40 @@ export default {
}, },
setDataForm() { setDataForm() {
this.$refs.deptSelect.setID(this.dataForm.deptId); this.$refs.deptSelect.setID(this.dataForm.deptId);
this.nameDisable = false;
updateIsProduction(this.dataForm.id).then(({ data }) => {
if (data) {
this.$notify({
title: '警告',
message: '当前班组仍参与排班计划或正在执行工单。班组名称不能修改',
type: 'warning',
});
this.nameDisable = true;
}
});
},
setIsProduction() {
// 修改的提交
if (this.dataForm.id && this.nameDisable) {
this.$confirm(
'当前班组仍参与排班计划或正在执行工单。<br/>修改<strong> 是否是生产班组 </strong>不会自动更新排班内容,可能导致排班信息与班组属性不一致,请注意核查!<br/>是否确认修改是否是生产班组?',
'修改是否是生产班组',
{
dangerouslyUseHTMLString: true,
confirmButtonText: '确认修改',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {})
.catch((res) => {
this.$message({
type: 'info',
message: '已取消',
});
this.dataForm.isProduction = !this.dataForm.isProduction;
});
}
}, },
setLeaderName(val) { setLeaderName(val) {
this.leaderArr.map((item) => { this.leaderArr.map((item) => {

View File

@@ -1,14 +1,21 @@
<!--
* @Author: zwq
* @Date: 2025-10-11 14:41:12
* @LastEditors: zwq
* @LastEditTime: 2025-11-27 14:19:39
* @Description:
-->
<template> <template>
<el-switch <el-switch
@change="changeStatus" @change="changeStatus"
size="small" size="small"
v-model="list.enabled" v-model="injectData.enabled"
:active-value="1" :active-value="1"
:inactive-value="0"></el-switch> :inactive-value="0"></el-switch>
</template> </template>
<script> <script>
import { updateGroup } from '@/api/group/groupSetting'; import { updateGroup, updateIsProduction } from '@/api/group/groupSetting';
export default { export default {
props: { props: {
injectData: { injectData: {
@@ -17,17 +24,51 @@ export default {
}, },
}, },
data() { data() {
return { return {};
list: this.injectData,
};
}, },
created() {}, created() {},
methods: { methods: {
changeStatus(val) { changeStatus(val) {
const data = { ...this.injectData, enabled: val }; const pdata = { ...this.injectData, enabled: val };
updateGroup(data).then((res) => { updateIsProduction(this.injectData.id).then(({ data }) => {
this.$modal.msgSuccess('修改成功'); if (data) {
this.$emit('emitData'); this.$confirm(
'当前班组仍参与排班计划或正在执行工单。<br/>修改<strong> 班组状态 </strong>不会自动更新排班内容,可能导致排班信息与班组属性不一致,请注意核查!<br/>是否确认修改班组状态?',
'更新班组状态',
{
dangerouslyUseHTMLString: true,
confirmButtonText: '确认修改',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
updateGroup(pdata).then((res) => {
if (res.code === 0 || res.code === 200) {
this.$modal.msgSuccess('修改成功');
this.$emit('emitData');
} else {
this.$modal.msg(res.msg);
}
});
})
.catch((res) => {
this.$emit('emitData');
this.$message({
type: 'info',
message: '已取消',
});
});
} else {
updateGroup(pdata).then((res) => {
if (res.code === 0 || res.code === 200) {
this.$modal.msgSuccess('修改成功');
this.$emit('emitData');
} else {
this.$modal.msg(res.msg);
}
});
}
}); });
}, },
}, },

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2025-10-11 14:27:37 * @Date: 2025-10-11 14:27:37
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-10-29 14:44:41 * @LastEditTime: 2025-11-14 21:50:40
* @Description: * @Description:
--> -->
<template> <template>
@@ -212,7 +212,7 @@ export default {
case 'search': case 'search':
this.listQuery = { this.listQuery = {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 20,
total: 1, total: 1,
...this.formInline, ...this.formInline,
}; };
@@ -225,7 +225,7 @@ export default {
this.$refs.deptSelect.clear(); this.$refs.deptSelect.clear();
this.formInline.leaderName = null; this.formInline.leaderName = null;
this.listQuery = { this.listQuery = {
pageSize: 10, pageSize: 20,
pageNo: 1, pageNo: 1,
total: 1, total: 1,
}; };

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2021-11-18 14:16:25 * @Date: 2021-11-18 14:16:25
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-11 10:29:18 * @LastEditTime: 2025-11-27 14:06:11
* @Description: * @Description:
--> -->
<template> <template>
@@ -213,6 +213,7 @@ export default {
deptId: undefined, deptId: undefined,
}, },
detail: false, detail: false,
inherited: true,
options1: [ options1: [
{ {
value: 1, value: 1,
@@ -330,11 +331,12 @@ export default {
}); });
}, },
methods: { methods: {
init(deptId, val, detail) { init(deptId, val, detail, inherited) {
this.dataForm.deptId = deptId || undefined; this.dataForm.deptId = deptId || undefined;
this.dataForm.id = val.holidayId || undefined; this.dataForm.id = val.holidayId || undefined;
this.dataForm.inherited = val.isInherit || false; this.dataForm.inherited = val.isInherit || false;
this.detail = detail || false; this.detail = detail || false;
this.inherited = inherited; //编辑的时候该部门如果是自定义的但这个val数据是继承的修改之后则变成自定义的inherited
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['dataForm'].resetFields(); this.$refs['dataForm'].resetFields();
if (this.dataForm.id) { if (this.dataForm.id) {
@@ -469,6 +471,9 @@ export default {
} }
// 修改的提交 // 修改的提交
if (this.dataForm.id) { if (this.dataForm.id) {
if (!this.inherited) {
this.dataForm.inherited = false;
}
updateHoliday(this.dataForm).then((res) => { updateHoliday(this.dataForm).then((res) => {
if (!res.data.updateFlag) { if (!res.data.updateFlag) {
this.$modal.msgSuccess('修改成功'); this.$modal.msgSuccess('修改成功');

View File

@@ -2,283 +2,284 @@
* @Author: zwq * @Author: zwq
* @Date: 2024-07-01 14:54:06 * @Date: 2024-07-01 14:54:06
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2025-11-11 14:29:10 * @LastEditTime: 2025-11-24 16:11:20
* @Description: * @Description:
--> -->
<template> <template>
<el-row :gutter="10" style="background-color: #f2f4f9"> <div
<!--部门数据--> class="app-container"
<el-col :span="4"> style="
<div class="head-container"> background-color: #f2f4f9;
<el-input padding: 0;
v-model="deptName" display: grid;
placeholder="请输入部门名称" grid-template-columns: 1fr 5fr;
clearable gap: 10px;
size="small" ">
prefix-icon="el-icon-search" <div class="head-container">
style="margin-bottom: 20px" /> <el-input
<el-tree v-model="deptName"
:data="deptOptions" placeholder="请输入部门名称"
:props="defaultProps" clearable
:expand-on-click-node="false" size="small"
:filter-node-method="filterNode" prefix-icon="el-icon-search"
ref="tree" style="margin-bottom: 20px" />
default-expand-all <el-tree
highlight-current :data="deptOptions"
@node-click="handleNodeClick" /> :props="defaultProps"
</div> :expand-on-click-node="false"
</el-col> :filter-node-method="filterNode"
<el-col :span="20"> ref="tree"
<div class="groupTeamScheduling"> node-key="id"
<div class="operationArea"> default-expand-all
<el-row> highlight-current
<el-col :span="6"> @node-click="handleNodeClick" />
<div style="height: 40px; font-size: 16px"> </div>
<span style="color: #409eff; font-weight: 600"> <div class="groupTeamScheduling">
{{ showDeptName }} <div class="operationArea">
</span> <el-row>
节假日设置 <el-col :span="6">
<span <div style="height: 40px; font-size: 16px">
:style="{ <span style="color: #409eff; font-weight: 600">
color: inherited ? '#67c23a' : '#b5b839', {{ showDeptName }}
fontSize: '12px', </span>
fontWeight: 600, 节假日设置
}" <span
v-show="ishasParent"> :style="{
{{ inherited ? '继承模式' : '自定义模式' }} color: inherited ? '#67c23a' : '#b5b839',
</span> fontSize: '12px',
</div> fontWeight: 600,
</el-col> }"
<el-col :span="18" v-if="!ishasParent"> v-show="ishasParent">
<div style="float: right"> {{ inherited ? '继承模式' : '自定义模式' }}
<el-button </span>
size="small" </div>
type="primary" </el-col>
style="margin-right: 10px" <el-col :span="18" v-if="!ishasParent">
v-hasPermi="['base:group-holiday:create']" <div style="float: right">
@click="addHoliday">
新增节假日
</el-button>
<el-button
size="small"
v-hasPermi="['base:group-holiday-log:query']"
@click="holidayLog">
节假日变更记录
</el-button>
</div>
</el-col>
<el-col :span="18" v-else style="text-align: right">
<el-button <el-button
size="small" size="small"
type="primary" type="primary"
:disabled="inherited" style="margin-right: 10px"
v-hasPermi="['base:group-holiday:create']" v-hasPermi="['base:group-holiday:create']"
@click="addHoliday"> @click="addHoliday">
新增节假日 新增节假日
</el-button> </el-button>
<el-button <el-button
size="small" size="small"
type="success"
:disabled="inherited"
v-hasPermi="['base:group-holiday:update']"
@click="reExtends">
恢复继承
</el-button>
<el-button
size="small"
type="warning"
:disabled="!inherited"
v-hasPermi="['base:group-holiday:update']"
@click="disExtends">
解除继承
</el-button>
<el-button
size="small"
:disabled="inherited"
v-hasPermi="['base:group-holiday-log:query']" v-hasPermi="['base:group-holiday-log:query']"
@click="holidayLog"> @click="holidayLog">
节假日变更记录 节假日变更记录
</el-button> </el-button>
</el-col> </div>
</el-row> </el-col>
<el-col :span="18" v-else style="text-align: right">
<el-button
size="small"
type="primary"
:disabled="inherited"
v-hasPermi="['base:group-holiday:create']"
@click="addHoliday">
新增节假日
</el-button>
<el-button
size="small"
type="success"
:disabled="inherited"
v-hasPermi="['base:group-holiday:update']"
@click="reExtends">
恢复继承
</el-button>
<el-button
size="small"
type="warning"
:disabled="!inherited"
v-hasPermi="['base:group-holiday:update']"
@click="disExtends">
解除继承
</el-button>
<el-button
size="small"
:disabled="inherited"
v-hasPermi="['base:group-holiday-log:query']"
@click="holidayLog">
节假日变更记录
</el-button>
</el-col>
</el-row>
</div>
<div class="operationArea">
<el-form :inline="true" class="demo-form-inline">
<span class="blue-block"></span>
<el-form-item label="月份选择">
<el-date-picker
v-model="startDay"
type="month"
placeholder="选择月"
size="small"
@change="selectMonth"
:clearable="false"
style="width: 120px"></el-date-picker>
</el-form-item>
<el-form-item label="继承上一级的节假日" v-show="ishasParent">
<div
style="
width: 36px;
height: 36px;
background-color: #67c23a;
border-radius: 3px;
"></div>
</el-form-item>
<el-form-item label="本级自定义的节假日" v-show="ishasParent">
<div
style="
width: 36px;
height: 36px;
background-color: #b5b839;
border-radius: 3px;
"></div>
</el-form-item>
<el-form-item style="float: right">
<el-button
size="small"
type="primary"
@click="(startDay = new Date()), getHolidayPage()">
跳转到今天
</el-button>
</el-form-item>
</el-form>
<div v-if="!ishasParent">
<el-tag
type="warning"
closable
v-if="showTag1"
@close="handleClose(1)"
style="margin-bottom: 10px; color: black">
<i class="el-icon-warning" style="color: #ffbd02"></i>
当前节假日设置为组织架构中最高层级配置默认自动继承至下属部门子部门可选择
<span style="color: red">解除继承</span>
设置后进行独立修改解除后不再继承上级设置
</el-tag>
</div> </div>
<div class="operationArea"> <div v-else>
<el-form :inline="true" class="demo-form-inline"> <div v-if="inherited">
<span class="blue-block"></span>
<el-form-item label="月份选择">
<el-date-picker
v-model="startDay"
type="month"
placeholder="选择月"
size="small"
@change="selectMonth"
:clearable="false"
style="width: 120px"></el-date-picker>
</el-form-item>
<el-form-item label="继承上一级的节假日" v-show="ishasParent">
<div
style="
width: 36px;
height: 36px;
background-color: #67c23a;
border-radius: 3px;
"></div>
</el-form-item>
<el-form-item label="本级自定义的节假日" v-show="ishasParent">
<div
style="
width: 36px;
height: 36px;
background-color: #b5b839;
border-radius: 3px;
"></div>
</el-form-item>
<el-form-item style="float: right">
<el-button
size="small"
type="primary"
@click="(startDay = new Date()), getHolidayPage()">
跳转到今天
</el-button>
</el-form-item>
</el-form>
<div v-if="!ishasParent">
<el-tag <el-tag
type="warning" type="warning"
closable closable
v-if="showTag1" v-if="showTag2"
@close="handleClose(1)" @close="handleClose(2)"
style="margin-bottom: 10px; color: black"> style="margin-bottom: 10px; color: black">
<i class="el-icon-warning" style="color: #ffbd02"></i> <i class="el-icon-warning" style="color: #ffbd02"></i>
当前节假日设置为组织架构中最高层级配置默认自动继承至下属部门子部门可选择 当前部门继承上级节假日设置默认不可修改可通过
<span style="color: red">解除继承</span> <span style="color: red">解除继承</span>
设置后进行独立修改解除后不再继承上级设置 进行自定义解除后不再继承
</el-tag> </el-tag>
</div> </div>
<div v-else> <div v-else>
<div v-if="inherited"> <el-tag
<el-tag type="warning"
type="warning" closable
closable v-if="showTag3"
v-if="showTag2" @close="handleClose(3)"
@close="handleClose(2)" style="margin-bottom: 10px; color: black">
style="margin-bottom: 10px; color: black"> <i class="el-icon-warning" style="color: #ffbd02"></i>
<i class="el-icon-warning" style="color: #ffbd02"></i> 当前部门已解除继承节假日可自由配置点击
当前部门继承上级节假日设置默认不可修改可通过 <span style="color: red">恢复继承</span>
<span style="color: red">解除继承</span> 将清空当前设置并同步上级节假日
进行自定义解除后将不再继承 </el-tag>
</el-tag>
</div>
<div v-else>
<el-tag
type="warning"
closable
v-if="showTag3"
@close="handleClose(3)"
style="margin-bottom: 10px; color: black">
<i class="el-icon-warning" style="color: #ffbd02"></i>
当前部门已解除继承节假日可自由配置点击
<span style="color: red">恢复继承</span>
将清空当前设置并同步上级节假日
</el-tag>
</div>
</div> </div>
</div> </div>
<!-- 日历区域 --> </div>
<div class="calenderArea"> <!-- 日历区域 -->
<el-calendar v-model="startDay"> <div class="calenderArea">
<template slot="dateCell" slot-scope="{ data }"> <el-calendar v-model="startDay">
<div v-if="data.type === 'current-month'"> <template slot="dateCell" slot-scope="{ data }">
<!-- 日期 --> <div v-if="data.type === 'current-month'">
<div <!-- 日期 -->
class="dateStyle" <div
@click=" class="dateStyle"
new Date(data.day).getTime() >= @click="
new Date().setHours(0, 0, 0, 0) && new Date(data.day).getTime() >=
(!ishasParent || !inherited) && new Date().setHours(0, 0, 0, 0) &&
HolidayList[Number(data.day.split('-')[2]) - 1] (!ishasParent || !inherited) &&
?.isHoliday && HolidayList[Number(data.day.split('-')[2]) - 1]
showDetail( ?.isHoliday &&
HolidayList[Number(data.day.split('-')[2]) - 1] showDetail(HolidayList[Number(data.day.split('-')[2]) - 1])
) ">
"> <el-row :gutter="20">
<el-row :gutter="20"> <!-- 公历和农历 -->
<!-- 公历和农历 --> <el-col :span="18">
<el-col :span="18"> {{ Number(data.day.split('-')[2]) }}
{{ Number(data.day.split('-')[2]) }} <div class="lunar-date">{{ getLunarDate(data.day) }}</div>
<div class="lunar-date">{{ getLunarDate(data.day) }}</div> </el-col>
</el-col> <!-- 显示假或班 -->
<!-- 显示假或班 --> <el-col :span="6">
<el-col :span="6"> <div
<div class="work-tip"
class="work-tip" :style="{
:style="{ backgroundColor: HolidayList[
backgroundColor: HolidayList[ Number(data.day.split('-')[2]) - 1
Number(data.day.split('-')[2]) - 1 ]?.isHoliday
]?.isHoliday ? '#67C23A'
? '#67C23A' : '#409EFF',
: '#409EFF', }">
}"> {{
{{
HolidayList[Number(data.day.split('-')[2]) - 1]
?.isHoliday
? '假'
: '班'
}}
</div>
</el-col>
<!-- 显示假期名和操作 -->
<el-col
:span="24"
v-if="
HolidayList[Number(data.day.split('-')[2]) - 1] HolidayList[Number(data.day.split('-')[2]) - 1]
?.isHoliday ?.isHoliday
"> ? '假'
<div : '班'
class="holiday-div" }}
:style="{ </div>
backgroundColor: ishasParent </el-col>
? HolidayList[Number(data.day.split('-')[2]) - 1] <!-- 显示假期名和操作 -->
.isInherit <el-col
? '#67c23a' :span="24"
: '#b5b839' v-if="
: '', HolidayList[Number(data.day.split('-')[2]) - 1]?.isHoliday
}"> ">
{{ <div
HolidayList[Number(data.day.split('-')[2]) - 1] class="holiday-div"
?.holidayName :style="{
}} backgroundColor: ishasParent
<span ? HolidayList[Number(data.day.split('-')[2]) - 1]
class="holiday-div-btn" .isInherit
v-if=" ? '#67c23a'
(!ishasParent || !inherited) && : '#b5b839'
new Date(data.day).getTime() >= : '',
new Date().setHours(0, 0, 0, 0) }">
"> {{
<i class="el-icon-more" style="color: #fff"></i> HolidayList[Number(data.day.split('-')[2]) - 1]
</span> ?.holidayName
</div> }}
</el-col> <span
</el-row> class="holiday-div-btn"
</div> v-if="
</div> (!ishasParent || !inherited) &&
<div new Date(data.day).getTime() >=
v-else new Date().setHours(0, 0, 0, 0)
style="font-size: 20px; font-weight: 500; text-align: left"> ">
<el-row :gutter="20"> <i class="el-icon-more" style="color: #fff"></i>
<el-col :span="24"> </span>
{{ Number(data.day.split('-')[2]) }} </div>
<span style="font-size: 12px">
{{ getLunarDate(data.day) }}
</span>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</template> </div>
</el-calendar> <div
</div> v-else
style="font-size: 20px; font-weight: 500; text-align: left">
<el-row :gutter="20">
<el-col :span="24">
{{ Number(data.day.split('-')[2]) }}
<span style="font-size: 12px">
{{ getLunarDate(data.day) }}
</span>
</el-col>
</el-row>
</div>
</template>
</el-calendar>
</div> </div>
</el-col> </div>
<base-dialog <base-dialog
:dialogTitle="dialogTitle" :dialogTitle="dialogTitle"
:dialogVisible="addOrUpdateVisible" :dialogVisible="addOrUpdateVisible"
@@ -352,7 +353,7 @@
</slot> </slot>
</template> </template>
</base-dialog> </base-dialog>
</el-row> </div>
</template> </template>
<script> <script>
@@ -453,13 +454,43 @@ export default {
// 遍历部门,判断当前帐号的部门是否有为最上级 // 遍历部门,判断当前帐号的部门是否有为最上级
const nowDept = response.data.filter((i) => i.id == this.topDeptId); const nowDept = response.data.filter((i) => i.id == this.topDeptId);
this.ishasParent = nowDept[0].hasParent; this.ishasParent = nowDept[0].hasParent;
this.parentId = nowDept.parentId; this.parentId = nowDept[0].parentId;
// 处理 deptOptions 参数 // 处理 deptOptions 参数
this.deptOptions = []; this.deptOptions = [];
this.deptOptions.push(...this.handleTree(response.data, 'id')); this.deptOptions.push(...this.handleTree1(response.data, 'id'));
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.deptId);
});
}); });
}, },
//大整数精度丢失
handleTree1(data, fid) {
const id = fid || 'id';
const parentId = 'parentId';
const children = 'children';
const rootId =
data
.map((item) => item[parentId].toString())
.reduce((min, current) => {
if (current.length < min.length) return current;
if (current.length > min.length) return min;
return current < min ? current : min;
}) || 0;
//对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data));
//循环所有项
const treeData = cloneData.filter((father) => {
let branchArr = cloneData.filter((child) => {
//返回每一项的子级数组
return father[id] == child[parentId];
});
branchArr.length > 0 ? (father.children = branchArr) : '';
//返回第一层
return father[parentId] == rootId;
});
return treeData !== '' ? treeData : data;
},
// 根据部门id查询该部门是否是继承 // 根据部门id查询该部门是否是继承
getSet() { getSet() {
getSet({ id: this.deptId }).then((res) => { getSet({ id: this.deptId }).then((res) => {
@@ -643,6 +674,7 @@ export default {
type: 'info', type: 'info',
message: '已取消', message: '已取消',
}); });
this.getSet();
}); });
} }
}); });
@@ -676,7 +708,7 @@ export default {
this.detail = true; this.detail = true;
this.dialogTitle = '节假日详情'; this.dialogTitle = '节假日详情';
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.addOrUpdataRef.init(this.deptId, val, true); this.$refs.addOrUpdataRef.init(this.deptId, val, true, this.inherited); //编辑的时候该部门如果是自定义的但这个val数据是继承的修改之后则变成自定义的inherited
}); });
}, },
editHoliday() { editHoliday() {
@@ -709,7 +741,7 @@ export default {
.head-container { .head-container {
padding: 20px 10px 0; padding: 20px 10px 0;
background-color: #fff; background-color: #fff;
min-height: calc(100vh - 120px - 8px); height: 100%;
border-radius: 8px; border-radius: 8px;
} }
.groupTeamScheduling { .groupTeamScheduling {