|
@@ -279,7 +279,12 @@
|
|
|
</el-popover>
|
|
</el-popover>
|
|
|
<div ref="scheduleContent" class="schedule-content">
|
|
<div ref="scheduleContent" class="schedule-content">
|
|
|
<div ref="sidebar" class="ordinate" :style="{ top: topOffset + 'px' }">
|
|
<div ref="sidebar" class="ordinate" :style="{ top: topOffset + 'px' }">
|
|
|
- <div v-for="item in ordinateList" :key="item.value" class="ordinate-item">
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="item in ordinateList"
|
|
|
|
|
+ :key="item.value"
|
|
|
|
|
+ class="ordinate-item"
|
|
|
|
|
+ :style="{ color: viewType === 'users' ? '#606266' : `${item.color}`, height:viewType === 'users' ? '60px' : '130px' }"
|
|
|
|
|
+ >
|
|
|
{{ item.label }}
|
|
{{ item.label }}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -292,6 +297,7 @@
|
|
|
:key="cIndex"
|
|
:key="cIndex"
|
|
|
ref="shiftItem"
|
|
ref="shiftItem"
|
|
|
class="shift-item"
|
|
class="shift-item"
|
|
|
|
|
+ :style="{ display: viewType === 'users' ? 'grid' : 'flex', height:viewType === 'users' ? '59px' : '129px'}"
|
|
|
@mouseenter="hoveredIndex = `${row.value}-${cIndex}`"
|
|
@mouseenter="hoveredIndex = `${row.value}-${cIndex}`"
|
|
|
@mouseleave="hoveredIndex = null"
|
|
@mouseleave="hoveredIndex = null"
|
|
|
@click.prevent="handleShiftClick($event, {row, rIndex, column, cIndex})"
|
|
@click.prevent="handleShiftClick($event, {row, rIndex, column, cIndex})"
|
|
@@ -300,9 +306,9 @@
|
|
|
v-for="(shift, sIndex) in scheduleData[row.value][cIndex]"
|
|
v-for="(shift, sIndex) in scheduleData[row.value][cIndex]"
|
|
|
:key="sIndex"
|
|
:key="sIndex"
|
|
|
class="shift"
|
|
class="shift"
|
|
|
- :style="{ color: `${shift.color}` }"
|
|
|
|
|
|
|
+ :style="{ color: viewType === 'users' ? `${shift.color}` : `${ordinateList[rIndex].color}`}"
|
|
|
>
|
|
>
|
|
|
- {{ shift.alias }}
|
|
|
|
|
|
|
+ {{ viewType === 'users'? shift.alias : shift.userName }}
|
|
|
<!-- <div :style="{ color: `${shift.color}` }">{{ shift.alias }}</div> -->
|
|
<!-- <div :style="{ color: `${shift.color}` }">{{ shift.alias }}</div> -->
|
|
|
</div>
|
|
</div>
|
|
|
<div v-if="hoveredIndex === `${row.value}-${cIndex}` && !readonly" class="overlay">
|
|
<div v-if="hoveredIndex === `${row.value}-${cIndex}` && !readonly" class="overlay">
|
|
@@ -324,9 +330,10 @@
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
<context-menu
|
|
<context-menu
|
|
|
|
|
+ :viewType="viewType"
|
|
|
:visible.sync="contextMenuVisible"
|
|
:visible.sync="contextMenuVisible"
|
|
|
:params="shiftParams"
|
|
:params="shiftParams"
|
|
|
- :shift-list="shiftList"
|
|
|
|
|
|
|
+ :shift-list="viewType === 'users' ? shiftList : userNameList"
|
|
|
:position="itemPosition"
|
|
:position="itemPosition"
|
|
|
:item-data="selectItem"
|
|
:item-data="selectItem"
|
|
|
:readonly="readonly"
|
|
:readonly="readonly"
|
|
@@ -354,6 +361,9 @@ import { previewFile } from '@/api/platform/file/attachment'
|
|
|
import { mapValues, keyBy } from 'lodash'
|
|
import { mapValues, keyBy } from 'lodash'
|
|
|
import html2canvas from 'html2canvas'
|
|
import html2canvas from 'html2canvas'
|
|
|
import ActionUtils from '@/utils/action'
|
|
import ActionUtils from '@/utils/action'
|
|
|
|
|
+import Json from '@/business/platform/serv/components/json.vue'
|
|
|
|
|
+import color from '@/store/modules/ibps/modules/color'
|
|
|
|
|
+import height from '@/mixins/height'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
name: 'schedule',
|
|
name: 'schedule',
|
|
@@ -420,6 +430,8 @@ export default {
|
|
|
],
|
|
],
|
|
|
viewType: 'users',
|
|
viewType: 'users',
|
|
|
scheduleData: {},
|
|
scheduleData: {},
|
|
|
|
|
+ responseData: {},
|
|
|
|
|
+ userNameList: [],
|
|
|
scheduleRecord: [],
|
|
scheduleRecord: [],
|
|
|
leftOffset: '',
|
|
leftOffset: '',
|
|
|
topOffset: '',
|
|
topOffset: '',
|
|
@@ -465,11 +477,19 @@ export default {
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
ordinateList () {
|
|
ordinateList () {
|
|
|
- const { scheduleStaff } = this.formData
|
|
|
|
|
- return this.userList.filter(u => scheduleStaff.includes(u.userId)).map(u => ({
|
|
|
|
|
- label: u.userName,
|
|
|
|
|
- value: u.userId
|
|
|
|
|
- }))
|
|
|
|
|
|
|
+ if (this.viewType === 'users') {
|
|
|
|
|
+ const { scheduleStaff } = this.formData
|
|
|
|
|
+ return this.userList.filter(u => scheduleStaff.includes(u.userId)).map(u => ({
|
|
|
|
|
+ label: u.userName,
|
|
|
|
|
+ value: u.userId
|
|
|
|
|
+ }))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return this.formData.scheduleShift.map(s => ({
|
|
|
|
|
+ label: s.name,
|
|
|
|
|
+ value: s.alias,
|
|
|
|
|
+ color: s.color
|
|
|
|
|
+ }))
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
// scheduleData () {
|
|
// scheduleData () {
|
|
|
// return mapValues(keyBy(this.ordinateList, 'value'), () => Array.from({ length: this.dateList.length }, () => []))
|
|
// return mapValues(keyBy(this.ordinateList, 'value'), () => Array.from({ length: this.dateList.length }, () => []))
|
|
@@ -550,6 +570,7 @@ export default {
|
|
|
const response = await getStaffSchedule({ id: this.pageParams.id })
|
|
const response = await getStaffSchedule({ id: this.pageParams.id })
|
|
|
const { staffScheduleDetailPoList: records, title, endDate, startDate, type, overview, config, status } = response.data
|
|
const { staffScheduleDetailPoList: records, title, endDate, startDate, type, overview, config, status } = response.data
|
|
|
const temp = config ? JSON.parse(config) : {}
|
|
const temp = config ? JSON.parse(config) : {}
|
|
|
|
|
+ this.responseData = response.data
|
|
|
console.log('responseData:', response.data)
|
|
console.log('responseData:', response.data)
|
|
|
console.log('configData:', temp)
|
|
console.log('configData:', temp)
|
|
|
this.formData = {
|
|
this.formData = {
|
|
@@ -558,6 +579,7 @@ export default {
|
|
|
config: temp.id,
|
|
config: temp.id,
|
|
|
dateRange: [startDate, endDate],
|
|
dateRange: [startDate, endDate],
|
|
|
approver: temp.approver || [],
|
|
approver: temp.approver || [],
|
|
|
|
|
+ overview: overview,
|
|
|
scheduleType: type,
|
|
scheduleType: type,
|
|
|
scheduleRule: temp.scheduleRule || [],
|
|
scheduleRule: temp.scheduleRule || [],
|
|
|
scheduleShift: temp.scheduleShift || [],
|
|
scheduleShift: temp.scheduleShift || [],
|
|
@@ -574,6 +596,10 @@ export default {
|
|
|
this.scheduleData = this.transformScheduleData(records, overview, temp)
|
|
this.scheduleData = this.transformScheduleData(records, overview, temp)
|
|
|
console.log('scheduleData', this.scheduleData)
|
|
console.log('scheduleData', this.scheduleData)
|
|
|
this.loading = false
|
|
this.loading = false
|
|
|
|
|
+ this.userNameList = this.ordinateList.map(item => ({ // 存起user对应id和name
|
|
|
|
|
+ userName: item.label,
|
|
|
|
|
+ userId: item.value
|
|
|
|
|
+ }))
|
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
|
this.loading = false
|
|
this.loading = false
|
|
|
})
|
|
})
|
|
@@ -623,6 +649,58 @@ export default {
|
|
|
})
|
|
})
|
|
|
return result
|
|
return result
|
|
|
},
|
|
},
|
|
|
|
|
+ /* 切换ScheduleData为人员排班数据格式(人员排班->班次排班)
|
|
|
|
|
+ */
|
|
|
|
|
+ transformScheduleDataForShiftsView (data, userList, scheduleShift, overview) {
|
|
|
|
|
+ const result = []
|
|
|
|
|
+ const temp = overview ? JSON.parse(overview) : {}
|
|
|
|
|
+ // 先创建以排班班次为键的空二维数组
|
|
|
|
|
+ scheduleShift.forEach(shift => {
|
|
|
|
|
+ result[shift.alias] = Array.from({ length: temp.dateCount }, () => [])
|
|
|
|
|
+ })
|
|
|
|
|
+ // 再次遍历用户列表,填充每个排班班次对应的用户信息
|
|
|
|
|
+ userList.forEach(({ userId, userName }) => {
|
|
|
|
|
+ data[userId].forEach((day, dayIndex) => {
|
|
|
|
|
+ day.forEach(({ alias }) => {
|
|
|
|
|
+ result[alias][dayIndex].push({
|
|
|
|
|
+ userId,
|
|
|
|
|
+ userName
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ return result
|
|
|
|
|
+ },
|
|
|
|
|
+ /* 复原ScheduleData为人员排班数据格式(班次排班->人员排班)
|
|
|
|
|
+ */
|
|
|
|
|
+ reverseForScheduleData (data, userList, scheduleShift, overview) {
|
|
|
|
|
+ const result = []
|
|
|
|
|
+ // 先创建以userId为键的空二维数组
|
|
|
|
|
+ const temp = overview ? JSON.parse(overview) : {}
|
|
|
|
|
+ userList.forEach(({ userId }) => {
|
|
|
|
|
+ result[userId] = Array.from({ length: temp.dateCount }, () => [])
|
|
|
|
|
+ })
|
|
|
|
|
+ const scheduleShiftMap = scheduleShift.reduce((acc, item) => {
|
|
|
|
|
+ acc[item.alias] = item
|
|
|
|
|
+ return acc
|
|
|
|
|
+ }, {})
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历转换后的数据格式中的每个排班班次
|
|
|
|
|
+ Object.keys(data).forEach(alias => {
|
|
|
|
|
+ const days = data[alias]
|
|
|
|
|
+ const aliasData = scheduleShiftMap[alias]
|
|
|
|
|
+ // 遍历每一天的数据
|
|
|
|
|
+ days.forEach((users, dayIndex) => {
|
|
|
|
|
+ // 遍历当天该班次上的每个用户
|
|
|
|
|
+ users.forEach(({ userId }) => {
|
|
|
|
|
+ // 将当天该用户在该班次的信息添加到对应的用户数据中
|
|
|
|
|
+ result[userId][dayIndex].push(aliasData)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return result
|
|
|
|
|
+ },
|
|
|
handleConfigChange (val) {
|
|
handleConfigChange (val) {
|
|
|
const temp = this.configList.find(i => i.id === val)
|
|
const temp = this.configList.find(i => i.id === val)
|
|
|
this.formData = {
|
|
this.formData = {
|
|
@@ -666,8 +744,18 @@ export default {
|
|
|
return dates
|
|
return dates
|
|
|
},
|
|
},
|
|
|
changeView () {
|
|
changeView () {
|
|
|
- console.log('changeView')
|
|
|
|
|
- debugger
|
|
|
|
|
|
|
+ // 关闭可能存在的弹出框(如果有的话),确保视图切换时界面整洁
|
|
|
|
|
+ this.$refs.popover.showPopper = false
|
|
|
|
|
+ this.handleClose()
|
|
|
|
|
+ // 判断当前视图类型,如果是'users'则切换为'shifts',如果是'shifts'则切换为'users'
|
|
|
|
|
+ this.viewType = this.viewType === 'users' ? 'shifts' : 'users'
|
|
|
|
|
+ // 重新计算scheduleData的结构以适应新视图
|
|
|
|
|
+ if (this.viewType === 'users') {
|
|
|
|
|
+ this.scheduleData = this.reverseForScheduleData(this.scheduleData, this.userNameList, this.formData.scheduleShift, this.formData.overview)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.scheduleData = this.transformScheduleDataForShiftsView(this.scheduleData, this.userNameList, this.formData.scheduleShift, this.formData.overview)
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log('changeView', this.scheduleData)
|
|
|
},
|
|
},
|
|
|
handleShiftClick (event, { row, rIndex, column, cIndex }) {
|
|
handleShiftClick (event, { row, rIndex, column, cIndex }) {
|
|
|
this.selectItem = []
|
|
this.selectItem = []
|
|
@@ -815,6 +903,9 @@ export default {
|
|
|
// return result
|
|
// return result
|
|
|
// },
|
|
// },
|
|
|
dealData (data) {
|
|
dealData (data) {
|
|
|
|
|
+ if (this.viewType === 'shifts') { // 班次排班需还原数据
|
|
|
|
|
+ data = this.reverseForScheduleData(this.scheduleData, this.userNameList, this.formData.scheduleShift, this.formData.overview)
|
|
|
|
|
+ }
|
|
|
var dateCount = 0
|
|
var dateCount = 0
|
|
|
const result = Object.entries(data).map(([userId, days]) => {
|
|
const result = Object.entries(data).map(([userId, days]) => {
|
|
|
const userObj = { userId, statistics: {}}
|
|
const userObj = { userId, statistics: {}}
|
|
@@ -842,6 +933,7 @@ export default {
|
|
|
statistics: JSON.stringify(userObj.statistics)
|
|
statistics: JSON.stringify(userObj.statistics)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
console.log(result)
|
|
console.log(result)
|
|
|
|
|
|
|
|
// 统计所有userId中各个alias的平均出现次数
|
|
// 统计所有userId中各个alias的平均出现次数
|
|
@@ -1013,6 +1105,8 @@ export default {
|
|
|
this.shiftForm.current = date
|
|
this.shiftForm.current = date
|
|
|
this.popoverReference = e.target
|
|
this.popoverReference = e.target
|
|
|
this.$refs.popover.showPopper = true
|
|
this.$refs.popover.showPopper = true
|
|
|
|
|
+ // 先把编辑菜单关闭
|
|
|
|
|
+ this.handleClose()
|
|
|
|
|
|
|
|
// 手动更改弹窗位置
|
|
// 手动更改弹窗位置
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
@@ -1250,11 +1344,11 @@ export default {
|
|
|
border-bottom: none;
|
|
border-bottom: none;
|
|
|
border-right: none;
|
|
border-right: none;
|
|
|
cursor: context-menu;
|
|
cursor: context-menu;
|
|
|
-
|
|
|
|
|
|
|
+ /*filter: saturate(0.8);*/
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
- align-items: center;
|
|
|
|
|
|
|
+ align-items: center ;
|
|
|
.shift {
|
|
.shift {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
}
|
|
}
|