You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

985 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<div class="select">
<div class="date">
<el-date-picker
size="small"
v-model="date"
:type="createType === 1 ? 'date' : 'week'"
value-format="yyyy-MM-dd"
:picker-options="pickerOptions"
placeholder="日期选择"
:format="createType === 1 ? 'yyyy-MM-dd' : 'yyyy第WW周'"
style="width: 160px"
@input="pickDate"
></el-date-picker>
<p style="margin-left: 14px">
您正在为
<span style="color: red">{{ date }}</span>
创建
<span style="color: red">
{{
abilities.find((i) => i.value === ability)
? abilities.find((i) => i.value === ability).key
: ""
}}
</span>
调令
</p>
<!-- <el-radio-group size="small" style="margin-left: 14px;" v-model="createType">-->
<!-- <el-radio-button :label="1">天</el-radio-button>-->
<!-- <el-radio-button :label="2"></el-radio-button>-->
<!-- </el-radio-group>-->
</div>
<div class="select-item">
<div class="select-item__title">选择范围</div>
<el-checkbox-group size="small" v-model="select.area">
<el-checkbox-button v-for="item in areas" :label="item.value">{{
item.key
}}</el-checkbox-button>
</el-checkbox-group>
</div>
<div class="select-item">
<div class="select-item__title">选择泵闸</div>
<el-checkbox-group size="small" v-model="select.type">
<el-checkbox-button v-for="item in types" :label="item.value">{{
item.key
}}</el-checkbox-button>
</el-checkbox-group>
</div>
<div class="select-item">
<div class="select-item__title">选择类别</div>
<el-radio-group
size="small"
v-model="ability"
@input="(e) => data.forEach((i) => (i.leibie = e))"
>
<el-radio-button v-for="item in abilities" :label="item.value">{{
item.key
}}</el-radio-button>
</el-radio-group>
</div>
<div class="select-item">
<Button type="primary" style="margin-left: 10px" @click="clear"
>清空筛选</Button
>
<el-popover
placement="top-start"
title="模板"
width="300"
trigger="click"
@show="getTemplates"
>
<template>
<Table
:loading="templateLoading"
:data="templates"
size="small"
:columns="templateTable"
></Table>
<div style="display: flex; justify-content: center; padding: 8px 0">
<el-pagination
small
:current-page.sync="templateSelect.page"
:page-size="templateSelect.page_size"
layout="prev, pager, next"
:total="templateTotal"
@current-change="getTemplates"
>
</el-pagination>
</div>
</template>
<Button
slot="reference"
type="primary"
style="margin-left: 10px"
>模板选择</Button
>
</el-popover>
</div>
</div>
<Table
ref="dataTable"
style="margin-top: 20px"
:columns="columns"
:data="mergeData"
stripe
:span-method="objectSpanMethod"
></Table>
<div class="btns">
<Button type="primary" @click="submit">创建调令</Button>
<Button type="primary" ghost @click="reset">重置列表</Button>
<Button type="primary" ghost @click="clone">克隆模板</Button>
</div>
</div>
</template>
<script>
import { uuid } from "@/utils";
import { index, save } from "@/api/system/baseForm";
import { deepCopy } from "@/utils";
import { mergeTableRow } from "@/utils/mergeTableRow";
import { show } from "@/api/system/customFormField";
export default {
inject: ["equipments"],
props: {},
data() {
return {
templateLoading: false,
templates: [],
templateTotal: 0,
templateSelect: {
table_name: "transfer_templates",
page: 1,
page_size: 20,
},
templateTable: [
{
type: "index",
width: 46,
title: " ",
},
{
title: "名称",
key: "name",
},
{
title: "操作",
key: "operate",
render: (h, { row }) =>
h(
"Button",
{
props: {
type: "primary",
size: "small",
},
on: {
["click"]: (_) => {
this.handleClone(JSON.parse(row.content))
},
},
},
"选择"
),
},
],
dispatches: [],
transferDispatches: [],
createType: 1,
pickerOptions: {
firstDayOfWeek: 1,
shortcuts: [
{
text: "今天",
onClick(picker) {
picker.$emit("pick", new Date());
},
},
{
text: "明天",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24);
picker.$emit("pick", date);
},
},
{
text: "下周",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);
picker.$emit("pick", date);
},
},
],
},
areas: [],
types: [],
abilities: [],
select: {
area: [],
type: [],
leibie: [],
},
weather: [],
copyOriginalData: [],
date: this.$moment().format("YYYY-MM-DD"),
ability: 1,
data:
this.equipmentList?.map((i) => ({
equipment: i,
equipment_id: i.id,
start_time: "",
end_time: "",
content: "",
level: 1,
leibie: this.ability,
})) || [],
columns: [
// {
// width: 50,
// title: ' ',
// type: 'index',
// key: 'index'
// },
{
title: "点位",
width: 240,
key: "equipment_id",
align: "center",
render: (h, { row, index }) => {
let text = row.equipment ? row.equipment.name : "";
return h("div", [
h(
"el-popover",
{
props: {
placement: "top-start",
title: "今日调令",
width: "400px",
},
on: {
show: (_) => {
this.transferDispatches = this.dispatches.filter(
(i) => i.equipment_id === row.equipment_id
);
},
},
},
[
h(
"span",
{
slot: "reference",
// props: {
// type: "ios-list-box"
// },
style: {
"border-radius": "100%",
"margin-right": "4px",
cursor: "pointer",
width: "20px",
height: "20px",
display: "inline-block",
background: "#367bc7",
color: "#fff",
},
},
this.dispatches.reduce((pre, cur) => {
return cur.equipment_id === row.equipment_id
? ++pre
: pre;
}, 0)
),
h("Table", {
style: {
width: "480px",
},
props: {
size: "small",
data: this.transferDispatches,
columns: [
{
title: " ",
type: "index",
width: 46,
},
{
title: "开始时间",
key: "start_time",
align: "center",
render: (h, { row }) =>
h(
"span",
this.$moment(row.start_time).format(
"YYYY-MM-DD HH:mm"
)
),
},
{
title: "结束时间",
key: "end_time",
align: "center",
render: (h, { row }) =>
h(
"span",
this.$moment(row.end_time).format(
"YYYY-MM-DD HH:mm"
)
),
},
{
title: "内容",
key: "content",
},
],
},
}),
]
),
h("span", text),
h(
"Button",
{
props: {
size: "small",
type: "primary",
icon: "ios-add",
},
style: {
"margin-left": "6px",
},
on: {
["click"]: (e) => {
this.data.splice(index, 0, deepCopy(row));
},
},
},
"新增"
),
]);
},
},
{
title: "机组运行状态",
width: 200,
render: (h, { row }) => {
const create = () => {
let dom = [];
for (let i = 0; i <= row._random; i++) {
dom.push(
h("div", {
style: {
width: "14px",
height: "14px",
background: i === row._random - 1 ? "red" : "green",
"border-radius": "100%",
"margin-left": "6px",
},
})
);
}
return dom;
};
return h(
"div",
{
style: {
display: "flex",
},
},
create()
);
},
},
{
title: "类别",
key: "yinpaishui",
width: 100,
align: "center",
render: (h, { row }) =>
h("span", this.abilities.find((i) => i.value === row.leibie)?.key),
},
{
title: "开启时间",
width: 140,
align: "center",
key: "start_time",
render: (h, { row, index }) => {
return h("TimePicker", {
props: {
value: row.start_time,
type: "time",
size: "small",
transfer: true,
format: "HH:mm",
},
on: {
["on-change"]: (e) => {
this.data[index].start_time = e;
if (this.data[index]._last) {
const [hour, min] = this.data[index].start_time
.split(":")
.map((i) => Number(i));
let addTime = {
hour: Math.floor(this.data[index]._last),
min: (this.data[index]._last % 1) * 60,
};
let resTime = {
hour:
hour + addTime.hour + (min + addTime.min >= 60 ? 1 : 0),
min: (min + addTime.min) % 60,
};
this.data[index].end_time = `${resTime.hour
.toString()
.padStart(2, "0")}:${resTime.min
.toString()
.padStart(2, "0")}`;
}
},
},
});
},
},
{
title: "持续时间(时)",
width: 140,
align: "center",
key: "last",
render: (h, { row, index }) => {
const getValue = () => {
if (row.start_time && row.end_time) {
const [start_hour,start_min] = row.start_time.split(':')
const [end_hour,end_min] = row.end_time.split(':')
const diffMins = (Number(end_hour) - Number(start_hour)) * 60 + (Number(end_min) - Number(start_min))
return diffMins / 60
}
return 0
}
return h("InputNumber", {
props: {
value: getValue(),
min: 0,
step: 0.5,
size: "small",
precision: 1,
},
on: {
["on-change"]: (e) => {
this.data[index]._last = e;
const [hour, min] = this.data[index].start_time
.split(":")
.map((i) => Number(i));
let addTime = {
hour: Math.floor(e),
min: (e % 1) * 60,
};
let resTime = {
hour:
hour + addTime.hour + (min + addTime.min >= 60 ? 1 : 0),
min: (min + addTime.min) % 60,
};
this.data[index].end_time = `${resTime.hour
.toString()
.padStart(2, "0")}:${resTime.min
.toString()
.padStart(2, "0")}`;
},
},
});
},
},
{
title: "结束时间",
width: 140,
align: "center",
key: "end_time",
render: (h, { row, index }) => {
return h("TimePicker", {
props: {
value: row.end_time,
type: "time",
size: "small",
transfer: true,
format: "HH:mm",
},
on: {
["on-change"]: (e) => (this.data[index].end_time = e),
},
});
},
},
{
title: "调令内容",
minWidth: 200,
key: "content",
align: "center",
render: (h, { row, index }) => {
return h("Input", {
style: {
padding: "6px 0",
},
props: {
size: "small",
value: row.content,
type: "textarea",
},
on: {
["input"]: (e) => (this.data[index].content = e),
},
});
},
},
{
title: "调令等级",
width: 140,
key: "level",
align: "center",
render: (h, { row, index }) => {
return h(
"Select",
{
props: {
value: row.level,
filterable: true,
size: "small",
transfer: true,
},
on: {
["on-select"]: (e) => {
row.level = e.value;
this.data[index].level = e.value;
},
},
},
[
{ label: "一般", value: 1 },
{ label: "紧急", value: 2 },
].map((i) => {
return h(
"Option",
{
props: {
value: i.value,
},
},
i.label
);
})
);
},
},
{
title: "操作",
width: 140,
key: "operate",
render: (h, { row, index }) => {
return h(
"Poptip",
{
props: {
title: "确认要删除吗?",
confirm: true,
transfer: true,
},
on: {
["on-ok"]: (e) => {
this.data.splice(index, 1);
},
},
},
[
h(
"Button",
{
props: {
type: "primary",
size: "small",
},
},
"删除"
),
]
);
},
},
],
};
},
methods: {
handleClone (content) {
if (!content) return;
const groupTemplateData = new Map();
content.sort((a, b) => a.equipment_id - b.equipment_id)
.forEach(item => {
const group = groupTemplateData.get(item.equipment_id) || [];
group.push(item);
groupTemplateData.set(item.equipment_id, group);
});
const dataMap = new Map(this.data.map((item, index) => [item.equipment_id, index]));
groupTemplateData.forEach((group, equipment_id) => {
const findIndex = dataMap.get(equipment_id);
if (findIndex !== undefined) {
const findData = this.data[findIndex];
this.data.splice(findIndex, 0, ...group.map(i => ({ ...findData, ...i })));
}
});
},
async getTemplates() {
this.templateLoading = true;
const res = await index(this.templateSelect);
this.templates = res.data;
this.templateTotal = res.total;
this.templateLoading = false;
},
clone() {
const submitData = this.data.filter(
(i) => i.start_time || i.end_time || i.content
);
let verify = submitData.length > 0;
submitData.forEach((item) => {
if (!item.start_time || !item.end_time) {
verify = false;
}
});
if (!verify) {
this.$message({
type: "warning",
message: "请填写完整信息",
});
return;
}
submitData.forEach((i) => {
delete i["equipment_id-span"];
delete i["_index"];
delete i["_rowKey"];
});
this.$prompt("请输入模板名称", "模板", {
confirmButtonText: "确定",
cancelButtonText: "取消",
inputValidator: (value) => {
return !!value;
},
inputErrorMessage: "请输入模板名称",
}).then(({ value }) => {
save({
table_name: "transfer_templates",
name: value,
content: JSON.stringify(
submitData.map((i) => ({
equipment_id: i.equipment_id,
start_time: i.start_time,
end_time: i.end_time,
content: i.content,
level: i.level,
}))
),
}).then((_) => {
this.$message({
type: "success",
message: "保存成功",
});
});
});
},
clear() {
this.select = {
area: [],
type: [],
};
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
const span = column["key"] + "-span";
if (row[span]) {
return row[span];
}
},
reset() {
this.clear();
this.data =
this.equipmentList?.map((i) => ({
equipment: i,
equipment_id: i.id,
start_time: "",
end_time: "",
content: "",
level: 1,
leibie: this.ability,
})) || [];
},
async submit() {
const submitData = this.data.filter(
(i) => i.start_time || i.end_time || i.content
);
let verify = submitData.length > 0;
submitData.forEach((item) => {
if (!item.start_time || !item.end_time || !item.level) {
verify = false;
}
});
if (!verify) {
this.$message({
type: "warning",
message: "请填写完整信息",
});
return;
}
let isNeed = 0;
try {
await this.$confirm("是否需要走流程?","提示",{
confirmButtonText: "需要",
cancelButtonText: "不需要",
type: "info",
closeOnClickModal: false,
distinguishCancelAndClose: true
})
isNeed = 1;
} catch (e) {
if (e === 'cancel') {
isNeed = 0;
} else {
return
}
}
const uid = uuid();
let promiseAll = [];
submitData.forEach((i) => {
delete i["equipment_id-span"];
delete i["_index"];
delete i["_rowKey"];
if (this.createType === 2) {
const startDay = this.$moment(this.date).startOf("week");
let weekArr = [];
for (let a = 1; a <= 7; a++) {
weekArr.push(
this.$moment(startDay).add(a, "days").format("YYYY-MM-DD")
);
}
weekArr.forEach((j) => {
promiseAll.push(
save(
{
...i,
table_name: "transfers",
start_time: `${j} ${i.start_time}`,
end_time: `${j} ${i.end_time}`,
no: uid,
status: 1,
shifouzouliucheng: isNeed
},
false
)
);
});
} else {
i.start_time = `${this.date} ${i.start_time}`;
i.end_time = `${this.date} ${i.end_time}`;
i.no = uid;
i.status = 1;
promiseAll.push(
save(
{
table_name: "transfers",
...i,
shifouzouliucheng: isNeed
},
false
)
);
}
});
let loadingInstance = this.$loading({
lock: true,
background: "rgba(0,0,0,0.4)",
text: "正在加载中...",
});
Promise.all(promiseAll)
.then((res) => {
this.reset();
loadingInstance.close();
this.$message({
type: "success",
message: `成功创建${res.length}条调令`,
});
this.$bus.$emit("createdTransfer");
})
.catch((_) => {
loadingInstance.close();
});
},
async getArea() {
const obj = (await show({ id: 4 }, false))?.select_item;
if (obj && typeof obj === "object") {
let keys = Object.keys(obj);
if (keys.length > 0) {
this.areas = keys.map((key) => {
return {
key,
value: /^\d*$/.test(obj[key]) ? Number(obj[key]) : obj[key],
};
});
}
}
this.$bus.$emit("areas", this.areas);
},
async getType() {
const obj = (await show({ id: 1 }, false))?.select_item;
if (obj && typeof obj === "object") {
let keys = Object.keys(obj);
if (keys.length > 0) {
this.types = keys.map((key) => {
return {
key,
value: /^\d*$/.test(obj[key]) ? Number(obj[key]) : obj[key],
};
});
}
}
},
async getAbility() {
const obj = (await show({ id: 31 }, false))?.select_item;
if (obj && typeof obj === "object") {
let keys = Object.keys(obj);
if (keys.length > 0) {
this.abilities = keys.map((key) => {
return {
key,
value: /^\d*$/.test(obj[key]) ? Number(obj[key]) : obj[key],
};
});
}
}
this.$bus.$emit("yinpaishui", this.abilities);
},
pickDate() {
this.$bus.$emit("pickDate", this.date);
},
},
computed: {
mergeData() {
return mergeTableRow({
data: this.data.map((i) => {
delete i["equipment_id-span"];
return i;
}),
mergeColNames: ["equipment_id"], // 需要合并的列,默认合并列相同的数据
firstMergeColNames: ["equipment_id"], // 受影响的列只合并以firstMerge为首的同类型数据
firstMerge: "equipment_id", // 以哪列为基础进行合并,一般为第一列
});
},
equipmentList() {
return this.equipments() || [];
},
},
watch: {
equipmentList(val) {
this.data =
val?.map((i) => ({
equipment: i,
equipment_id: i.id,
start_time: "",
end_time: "",
content: "",
level: 1,
leibie: this.ability,
_random: Math.round(Math.random() * 8),
})) || [];
this.handleClone(this.$route.params.cloneTransfer)
},
select: {
handler: function (val) {
if (val.area.length > 0 || val.type.length > 0) {
let list1 = [];
let list2 = [];
if (val.area.length > 0) {
list1 = this.equipments().filter((i) =>
val.area.find((j) => j === i.area)
);
}
if (val.type.length > 0) {
list2 = this.equipments().filter((i) =>
val.type.find((j) => j === i.type)
);
}
this.data =
Array.from(new Set([...list1, ...list2].map(JSON.stringify)))
.map(JSON.parse)
.map((i) => ({
equipment: i,
equipment_id: i.id,
start_time: "",
end_time: "",
content: "",
level: 1,
leibie: this.ability,
})) || [];
} else {
this.data =
this.equipments()?.map((i) => ({
equipment: i,
equipment_id: i.id,
start_time: "",
end_time: "",
content: "",
level: 1,
leibie: this.ability,
})) || [];
}
},
deep: true,
},
},
mounted() {},
created() {
this.$bus.$on(
"getDispatches",
(dispatches) => (this.dispatches = dispatches)
);
this.getArea();
this.getType();
this.getAbility();
},
destroyed() {
this.$bus.$off("getDispatches");
},
};
</script>
<style scoped lang="scss">
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.select {
&-item {
display: flex;
align-items: center;
&__title {
width: 80px;
flex-shrink: 0;
font-weight: 600;
text-align: center;
}
& + & {
margin-top: 10px;
}
}
.date {
display: flex;
align-items: center;
padding: 10px;
}
}
.btns {
margin-top: 10px;
padding-left: 10px;
}
</style>