<template>
|
<div class="class-page">
|
<div class="search">
|
<div class="search_thing">
|
<div class="search_label">选择时间:</div>
|
<div class="search_input">
|
<el-date-picker
|
v-model="query.year"
|
type="year"
|
size="small"
|
format="yyyy"
|
placeholder="选择年"
|
@change="refreshTable()"
|
style="width: 140px"
|
:clearable="false"
|
>
|
</el-date-picker>
|
<el-select
|
v-model="query.month"
|
clearable
|
placeholder="选择月"
|
style="width: 140px; margin-left: 16px"
|
size="small"
|
@change="refreshTable()"
|
>
|
<el-option
|
v-for="item in monthOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
>
|
</el-option>
|
</el-select>
|
<el-input
|
v-model="query.userName"
|
placeholder="请输入人员名称"
|
size="small"
|
style="width: 140px; margin: 0 16px"
|
clearable
|
@keyup.enter.native="refreshTable()"
|
></el-input>
|
<el-select
|
v-model="query.laboratory"
|
placeholder="请选择实验室"
|
style="width: 140px"
|
size="small"
|
clearable
|
@change="refreshTable()"
|
>
|
<el-option
|
v-for="item in laboratory"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
>
|
</el-option>
|
</el-select>
|
</div>
|
</div>
|
<div class="search_thing" style="padding-left: 30px">
|
<el-button size="mini" type="primary" @click="refreshTable()"
|
>查 询</el-button
|
>
|
<el-button size="mini" @click="refresh()">重置</el-button>
|
</div>
|
<div class="search_thing btns" style="padding-left: 30px">
|
<el-button
|
size="small"
|
type="primary"
|
v-if="checkPermi(['performance:class:time'])"
|
@click="configTime"
|
>时间配置</el-button
|
>
|
<el-button
|
size="small"
|
type="primary"
|
v-if="checkPermi(['performance:class:down'])"
|
@click="handleDown"
|
:loading="downLoading"
|
>导 出</el-button
|
>
|
<el-button
|
size="small"
|
type="primary"
|
@click="schedulingVisible = true"
|
v-if="checkPermi(['performance:class:add'])"
|
>排 班</el-button
|
>
|
</div>
|
</div>
|
<div class="center" v-loading="pageLoading">
|
<div class="clearfix" style="width: 100%" v-show="query.month">
|
<div class="fixed-left">
|
<div
|
class="content-title"
|
style="
|
padding-left: 16px;
|
box-sizing: border-box;
|
position: fixed;
|
z-index: 1;
|
background-color: #fff;
|
width: 220px;
|
"
|
>
|
人员名称
|
<span style="color: #ff4949">(人员数量:{{ list.length }})</span>
|
</div>
|
<div class="content-user" v-for="(item, index) in list">
|
<div class="user-pic">
|
{{ item.userName ? item.userName.charAt(0) : "" }}
|
</div>
|
<div class="user-info">
|
<p
|
style="
|
font-size: 14px;
|
color: #3a7bfa;
|
line-height: 24px;
|
margin: 0;
|
"
|
>
|
{{ item.userName }}
|
</p>
|
<p
|
style="
|
color: #999999;
|
font-size: 12px;
|
transform: scale(0.8) translateX(-20px);
|
white-space: nowrap;
|
width: 150px;
|
margin: 0;
|
"
|
v-text="item.monthlyAttendanceStr"
|
></p>
|
<p style="margin-top: 4px; margin: 0">
|
<span
|
style="
|
color: #999999;
|
font-size: 12px;
|
display: inline-block;
|
transform: scale(0.8) translateX(-10px);
|
"
|
>合计出勤: </span
|
><span style="font-size: 16px; color: #ff4902"
|
>{{ item.monthlyAttendance.totalCount }}天</span
|
>
|
</p>
|
</div>
|
</div>
|
</div>
|
<div class="scroll-right">
|
<div class="content">
|
<div
|
class="content-title content-title-right"
|
style="
|
border-bottom: 0;
|
position: fixed;
|
z-index: 1;
|
background-color: #fff;
|
"
|
>
|
<div
|
class="content-title-item"
|
v-for="(item, index) in weeks"
|
:key="'b' + index"
|
>
|
<span
|
class="month"
|
style="position: absolute; top: 0px"
|
v-if="item.week == '周日'"
|
>{{ item.weekNum }}周</span
|
>
|
<p style="height: 26px; position: absolute; bottom: 12px">
|
<span class="day">{{ item.day }}</span>
|
<span class="week">{{ item.week.charAt(1) }}</span>
|
</p>
|
</div>
|
</div>
|
<div
|
class="content-body"
|
v-for="(item, index) in list"
|
:key="'c' + index"
|
>
|
<div
|
class="content-body-item"
|
v-for="(m, i) in item.list"
|
:key="'d' + i"
|
>
|
<el-dropdown
|
v-if="m"
|
trigger="click"
|
placement="bottom"
|
@command="(e) => handleCommand(e, m)"
|
:disabled="!checkPermi(['performance:class:edit'])"
|
style="width: 100%; height: 100%; cursor: pointer"
|
>
|
<el-tooltip
|
:disabled="m && !m.annotationText"
|
:content="m.annotationText"
|
>
|
<el-tag
|
@contextmenu.prevent.native="handleContextMenu(m, $event)"
|
class="work-box"
|
:type="getDictTypeByShift(m.shift)"
|
>{{ getShiftByDic(m.shift) }}</el-tag
|
>
|
</el-tooltip>
|
<i
|
v-if="m.checkinResult === 'success'"
|
class="el-icon-success"
|
style="position: relative; top: -20px; color: #67c23a"
|
></i>
|
<i
|
v-else-if="m.checkinResult === 'fail'"
|
class="el-icon-warning"
|
style="position: relative; top: -20px; color: #f56c6c"
|
></i>
|
<svg
|
v-if="m.annotationText"
|
style="position: relative; top: -62px; left: 31px"
|
t="1772437700487"
|
class="icon"
|
viewBox="0 0 1024 1024"
|
version="1.1"
|
xmlns="http://www.w3.org/2000/svg"
|
p-id="6193"
|
width="12"
|
height="12"
|
>
|
<path
|
d="M751.228537 117.332567c-1.023063 7.672974-1.470653 15.601715-1.278829 23.466514l1.278829 41.434062-32.418317 25.768406L473.466862 402.639333l-34.656268 27.494825-42.137418-13.747412a332.495559 332.495559 0 0 0-270.280524 28.965478l193.742604 194.637785 49.107037 49.362802 14.51471 14.642593 193.99837 194.829609a331.21673 331.21673 0 0 0 29.732776-271.559353l-13.747413-42.137418 27.494825-34.656268 194.509902-245.535182 25.768406-32.354375 41.434062 1.278829 4.220136 0.127883c6.522028 0 13.044057-0.44759 19.438202-1.406712l-155.377732-155.24985zM734.539817 0c9.719101 0 19.566085 3.644663 27.111177 11.189754l251.034146 250.650499a38.236989 38.236989 0 0 1-5.946555 59.081903 219.255244 219.255244 0 0 1-119.570518 35.359623c-2.301892 0-4.539843 0-6.841736-0.127882L685.752488 601.689078a413.253615 413.253615 0 0 1-71.742311 388.764038 39.451877 39.451877 0 0 1-58.378547 2.941307l-235.752139-236.775202L64.497325 1012.193211a37.277867 37.277867 0 1 1-52.623816-52.7517l255.510048-255.57399L31.631418 467.092319a39.451877 39.451877 0 0 1 3.197072-58.378548 411.399313 411.399313 0 0 1 258.771063-91.244454c43.480188 0 86.832494 6.905677 128.586263 20.461265l245.407299-194.573843A218.871596 218.871596 0 0 1 702.56909 17.264192a37.981223 37.981223 0 0 1 31.970727-17.264192z"
|
fill="#f56c6c"
|
p-id="6194"
|
></path>
|
</svg>
|
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-item
|
v-for="(n, j) in classType"
|
:key="'h' + j"
|
:command="n.dictValue"
|
>{{ n.dictLabel }}</el-dropdown-item
|
>
|
</el-dropdown-menu>
|
</el-dropdown>
|
<div></div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div
|
class="clearfix year-table"
|
style="width: 100%"
|
v-show="!query.month"
|
>
|
<div class="fixed-left">
|
<div
|
class="content-title"
|
style="
|
padding-left: 16px;
|
box-sizing: border-box;
|
position: fixed;
|
z-index: 1;
|
background-color: #fff;
|
width: 220px;
|
"
|
>
|
人员名称
|
<span style="color: #ff4949">(人员数量:{{ yearList.length }})</span>
|
</div>
|
<div
|
class="content-user"
|
v-for="(item, index) in yearList"
|
:key="'e' + index"
|
>
|
<div class="user-pic">
|
{{ item.userName ? item.userName.charAt(0) : "" }}
|
</div>
|
<div class="user-info">
|
<p
|
style="
|
font-size: 14px;
|
color: #3a7bfa;
|
line-height: 24px;
|
margin: 0;
|
"
|
>
|
{{ item.userName }}
|
</p>
|
<p
|
style="
|
color: #999999;
|
font-size: 12px;
|
transform: scale(0.8) translateX(-20px);
|
white-space: nowrap;
|
width: 150px;
|
margin: 0;
|
"
|
v-text="item.sidebarAnnualAttendanceStr"
|
></p>
|
<p style="margin-top: 4px; margin: 0">
|
<span
|
style="
|
color: #999999;
|
font-size: 12px;
|
display: inline-block;
|
transform: scale(0.8) translateX(-10px);
|
"
|
>合计出勤: </span
|
><span style="font-size: 16px; color: #ff4902"
|
>{{ item.sidebarAnnualAttendance.totalCount }}天</span
|
>
|
</p>
|
</div>
|
</div>
|
</div>
|
<div class="scroll-right">
|
<div class="content">
|
<div>
|
<div
|
class="content-title content-title-right"
|
style="
|
border-bottom: 0;
|
height: 63px;
|
position: fixed;
|
z-index: 1;
|
background-color: #fff;
|
width: calc(100% - 448px);
|
"
|
:style="`display: grid;
|
grid-template-columns: repeat(${monthList.length}, 1fr);`"
|
>
|
<div
|
class="content-title-item"
|
v-for="(item, index) in monthList"
|
:key="'b' + index"
|
style="height: 52px"
|
>
|
<span class="month">{{ item }}月</span>
|
</div>
|
</div>
|
<div
|
class="content-body"
|
v-for="(item, index) in yearList"
|
:key="'c' + index"
|
:style="`display: grid;
|
grid-template-columns: repeat(${monthList.length}, 1fr);`"
|
>
|
<div
|
class="content-body-item"
|
v-for="(m, i) in item.monthlyAttendances"
|
:key="'d' + i"
|
>
|
<p style="color: rgb(153, 153, 153); font-size: 12px">
|
合计出勤:<span style="font-size: 14px; color: #000">{{
|
m.monthlyAttendance.totalCount
|
}}</span>
|
</p>
|
<p style="color: rgb(153, 153, 153); font-size: 12px">
|
<span>{{ m.monthlyAttendanceStr }}</span>
|
</p>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<ul
|
v-show="showMenu"
|
class="contextmenu"
|
:style="{ left: menuX + 'px', top: menuY + 'px' }"
|
@click.stop
|
>
|
<li @click="updateAnnotation('edit')">
|
<i class="el-icon-edit-outline"></i> 编辑批注
|
</li>
|
<li @click="updateAnnotation('delete')">
|
<i class="el-icon-delete"></i> 删除批注
|
</li>
|
</ul>
|
<el-dialog title="时间配置" :visible.sync="configTimeVisible" width="620px">
|
<div v-loading="configTimeVisibleLoading" style="min-height: 200px">
|
<div v-for="(item, index) in timeQuery">
|
<div
|
class="form"
|
style="display: flex; justify-content: space-between"
|
>
|
<div style="margin-bottom: 12px; width: 200px">
|
<span class="form_label">班次:</span>
|
<span v-if="!item.isEdit"> {{ item.type }} </span>
|
<span class="form_input" v-if="item.isEdit">
|
<el-select
|
v-model="item.shift"
|
placeholder="请选择"
|
style="width: 70%; margin-right: 8px"
|
clearable
|
size="small"
|
>
|
<el-option
|
v-for="obj in timeTypeList"
|
:key="obj.dictValue"
|
:label="obj.dictLabel"
|
:value="obj.dictValue"
|
>
|
</el-option>
|
</el-select>
|
</span>
|
</div>
|
<div style="width: calc(100% - 260px)">
|
<span class="form_label">时间:</span>
|
<span v-if="!item.isEdit">
|
{{
|
item.startTime && item.endTime
|
? item.startTime + "~" + item.endTime
|
: ""
|
}}
|
</span>
|
<span class="form_input" v-if="item.isEdit">
|
<el-time-select
|
placeholder="起始时间"
|
v-model="item.startTime"
|
size="small"
|
:picker-options="{
|
start: '00:00',
|
step: '00:15',
|
end: '24:00',
|
}"
|
style="width: 120px"
|
>
|
</el-time-select>
|
<el-time-select
|
style="width: 120px"
|
placeholder="结束时间"
|
v-model="item.endTime"
|
size="small"
|
:picker-options="{
|
start: '00:00',
|
step: '00:15',
|
end: '24:00',
|
}"
|
>
|
</el-time-select>
|
</span>
|
</div>
|
<span>
|
<i
|
class="el-icon-circle-check"
|
v-if="item.isEdit"
|
style="margin-left: 10px; color: #4b79f2; cursor: pointer"
|
@click="saveEdit(item, index)"
|
></i>
|
<i
|
class="el-icon-edit"
|
v-if="!item.isEdit"
|
style="margin-left: 10px; color: #4b79f2; cursor: pointer"
|
@click="item.isEdit = true"
|
></i>
|
<i
|
class="el-icon-delete"
|
v-if="timeQuery.length > 1"
|
style="margin-left: 10px; color: #ff4902; cursor: pointer"
|
@click="deleteTime(item, index)"
|
></i>
|
</span>
|
</div>
|
<el-divider></el-divider>
|
<div
|
@click="addTimeForm"
|
style="color: #4b79f2; cursor: pointer"
|
v-if="index === timeQuery.length - 1"
|
>
|
添加时间配置
|
</div>
|
</div>
|
<div
|
@click="addTimeForm"
|
style="color: #4b79f2"
|
v-if="timeQuery.length === 0"
|
>
|
添加时间配置
|
</div>
|
</div>
|
</el-dialog>
|
<el-dialog
|
title="排班"
|
:visible.sync="schedulingVisible"
|
width="20%"
|
@close="resetForm"
|
>
|
<el-form
|
ref="schedulingQueryRef"
|
:model="schedulingQuery"
|
:rules="schedulingQueryRules"
|
>
|
<el-form-item label="排班时间:" prop="dateRange">
|
<el-date-picker
|
v-model="schedulingQuery.dateRange"
|
type="datetimerange"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
:default-time="['00:00:00', '23:59:59']"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
style="width: 100%"
|
>
|
</el-date-picker>
|
</el-form-item>
|
<el-form-item label="人员名称:" prop="userIdList">
|
<el-select
|
v-model="schedulingQuery.userIdList"
|
popper-class="select-with-all"
|
placeholder="请选择"
|
style="width: 100%"
|
multiple
|
collapse-tags
|
clearable
|
>
|
<template slot="prefix">
|
<el-button
|
type="text"
|
size="mini"
|
@click="handleSelectAll"
|
style="margin: 4px 0"
|
>
|
{{ isAllSelected ? "取消全选" : "全选" }}
|
</el-button>
|
<el-divider style="margin: 5px 0" />
|
</template>
|
<el-option
|
v-for="item in personList"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
>
|
<span style="float: left">{{ item.name }}</span>
|
<span style="float: right; color: #8492a6; font-size: 13px">{{
|
item.account
|
}}</span>
|
</el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="班次:" prop="shift">
|
<el-select
|
v-model="schedulingQuery.shift"
|
placeholder="请选择"
|
style="width: 100%"
|
>
|
<el-option
|
v-for="item in classType"
|
:key="item.dictValue"
|
:label="item.dictLabel"
|
:value="item.dictValue"
|
>
|
</el-option>
|
</el-select>
|
</el-form-item>
|
</el-form>
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="resetForm">取 消</el-button>
|
<el-button type="primary" @click="confirmScheduling" :loading="loading"
|
>确 定</el-button
|
>
|
</span>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import {
|
page,
|
pageYear,
|
add,
|
list,
|
shiftAdd,
|
shiftUpdate,
|
shiftRemove,
|
exportFile,
|
obtainItemParameterList,
|
update,
|
editAnnotationText,
|
delAnnotationText,
|
} from "@/api/performance/class";
|
import { selectUserListByPerformance } from "@/api/system/user";
|
import { getWorkMonth } from "@/utils/date";
|
import { transformExcel } from "@/utils/file";
|
export default {
|
name: "Class",
|
data() {
|
return {
|
query: {
|
userName: "",
|
laboratory: "",
|
year: new Date(),
|
month: getWorkMonth().month() + 1,
|
},
|
monthOptions: [
|
{
|
value: 1,
|
label: "1月",
|
},
|
{
|
value: 2,
|
label: "2月",
|
},
|
{
|
value: 3,
|
label: "3月",
|
},
|
{
|
value: 4,
|
label: "4月",
|
},
|
{
|
value: 5,
|
label: "5月",
|
},
|
{
|
value: 6,
|
label: "6月",
|
},
|
{
|
value: 7,
|
label: "7月",
|
},
|
{
|
value: 8,
|
label: "8月",
|
},
|
{
|
value: 9,
|
label: "9月",
|
},
|
{
|
value: 10,
|
label: "10月",
|
},
|
{
|
value: 11,
|
label: "11月",
|
},
|
{
|
value: 12,
|
label: "12月",
|
},
|
],
|
laboratory: [],
|
weeks: [],
|
classType: [],
|
currentUserIndex: null,
|
schedulingVisible: false,
|
personList: [],
|
loading: false,
|
schedulingQuery: {
|
dateRange: [],
|
userIdList: [],
|
shift: "",
|
},
|
schedulingQueryRules: {
|
dateRange: {
|
required: true,
|
message: "请选择排班日期",
|
trigger: "change",
|
},
|
userIdList: {
|
required: true,
|
message: "请选择人员名称",
|
trigger: "change",
|
},
|
shift: { required: true, message: "请选择班次", trigger: "change" },
|
},
|
list: [],
|
currentPage: 1, // 当前页
|
pageSize: 20, // 一页10条
|
total: 0,
|
pageLoading: false, // 组件loading的展示,默认为true
|
finishLoding: false, // 加载完成,显示已经没有更多了
|
monthList: [],
|
yearList: [],
|
downLoading: false,
|
configTimeVisible: false, // 时间配置弹框
|
configTimeVisibleLoading: false, // 时间配置弹框loading
|
timeTypeList: [],
|
timeQuery: [],
|
showMenu: false,
|
menuX: 0,
|
menuY: 0,
|
selectedTarget: null,
|
};
|
},
|
computed: {
|
isAllSelected() {
|
return (
|
this.schedulingQuery.userIdList.length === this.personList.length &&
|
this.personList.length > 0
|
);
|
},
|
},
|
watch: {},
|
mounted() {
|
document.addEventListener("click", this.handleClickOutside);
|
this.selectEnumByCategory();
|
this.obtainItemParameterList();
|
this.getUsers();
|
if (this.query.month) {
|
this.init();
|
} else {
|
this.initYear();
|
}
|
this.monthList = [];
|
for (let i = 12; i > 0; i--) {
|
this.monthList.push(i);
|
}
|
this.monthList.reverse();
|
},
|
destroyed() {
|
document.removeEventListener("click", this.handleClickOutside);
|
},
|
methods: {
|
resetForm() {
|
this.$refs.schedulingQueryRef.resetFields();
|
this.$nextTick(() => {
|
this.schedulingVisible = false;
|
});
|
},
|
handleSelectAll() {
|
if (this.isAllSelected) {
|
this.schedulingQuery.userIdList = [];
|
} else {
|
// 只选中可用选项的value
|
this.schedulingQuery.userIdList = this.personList.map(
|
(item) => item.id
|
);
|
}
|
},
|
handleContextMenu(target, e) {
|
// 阻止浏览器默认右键菜单
|
e.preventDefault();
|
|
const menuMinWidth = 105;
|
const offsetLeft = this.$el.getBoundingClientRect().left; // container margin left
|
const offsetWidth = this.$el.offsetWidth; // container width
|
const maxLeft = offsetWidth - menuMinWidth; // left boundary
|
const left = e.clientX - offsetLeft + 15; // 15: margin right
|
|
if (left > maxLeft) {
|
this.menuX = maxLeft;
|
} else {
|
this.menuX = left;
|
}
|
this.menuY = e.clientY - 60;
|
// 显示菜单
|
this.selectedTarget = target;
|
this.showMenu = true;
|
},
|
//编辑批注
|
updateAnnotation(operation) {
|
// 点击菜单后关闭菜单
|
this.showMenu = false;
|
if (this.selectedTarget && !this.selectedTarget.shift) {
|
this.$message.warning("请先选择班次");
|
return;
|
}
|
if (operation && operation === "edit") {
|
this.$prompt("", "编辑批注", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
inputType: "textarea",
|
inputPlaceholder: "填写批注内容",
|
inputPattern: /^.{0,100}$/,
|
inputErrorMessage: "最大输入100个字符",
|
})
|
.then(({ value }) => {
|
editAnnotationText({
|
id: this.selectedTarget.id,
|
annotationText: value,
|
}).then((res) => {
|
this.$message.success("提交成功");
|
this.refreshTable();
|
});
|
})
|
.catch(() => {});
|
} else if (operation && operation === "delete") {
|
this.$confirm("是否删除批注内容?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delAnnotationText(this.selectedTarget.id).then((res) => {
|
this.$message.success("删除成功");
|
this.refreshTable();
|
});
|
})
|
.catch(() => {});
|
}
|
},
|
handleClickOutside() {
|
this.showMenu = false;
|
},
|
getDictTypeByShift(e) {
|
let obj = this.classType.find((m) => m.dictValue == e);
|
if (obj) {
|
return obj.listClass;
|
}
|
return "";
|
},
|
refresh() {
|
this.list = [];
|
this.yearList = [];
|
this.currentPage = 1;
|
this.query = {
|
userName: "",
|
laboratory: "",
|
year: new Date(),
|
month: new Date().getMonth() + 1,
|
};
|
if (this.query.month) {
|
this.init();
|
} else {
|
this.initYear();
|
}
|
},
|
refreshTable() {
|
this.currentPage = 1;
|
if (this.query.month) {
|
this.list = [];
|
this.init();
|
} else {
|
this.yearList = [];
|
this.initYear();
|
}
|
},
|
currentChange(num) {
|
this.currentPage = num;
|
if (this.query.month) {
|
this.init();
|
} else {
|
this.initYear();
|
}
|
},
|
init() {
|
this.pageLoading = true;
|
let year = this.query.year.getFullYear();
|
let month0 = this.query.month
|
? this.query.month
|
: new Date().getMonth() + 1;
|
let month = month0 > 9 ? month0 : "0" + month0;
|
page({
|
time: year + "-" + month + "-01 00:00:00",
|
userName: this.query.userName,
|
laboratory: this.query.laboratory,
|
})
|
.then((res) => {
|
this.pageLoading = false;
|
this.list = res.data.page;
|
let headerList = res.data.headerList;
|
this.weeks = [];
|
headerList.forEach((item) => {
|
let obj = {
|
weekNum: item.weekly,
|
week: item.headerTime.split(" ")[1],
|
day: item.headerTime.split(" ")[0],
|
};
|
this.weeks.push(obj);
|
});
|
})
|
.catch(() => {
|
this.pageLoading = false;
|
});
|
},
|
initYear() {
|
this.pageLoading = true;
|
let year = this.query.year.getFullYear();
|
pageYear({
|
time: year + "-01-01 00:00:00",
|
userName: this.query.userName,
|
laboratory: this.query.laboratory,
|
}).then((res) => {
|
this.pageLoading = false;
|
this.yearList = res.data;
|
});
|
},
|
confirmScheduling() {
|
this.$refs.schedulingQueryRef.validate((valid) => {
|
if (valid) {
|
this.loading = true;
|
add({
|
startTime: this.schedulingQuery.dateRange[0],
|
endTime: this.schedulingQuery.dateRange[1],
|
userIdList: this.schedulingQuery.userIdList,
|
shift: this.schedulingQuery.shift,
|
})
|
.then((res) => {
|
this.loading = false;
|
this.$message.success("操作成功");
|
this.schedulingVisible = false;
|
this.schedulingQuery = {
|
week: "",
|
userIdList: [],
|
shift: "",
|
};
|
this.refresh();
|
})
|
.catch((err) => {
|
this.loading = false;
|
});
|
}
|
});
|
},
|
configTime() {
|
this.getDicts("sys_class_type").then((response) => {
|
this.timeTypeList = response.data;
|
});
|
this.getTimeList();
|
this.configTimeVisible = true;
|
},
|
getTimeList() {
|
this.configTimeVisibleLoading = true;
|
list()
|
.then((res) => {
|
if (res.data.length > 0) {
|
res.data.forEach((item) => {
|
item.isEdit = false;
|
const index = this.timeTypeList.findIndex(
|
(val) => val.dictValue === item.shift
|
);
|
if (index > -1) {
|
item.type = this.timeTypeList[index].dictLabel;
|
}
|
});
|
this.timeQuery = res.data;
|
}
|
this.configTimeVisibleLoading = false;
|
})
|
.catch((e) => {
|
this.configTimeVisibleLoading = false;
|
console.log("e--", e);
|
});
|
},
|
addTimeForm() {
|
this.timeQuery.push({
|
type: "",
|
shift: "",
|
time: null,
|
isEdit: true,
|
});
|
},
|
saveEdit(item, index) {
|
if (item.shift) {
|
const index = this.timeTypeList.findIndex(
|
(val) => val.dictValue === item.shift
|
);
|
if (index > -1) {
|
item.type = this.timeTypeList[index].dictLabel;
|
}
|
}
|
delete item.orderBy;
|
delete item.time;
|
const isEmpty = this.isObjectEmpty(item);
|
if (isEmpty) {
|
this.$message.error("请填写完整");
|
return;
|
}
|
let newObj = {};
|
newObj.shift = item.shift;
|
newObj.startTime = item.startTime;
|
newObj.endTime = item.endTime;
|
if (item.id) {
|
// 编辑
|
newObj.id = item.id;
|
shiftUpdate(newObj).then((res) => {
|
this.$message.success("操作成功");
|
this.getTimeList();
|
});
|
} else {
|
// 新增
|
shiftAdd(newObj).then((res) => {
|
this.$message.success("操作成功");
|
this.getTimeList();
|
});
|
}
|
},
|
deleteTime(item, index) {
|
if (item.id) {
|
shiftRemove({
|
id: item.id,
|
}).then((res) => {
|
this.$message.success("操作成功");
|
this.getTimeList();
|
});
|
} else {
|
this.timeQuery.splice(index, 1);
|
}
|
},
|
isObjectEmpty(obj) {
|
return Object.keys(obj).some((key) => !obj[key]);
|
},
|
handleDown() {
|
let year = this.query.year.getFullYear();
|
let time = "";
|
if (this.query.month) {
|
let month =
|
this.query.month > 9 ? this.query.month : "0" + this.query.month;
|
time = year + "-" + month + "-01 00:00:00";
|
} else {
|
time = year + "-01-01 00:00:00";
|
}
|
this.downLoading = true;
|
exportFile({
|
time,
|
userName: this.query.userName,
|
laboratory: this.query.laboratory,
|
isMonth: !!this.query.month,
|
})
|
.then((res) => {
|
this.downLoading = false;
|
let fileName = "中天耐丝质量部";
|
if (this.query.month) {
|
fileName += this.query.month + "月班次信息";
|
} else {
|
fileName += year + "年班次汇总";
|
}
|
transformExcel(res, fileName + ".xlsx");
|
this.$message.success("导出成功");
|
})
|
.catch((err) => {
|
this.downLoading = false;
|
});
|
},
|
selectEnumByCategory() {
|
this.getDicts("sys_class_type").then((response) => {
|
this.classType = response.data;
|
});
|
},
|
obtainItemParameterList() {
|
obtainItemParameterList().then((res) => {
|
let data = [];
|
res.data.forEach((a) => {
|
data.push({
|
label: a.laboratoryName,
|
value: a.id,
|
});
|
});
|
this.laboratory = data;
|
});
|
},
|
handleCommand(e, m) {
|
if (e != m.shift) {
|
update({
|
id: m.id,
|
shift: e,
|
}).then((res) => {
|
this.$message.success("操作成功");
|
m.shift = e;
|
});
|
}
|
},
|
getUsers() {
|
selectUserListByPerformance().then((res) => {
|
this.personList = res.data;
|
});
|
},
|
getShiftByDic(e) {
|
let obj = this.classType.find((m) => m.dictValue == e);
|
if (obj) {
|
return obj.dictLabel;
|
}
|
return "无";
|
},
|
},
|
};
|
</script>
|
|
<style scoped lang="scss">
|
.class-page {
|
padding: 10px;
|
}
|
|
.search {
|
height: 50px;
|
display: flex;
|
align-items: center;
|
position: relative;
|
}
|
|
.search_thing {
|
display: flex;
|
align-items: center;
|
height: 50px;
|
}
|
|
.search_label {
|
width: 70px;
|
font-size: 14px;
|
text-align: right;
|
}
|
|
.search_input {
|
display: flex;
|
align-items: center;
|
}
|
|
.btns {
|
position: absolute;
|
right: 16px;
|
top: 50%;
|
transform: translate(0, -50%);
|
}
|
|
.center {
|
width: 100%;
|
height: calc(100vh - 220px);
|
background-color: #fff;
|
overflow-y: auto;
|
display: flex;
|
}
|
|
>>> .scroll-pagination {
|
overflow-y: scroll;
|
scrollbar-width: none;
|
}
|
|
>>> .scroll-pagination::-webkit-scrollbar {
|
display: none;
|
}
|
|
.fixed-left {
|
float: left;
|
width: 220px;
|
/* 左边区域宽度 */
|
background-color: #fff;
|
box-shadow: 2px -2px 5px rgba(51, 51, 51, 0.12);
|
/* 左边阴影 */
|
}
|
|
.clearfix::after {
|
content: "";
|
display: table;
|
clear: both;
|
}
|
|
.scroll-right {
|
width: calc(100% - 220px);
|
/* 减去左边区域宽度 */
|
/*min-height: calc(100% - 10px);*/
|
/* 视口高度 */
|
margin-left: 220px;
|
/*overflow-x: auto;*/
|
}
|
|
.content {
|
/* 视口高度 */
|
/*min-height: calc(100% - 10px);*/
|
}
|
|
.content-title {
|
height: 58px;
|
line-height: 58px;
|
border-bottom: 1px solid #eeeeee;
|
}
|
|
.content-title-right {
|
display: flex;
|
align-items: center;
|
}
|
|
.content-title-item {
|
height: 100%;
|
width: 50px;
|
flex-shrink: 0;
|
border-bottom: 1px solid #eeeeee;
|
box-sizing: border-box;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
flex-direction: column;
|
position: relative;
|
}
|
|
.content-title-item .month {
|
font-size: 12px;
|
color: #3a7bfa;
|
box-sizing: border-box;
|
padding: 0 1px;
|
border-radius: 50%;
|
background: #d6e4ff;
|
text-align: center;
|
line-height: 22px;
|
}
|
|
.content-title-item .day {
|
font-size: 14px;
|
color: #333333;
|
margin-right: 4px;
|
}
|
|
.content-title-item .week {
|
font-size: 12px;
|
color: #999999;
|
}
|
|
.content-body {
|
display: flex;
|
align-items: center;
|
}
|
|
.content-body:nth-child(2) {
|
padding-top: 58px;
|
}
|
|
.content-body-item {
|
height: 70px;
|
width: 50px;
|
flex-shrink: 0;
|
font-size: 12px;
|
box-sizing: border-box;
|
padding: 4px;
|
border-right: 1px solid #eeeeee;
|
border-bottom: 1px solid #eeeeee;
|
}
|
|
.work-box {
|
width: 100%;
|
height: 100%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border-radius: 8px 8px 8px 8px;
|
font-size: 14px;
|
}
|
.content-user {
|
width: 100%;
|
height: 70px;
|
box-sizing: border-box;
|
border-bottom: 1px solid #eeeeee;
|
display: flex;
|
align-items: center;
|
}
|
.content-user:nth-child(2) {
|
margin-top: 58px;
|
}
|
.user-pic {
|
width: 50px;
|
height: 50px;
|
border-radius: 50%;
|
background: #c0c4cc;
|
color: #fff;
|
font-size: 20px;
|
text-align: center;
|
line-height: 50px;
|
margin-left: 10px;
|
}
|
|
.user-info {
|
flex: 1;
|
margin-left: 10px;
|
}
|
|
.year-table {
|
width: 100%;
|
}
|
|
.year-table .scroll-right {
|
flex: 1;
|
}
|
|
.year-table .month {
|
font-size: 14px;
|
color: #3a7bfa;
|
box-sizing: border-box;
|
padding: 0 4px;
|
border-radius: 50%;
|
background: #d6e4ff;
|
text-align: center;
|
line-height: 30px;
|
}
|
|
.year-table .content-title-item {
|
width: 100%;
|
}
|
|
.year-table .content-body-item {
|
width: 100%;
|
height: 70px;
|
display: flex;
|
align-items: center;
|
flex-direction: column;
|
justify-content: center;
|
}
|
|
/* 自定义右键菜单样式 */
|
.contextmenu {
|
margin: 0;
|
background: #fff;
|
z-index: 3000;
|
position: absolute;
|
list-style-type: none;
|
padding: 5px 0;
|
border-radius: 4px;
|
font-size: 12px;
|
font-weight: 400;
|
color: #333;
|
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
li {
|
margin: 0;
|
padding: 7px 16px;
|
cursor: pointer;
|
&:hover {
|
background: #eee;
|
}
|
}
|
}
|
</style>
|