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.

870 lines
26 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>
<div ref="lxHeader">
<LxHeader
icon="md-apps"
:text="$route.meta.title"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content"></div>
<slot>
<header-content :auths="auths_auth_mixin">
<template #search>
<div style="display: flex;">
<Select clearable v-model="select.filter[1].value" placeholder="请选择类别" style="width: 140px;margin-left: 6px;">
<Option v-for="item in abilities" :value="item.value">{{ item.key }}</Option>
</Select>
<Input style="width: 140px;margin-left: 6px;" clearable v-model="select.filter[0].value" placeholder="搜索内容"/>
<el-date-picker size="small" style="width: 140px;margin-left: 6px;" value-format="yyyy-MM-dd" v-model="select.filter[2].value"></el-date-picker>
<Button
style="margin-left: 10px"
type="primary"
@click="$refs['xyTable'].getTableData(true)"
>查询</Button
>
</div>
</template>
<template #create>
<Button
type="primary"
@click="
$refs['dialog'].setType('add'), $refs['dialog'].show()
"
>新增</Button
>
</template>
<template #import>
<Button type="primary" @click="$refs['imports'].show()"
>导入</Button
>
</template>
<template #export>
<Button
type="primary"
@click="exportExcel(new Date().getTime().toString())"
>导出</Button
>
</template>
<Button type="primary" @click="cloneTransfer">克隆调令</Button>
<template #distribute>
<Button type="primary" @click="pickNoDistribute">勾选当日未下发</Button>
<Button type="primary" @click="distributeTransfers">批量下发</Button>
</template>
</header-content>
</slot>
</LxHeader>
</div>
</div>
<!--$refs['drawer'].setId(row.id);
$refs['drawer'].show();-->
<el-row :gutter="10">
<el-col :span="4">
<el-tree :data="equipments"
node-key="id"
:style="{ 'max-height': treeHeight, 'overflow': 'scroll' }"
ref="elTree"
:props="{ children: 'children', label: 'name' }"
show-checkbox
@check="handleCheckChange">
</el-tree>
</el-col>
<el-col :span="20">
<xy-table
:btnCondition="btnCondition"
:span-method="objectSpanMethod"
:format-list-data="mergeData"
:is-page="false"
:btn-width="360"
:auths="auths_auth_mixin"
:delay-req="true"
:destroy-action="destroy"
ref="xyTable"
:border="true"
:row-key="row => row.id"
:action="index"
:req-opt="tableSelect"
:destroy-req-opt="select"
:table-item="table"
@detail="
(row) => {
$router.push({
path: $route.path + '/detail/' + row.id,
});
}
"
@editor="
(row) => {
$refs['dialog'].setId(row.id);
$refs['dialog'].setType('editor');
$refs['dialog'].show();
}
"
>
<template #adjust="{ row }">
<template v-if="[2,3,4,5,6].find(i => i === row.status)">
<Button
size="small"
type="primary"
@click="
$refs['adjust'].setId(row.id),
$refs['adjust'].setType('editor'),
$refs['adjust'].show()
"
>调整</Button
>
</template>
</template>
<template #callback="{ row }">
<Button
size="small"
type="primary"
@click="
$refs['callback'].setId(row.id),
$refs['callback'].setType('add'),
$refs['callback'].show()
"
>反馈</Button
>
</template>
<template #oa="{ row }">
<Button
size="small"
type="primary"
@click="toOa(row)"
>发起流程</Button
>
</template>
<template #distribute="{ row }">
<Button
v-if="row.status === 1 || row.status === 0"
size="small"
type="primary"
@click="setTransferStatus(2,row)"
>下发</Button
>
</template>
<template #cancel="{ row }">
<Button
v-if="row.status === 2 || row.status === 3"
size="small"
type="primary"
ghost
@click="setTransferStatus(0,row)"
>取消</Button
>
</template>
</xy-table>
</el-col>
</el-row>
<!-- <dialoger-->
<!-- :table-name="customForm.tableName"-->
<!-- :form-info="form"-->
<!-- ref="dialog"-->
<!-- @refresh="$refs['xyTable'].getTableData()"-->
<!-- >-->
<!-- </dialoger>-->
<!-- <drawer-->
<!-- :table-name="customForm.tableName"-->
<!-- :form-info="form"-->
<!-- ref="drawer"-->
<!-- ></drawer>-->
<imports
:table-name="customForm.tableName"
:form-info="form"
ref="imports"
@refresh="$refs['xyTable'].getTableData()"
></imports>
<callback ref="callback"></callback>
<adjust :areas="areas" :abilities="abilities" ref="adjust" @refresh="$refs['xyTable'].getTableData()"></adjust>
</div>
</template>
<script>
import { getOaToken } from "@/api/other";
import { index as fieldIndex } from "@/api/system/customFormField";
import { authMixin } from "@/mixin/authMixin";
import { index, destroy, save } from "@/api/system/baseForm";
import { op } from "@/const/op";
import { download } from "@/utils/downloadRequest";
import { getparameter } from "@/api/system/dictionary";
import { show } from "@/api/system/customForm";
import { show as formFieldShow } from "@/api/system/customFormField"
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import { listdept } from "@/api/system/department";
import dialoger from "@/views/component/dialog.vue";
import LxHeader from "@/components/LxHeader/index.vue";
import headerContent from "@/components/LxHeader/XyContent.vue";
import drawer from "@/views/component/drawer.vue";
import imports from "@/views/component/imports.vue";
import callback from "@/views/order/component/callback.vue";
import adjust from "@/views/order/component/adjust.vue";
import {deepCopy} from "@/utils";
import {mergeTableRow} from "@/utils/mergeTableRow";
export default {
components: {
LxHeader,
dialoger,
headerContent,
drawer,
imports,
callback,
adjust
},
mixins: [authMixin],
provide: {
formStore: () => this.form,
areas: () => this.areas,
abilities: () => this.abilities
},
data() {
return {
equipments: [],
areas: [],
abilities: [],
window: {
width: 0,
height: 0,
top: 0,
left: 0
},
oaToken: "",
op,
selectArea: "",
select: {
table_name: "",
filter: [
{
key: "content",
op: "like",
value: ""
},
{
key: "leibie",
op: "eq",
value: ""
},
{
key: "start_time",
op: "like",
value: this.$moment().format('YYYY-MM-DD')
},
{
key: "equipment_id",
op: "in",
value: []
},
{
key: "is_adjust",
op: "eq",
value: -1
}
],
sort_name: 'start_time',
page_size: 9999,
},
selectQuery: [],
form: [],
table: [],
customForm: {
customFormId: "",
tableName: "",
},
resetTable: new Map([
["start_time",{
formatter: (data, cell, val)=>{
return val ? this.$moment(val).format("HH:mm") : ''
}
}],
["end_time",{
formatter: (data, cell, val)=>{
return val ? this.$moment(val).format("HH:mm") : ''
}
}],
["shichang",{
formatter: (data) => {
return this.$moment(data.end_time).diff(this.$moment(data.start_time),"hours",true) + "小时"
},
width: 120
}]
])
};
},
methods: {
btnCondition ({ row }, item, index) {
if (row.status === 0) {
if (item === 'oa') {
return false
}
}
if ([2,3,4,5,6,7].find(i => i === row.status)) {
if (item === 'delete' || item === 'oa') {
return false
}
}
if ([3,4,5,6,7].find(i => i === row.status)) {
if (item === 'edit') {
return false
}
}
if (row.liuchengzhuangtai === 2 || row.liuchengzhuangtai === 3) {
if (item === 'delete' || item === 'edit') {
return false
}
}
return true
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
const span = column["property"] + "-span";
if (row[span]) {
return row[span];
}
},
mergeData(list) {
return mergeTableRow({
data: this.selectArea ? list.filter(i => (i.equipment_id_equipments_id_relation?.area === this.selectArea)) : list,
mergeColNames: ["equipment_id_equipments_id_relation.area","equipment_id_equipments_id_relation.name"], // 需要合并的列,默认合并列相同的数据
firstMergeColNames: ["equipment_id_equipments_id_relation.area","equipment_id_equipments_id_relation.name"], // 受影响的列只合并以firstMerge为首的同类型数据
firstMerge: "equipment_id", // 以哪列为基础进行合并,一般为第一列
});
},
pickNoDistribute () {
this.$refs['xyTable'].getListData()?.forEach(item => {
if (item.status === 1) {
this.$refs['xyTable'].toggleRowSelection(item)
}
})
},
async getEquipments () {
const res = (await index({
table_name: 'equipments',
page: 1,
page_size: 9999
},false))?.data || []
this.equipments = this.areas.map(i => ({
id: `area_${i.value}`,
name: i.key,
children: res.filter(j => j.area === i.value)
}))
this.$nextTick(() => {
this.areas.forEach(i => {
this.$refs['elTree'].setChecked(`area_${i.value}`, true, true)
})
})
},
async getArea() {
const obj = (await formFieldShow({ 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);
await this.getEquipments()
},
async getAbility() {
const obj = (await formFieldShow({ 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);
},
async toOa (row) {
if (!this.oaToken) {
this.oaToken = (await getOaToken()).oatoken
}
let jsonInfo = {
'title': row.equipment_id_equipments_id_relation?.name,
'65aa1a59e408c': row.start_time,
'65aa1a7e4109d': row.level,
'65aa1a442705f': row.content
}
let url =
`${process.env.VUE_APP_OA_URL}/admin/flow/create/34?diaoling_oatoken=${this.oaToken}&out_diaoling_id=${row.id}&default_json=${JSON.stringify(jsonInfo)}`
window.open(url, 'diaoling',
`top=${this.window.top},left=${this.window.left},width=${this.window.width},height=${this.window.height},location=0`
)
},
async distributeTransfers () {
let promiseAll = this.$refs['xyTable'].getSelection().map(i => {
for (let key in i) {
if (/_relation/g.test(key)) {
delete i[key]
}
}
i.status = 2;
return save({
table_name: 'transfers',
...i
})
})
const res = await Promise.all(promiseAll)
this.$message({
type: 'success',
message: `下发${res.length}条调令`
})
this.$refs['xyTable'].getTableData()
},
cloneTransfer () {
this.$router.push({
name: 'menu_14',
params: {
cloneTransfer: this.$refs['xyTable'].getSelection().map(i => ({
equipment_id: i.equipment_id,
start_time: this.$moment(i.start_time).format('HH:mm'),
end_time: this.$moment(i.end_time).format('HH:mm'),
kaiqishuliang: i.kaiqishuliang,
kaiqishuliang1: i.kaiqishuliang1,
yinpaishui: i.yinpaishui,
diaolingleixing: i.diaolingleixing,
content: i.content,
level: i.level,
}))
}
})
},
handleCheckChange (data, checked, indeterminate) {
this.treeValue = this.$refs['elTree'].getCheckedNodes(true)?.filter(i => !i.children)?.map(i => i.name).toString()
this.select.filter[3].value = this.$refs['elTree'].getCheckedNodes(true)?.filter(i => !i.children)?.map(i => i.id)
this.$refs['xyTable'].getTableData(true)
},
setTransferStatus (status,row) {
let copyRow = deepCopy(row);
copyRow.status = status;
for (let key in copyRow) {
if (/_relation/g.test(key)) {
delete copyRow[key]
}
}
save({
table_name: 'transfers',
...copyRow
}).then(_ => this.$refs['xyTable'].getTableData())
},
index,
destroy,
download,
reset() {
this.select.filter.splice(1);
this.select.filter[0] = {
key: "",
op: "",
value: "",
};
},
async exportExcel(sheetName) {
const res = await index(
Object.assign(this.select, { page: 1, page_size: 9999 })
);
if (res.data) {
let headers = this.form.map((i) => {
return {
key: i.field,
title: i.name,
};
});
const data = res.data.map((row) =>
headers.map((header) => row[header.key])
);
data.unshift(headers.map((header) => header.title));
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
const wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
`${sheetName}.xlsx`
);
}
},
//target要为内存地址引用类型
inputStartHandler(e, target) {
let temp = target?.value.split(",")[1];
target.value = `${e},${temp ? temp : ""}`;
},
inputEndHandler(e, target) {
let temp = target?.value.split(",")[0];
target.value = `${temp ? temp : ""},${e}`;
},
async getFormDetail() {
if (this.$route.meta.params?.custom_form) {
let decode = decodeURIComponent(this.$route.meta.params?.custom_form);
try {
let custom_form = JSON.parse(decode);
this.customForm.customFormId = custom_form.custom_form_id;
this.customForm.tableName = custom_form.table_name;
this.select.table_name = custom_form.table_name;
} catch (err) {
console.warn(err);
}
}
if (this.$route.meta.params?.select) {
try {
this.selectQuery = JSON.parse(
decodeURIComponent(this.$route.meta.params?.select)
);
} catch (err) {
console.warn(err);
}
}
const res = await show({ id: this.customForm.customFormId }, false);
//字段处理
//初始表白名单
let baseTable = new Map([
[
"departments",
async () => {
const res = await listdept();
return res;
},
],
["admins", []],
]);
let { fields, relation } = res;
let fieldRes = fields.sort((a, b) => a.sort - b.sort);
if (
!fields ||
!relation ||
!fields instanceof Array ||
!relation instanceof Array
) {
throw new Error("fields或relation格式错误");
}
fieldRes?.forEach((i, index) => {
i._relations = relation.find((j) => j.custom_form_field === i.field);
if (i.select_item && typeof i.select_item === "object") {
let keys = Object.keys(i.select_item);
if (keys.length > 0) {
i._params = keys.map((key) => {
return {
key,
value: /^\d*$/.test(i.select_item[key])
? Number(i.select_item[key])
: i.select_item[key],
};
});
}
}
if (i.edit_input === "file" || i.edit_input === "files") {
return;
}
if (i._relations) {
if (baseTable.get(i._relations.link_table_name)) {
baseTable
.get(i._relations.link_table_name)()
.then((res) => (i._params = res));
} else {
i._params = i._relations.parameter_id
? getparameter({ id: i._relations.parameter_id }, false).then(
(res) => {
i._params = res.detail;
}
)
: this.index({
table_name: i._relations.link_table_name,
page: 1,
page_size: 9999,
}).then((res) => {
i._params = res.data;
});
}
}
});
this.form = fields;
this.form
?.filter((i) => i.list_show)
.forEach((i) => {
let linkOb = {};
if (i.edit_input === "richtext") {
linkOb.customFn = (row) => {
return (
<div
style={{ "max-height": "55px", overflow: "scroll" }}
domPropsInnerHTML={row[i.field]}
></div>
);
};
}
if (
i.select_item &&
typeof i.select_item === "object" &&
!(i.select_item instanceof Array)
) {
let keys = Object.keys(i.select_item);
linkOb.customFn = (row) => {
let paramMap = new Map();
keys.forEach((key) => {
paramMap.set(i.select_item[key], key);
});
return <span>{paramMap.get(row[i.field]?.toString())}</span>;
};
}
if (i._relations) {
let { link_relation, foreign_key, link_with_name } = i._relations;
if (link_relation === "newHasOne" || link_relation === "hasOne") {
linkOb.customFn = (row) => {
if (i.edit_input === "file") {
return (
<img
style="height: 40px;"
alt={row[link_with_name]?.original_name}
src={row[link_with_name]?.url}
>
</img>
);
} else {
return (
<span>
{row[link_with_name]?.name ||
row[link_with_name]?.no ||
row[link_with_name]?.value}
</span>
);
}
};
}
if (link_relation === "hasMany" || link_relation === "newHasMany") {
linkOb.customFn = (row) => {
if (i.edit_input === "files") {
return (
<div style="display: flex;flex-direction: column;">
{row[link_with_name]?.map((o) => (
<img alt={o.original_name} src={o?.url}></img>
))}
</div>
);
} else {
return (
<div>
{row[link_with_name]?.map((o) => (
<p>
{o?.name ||
o?.no ||
o?.value ||
o?.biaoti ||
o?.mingcheng}
</p>
))}
</div>
);
}
};
}
}
let alignLeft = [];
if (this.resetTable.get(i.field)) {
this.table.push(Object.assign(
{
prop: i.field,
label: i.name,
width: i.width,
align: alignLeft.find((m) => m === i.field) ? "left" : "center",
fixed: i.is_fixed,
},
linkOb,
this.resetTable.get(i.field)
))
return
}
this.table.push(
Object.assign(
{
prop: i.field,
label: i.name,
width: i.width,
align: alignLeft.find((m) => m === i.field) ? "left" : "center",
fixed: i.is_fixed,
},
linkOb
)
);
});
this.table.unshift({
width: 100,
label: "范围",
prop: "equipment_id_equipments_id_relation.area",
formatter:(data,row,val) => {
return this.areas.find(i => i.value === val)?.key
}
});
this.table.unshift({
label: "选择",
prop: "selections",
type: "selection",
width: 46,
reserveSelection: true
})
this.table.unshift({
prop: "expand",
type: "expand",
width: 46,
expandFn:({ row }) => {
return (
<div style="max-width: 800px;padding: 10px;">
{
(row.id_transfers_to_transfer_id_relation || []).map((i,index) => (
<div style="display: flex;">
<div style="font-weight: 600;padding: 0 10px;">{index+1}.</div>
<div>
<span style="font-weight: 600;padding: 0 6px;">调整时间:</span>
<span>{ this.$moment(i.created_at).format('YYYY-MM-DD HH:mm') }</span>
</div>
<div>
<span style="font-weight: 600;padding: 0 6px;">当前闸门数量:</span>
<span>{ i.kaiqishuliang }</span>
</div>
<div>
<span style="font-weight: 600;padding: 0 6px;">当前水泵数量:</span>
<span>{ i.kaiqishuliang1 }</span>
</div>
<div>
<span style="font-weight: 600;padding: 0 6px;">调整类型:</span>
<span>{ this.form.find(i => i.field === "tiaozhengleixing")?._params?.find(j => j.value == i.tiaozhengleixing)?.key }</span>
</div>
<div>
<span style="font-weight: 600;padding: 0 6px;">调整内容:</span>
<span>{ i.content }</span>
</div>
</div>
))
}
</div>
)
}
})
},
},
computed: {
columnArrTest() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field).search_input ===
"checkbox" ||
this.form.find((i) => i.field === field).search_input === "radio"
: false;
};
},
getColumnField() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field)
: {};
};
},
getColumnParams() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field)._params
: [];
};
},
tableSelect() {
let filter = [...this.select.filter, ...this.selectQuery];
return {
...this.select,
filter,
};
},
treeHeight () {
return (this.$refs['xyTable']?.tableHeight + 36 || 630) + 'px'
},
},
created() {
this.window.width = screen.availWidth * 0.95
this.window.height = screen.availHeight * 0.95
this.window.top = (window.screen.height - 30 - this.window.height) / 2
this.window.left = (window.screen.width - 10 - this.window.width) / 2
this.getFormDetail();
this.getArea();
this.getAbility();
},
};
</script>
<style scoped lang="scss">
.select {
&__item {
& > p {
display: inline-block;
width: 80px;
text-align: center;
}
& + div {
margin-top: 6px;
}
}
}
.add-btn {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
& > span {
padding: 0 10px;
}
}
a {
color: red;
text-decoration: none;
transition: all 0.2s;
}
a:hover {
color: red;
text-decoration: underline;
}
</style>