Files
smartClean/frontend/witcleansystem/src/Page/TaskCenter/PurifierTask.vue
xqzp2026 515f1bec5b Initial commit: SmartClean SaaS platform
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:53:34 +09:30

816 lines
22 KiB
Vue

<template>
<el-skeleton :rows="30" :loading="pageBasicsData.loading" animated />
<!-- 保洁任务 -->
<div class="task-box" v-if="!pageBasicsData.loading">
<div ref="topSearchRef">
<!-- 顶部功能按钮 -->
<qu-button-group
:buttonList="[
{ cnName: '导出', enName: 'export', theme: 'primary', icon: 'top' },
]"
@buttonClick="buttonClick"
/>
<!-- 搜索区域 -->
<div class="search-area">
<el-form
ref="screenFormRef"
:model="pageBasicsData.screenForm"
inline
size="small"
>
<el-form-item prop="dateType">
<el-select
style="width: 110px"
filterable
placeholder="请选择查询日期"
v-model="pageBasicsData.screenForm.dateType"
>
<el-option
v-for="item in pageBasicsData.taskDateTypeList"
:key="item.key"
:label="item.value"
:value="item.key"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="date" style="margin-left: -20px">
<qu-time-select v-model.date="pageBasicsData.screenForm.date" />
</el-form-item>
<el-form-item label="所属站点" prop="districtId">
<div class="screen-item">
<el-select
filterable
placeholder="请选择"
v-model="pageBasicsData.screenForm.districtId"
>
<el-option
v-for="item in pageBasicsData.districtList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务派单号" prop="no">
<div class="screen-item">
<el-input
placeholder="请输入任务派单号"
clearable
v-model="pageBasicsData.screenForm.no"
></el-input>
</div>
</el-form-item>
<el-form-item label="任务名称" prop="name">
<div class="screen-item">
<el-input
placeholder="请输入任务名称"
clearable
v-model="pageBasicsData.screenForm.name"
></el-input>
</div>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<div class="screen-item">
<el-select
filterable
clearable
placeholder="请选择任务类型"
v-model="pageBasicsData.screenForm.taskType"
>
<el-option
v-for="item in selectItems['taskType']"
:key="item.key"
:label="item.value"
:value="item.key"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务生成类型" prop="taskCreateType">
<div class="screen-item">
<el-select
filterable
clearable
placeholder="请选择任务生成类型"
v-model="pageBasicsData.screenForm.taskCreateType"
>
<el-option
v-for="item in selectItems['taskCreateType']"
:key="item.key"
:label="item.value"
:value="item.key"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务状态" prop="status">
<div class="screen-item">
<el-select
filterable
clearable
placeholder="请选择任务状态"
v-model="pageBasicsData.screenForm.status"
>
<el-option
v-for="item in selectItems['status']"
:key="item.key"
:label="item.value"
:value="item.key"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务派单人员" prop="taskDistributiUser">
<div class="screen-item">
<el-select
filterable
clearable
placeholder="请选择任务派单人员"
v-model="pageBasicsData.screenForm.taskDistributiUser"
@focus="
() => {
if (pageBasicsData.personSelectList?.length <= 0) {
$message.warning('当前选择的所属站点暂无任务派单人员!');
}
}
"
>
<el-option
v-for="item in pageBasicsData.personSelectList"
:key="item.id"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务接单人员" prop="taskAcceptUser">
<div class="screen-item">
<el-select
filterable
clearable
placeholder="请选择任务接单人员"
v-model="pageBasicsData.screenForm.taskAcceptUser"
@focus="
() => {
if (pageBasicsData.personSelectList?.length <= 0) {
$message.warning('当前选择的所属站点暂无任务接单人员!');
}
}
"
>
<el-option
v-for="item in pageBasicsData.personSelectList"
:key="item.id"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="任务位置" prop="taskScene">
<div class="screen-item">
<el-cascader
ref="taskSceneRef"
collapse-tags
:show-all-levels="false"
clearable
v-model="pageBasicsData.screenForm.taskScene"
:options="pageBasicsData.taskSceneList"
:props="pageBasicsData.areaGridSelectProps"
@change="taskSceneHandleChange"
@focus="
() => {
if (pageBasicsData.taskSceneList.length <= 0) {
$message.warning(
'当前选择的所属站点暂无任务场景,请重新选择!'
);
}
}
"
>
<template #default="{ data }">
<span>{{ data.name }}</span>
</template>
</el-cascader>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" round @click="restSearch"
>查询</el-button
>
<el-button round icon="Refresh" type="warning" @click="clearScreen"
>重置</el-button
>
</el-form-item>
</el-form>
</div>
</div>
<!-- 表格 -->
<div class="main-table">
<qu-table
:custom="true"
:showPage="true"
:showIndex="true"
:height="pageBasicsData.tableHeight"
:tableData="tableData"
:tableHeader="tableHeader"
:pageProps="pageProps"
@pageChange="pageChange"
:rowButtons="rowButtons"
@rowButtonClick="rowButtonClick"
@fetchTableAttr="fetchTableAttr"
></qu-table>
</div>
</div>
<!-- 查看任务弹窗 -->
<div v-if="showLookDialog">
<el-dialog v-model="showLookDialog" title="任务详情" fullscreen>
<purifierTaskDetailCom
v-model:showLookDialog="showLookDialog"
:taskDetailData="taskDetailData"
/>
</el-dialog>
</div>
<!-- 取消任务弹窗 -->
<el-dialog
v-model="cancelRelevant.showCancelDialog"
title="取消任务"
width="600px"
@close="closeCancelDialog"
>
<el-form
style="
border-top: 1px solid #dcdfe6;
border-bottom: 1px solid #dcdfe6;
margin-top: -20px;
padding-bottom: 40px;
"
label-width="130px"
ref="cancelRef"
:model="cancelRelevant.cancelForm"
>
<el-form-item
style="padding-top: 40px"
label="取消原因"
prop="cancelReason"
:rules="{
required: true,
message: '请选择取消原因',
trigger: 'change',
}"
>
<el-select
style="width: 350px"
filterable
placeholder="请选择取消任务的原因"
v-model="cancelRelevant.cancelForm.cancelReason"
>
<el-option
v-for="item in cancelRelevant.cancelCauseSelectList"
:key="item.key"
:label="item.value"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
v-if="cancelRelevant.cancelForm.cancelReason == '其他原因'"
label="详细原因"
prop="detailReason"
:rules="{
required: true,
message: '请输入详细原因',
trigger: 'change',
}"
>
<el-input
style="width: 350px"
type="textarea"
autosize
maxlength="500"
placeholder="请输入详细原因(限500字以内)"
v-model="cancelRelevant.cancelForm.detailReason"
>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button
style="width: 90px"
@click="cancelRelevant.showCancelDialog = false"
>取消</el-button
>
<el-button style="width: 90px" type="primary" @click="cancelSubmit"
>提交</el-button
>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, onMounted, watch, nextTick } from "vue";
import templateHooks from "@/Hooks/templateHooks.js";
import { purifierTaskService } from "@/ApiService/taskCenterService";
import { dropdownService } from "@/ApiService/dropdownService";
import purifierTaskDetailCom from "@/Components/taskCenter/purifierTaskDetailCom.vue";
//页面基础数据
const pageBasicsData = reactive({
loading: true, // 页面加载状态
tableHeight: 200, //表格高度
screenForm: {
// 顶部搜索字段
dateType: 0,
date: [],
districtId: "",
no: "",
name: "",
taskType: "",
taskCreateType: "",
status: "",
taskScene: "",
gridAndScenes: [],
taskDistributiUser: "",
taskAcceptUser: "",
},
districtList: [], // 所属站点下拉列表
taskSceneList: [], // 任务场景下拉列表
personSelectList: [
{
id: 0,
name: "全部",
},
], // 派单and接单人员列表
areaGridSelectProps: {
value: "gridId",
label: "name",
children: "childNode",
checkStrictly: true,
multiple: true,
},
taskDateTypeList: [
// 时间类型下拉列表
{
key: 0,
value: "生成日期",
},
{
key: 1,
value: "派发日期",
},
{
key: 2,
value: "响应日期",
},
{
key: 3,
value: "作业日期",
},
{
key: 4,
value: "完成日期",
},
{
key: 5,
value: "过期日期",
},
],
});
// 查看任务弹窗
const showLookDialog = ref(false);
// 查看任务数据
const taskDetailData = ref({});
// 查看任务操作相关
const lookRelevant = reactive({
lookForm: {},
});
// 取消任务操作相关
const cancelRelevant = reactive({
showCancelDialog: false,
cancelForm: {
cancelReason: "",
detailReason: "",
},
cancelCauseSelectList: [
{
key: 0,
value: "任务信息填错",
},
{
key: 1,
value: "任务重复",
},
{
key: 2,
value: "已通过其它方式解决",
},
{
key: 3,
value: "其他原因",
},
],
});
// 元素ref
const topSearchRef = ref(); //顶部搜索区域ref
const screenFormRef = ref(); //搜索区ref
const taskSceneRef = ref(); // 任务场景ref
const cancelRef = ref(); // 取消任务ref
onMounted(() => {
setDefaultCancelDialog();
//获取站点数据
fetchDistricts();
buttonsClickFun.data = {
// 查看
look: () => {
lookTask();
},
// 取消
cancel: () => {
cancelRelevant.showCancelDialog = true;
},
};
});
//#region watch定义start
// 设置表格高度
watch(
() => topSearchRef.value,
(val) => {
let wHeight =
document.documentElement.clientHeight || document.body.clientHeight;
nextTick(() => {
pageBasicsData.tableHeight = wHeight - val.clientHeight - 184;
});
}
);
// 站点变化清空其它查询条件
watch(
() => pageBasicsData.screenForm.districtId,
(val) => {
if (val) {
for (const key in pageBasicsData.screenForm) {
if (key !== "districtId") {
pageBasicsData.screenForm[key] = "";
}
}
}
pageBasicsData.screenForm.dateType = 0;
setDefaultCancelDialog();
fetchTaskScene(val);
fetchTaskPerson(val);
}
);
watch(
() => pageBasicsData.screenForm.date,
(val) => {}
);
//#endregion watch定义end
//#region 函数定义start
// 顶部按钮事件
const buttonClick = ({ enName }) => {
if (enName == "export") {
setDateFormat();
const { page, rows } = pageProps;
purifierTaskService.export({
page,
rows,
...pageBasicsData.screenForm,
});
}
};
// 任务场景级联事件
const taskSceneHandleChange = () => {
let checkArr = taskSceneRef.value.getCheckedNodes();
let gridAndScenes = [];
checkArr.forEach((item) => {
gridAndScenes.push({
gridId: item.data.gridId,
id: item.data.id,
isscene: item.data.isscene,
level: item.data.level,
sceneId: item.data.sceneId,
});
});
pageBasicsData.screenForm.gridAndScenes = gridAndScenes;
};
// 取消任务提交
const cancelSubmit = () => {
cancelRef.value.validate((valid) => {
if (valid) {
$messageBox
.confirm("您确定要进行提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
center: true,
})
.then(() => {
return new Promise(() => {
purifierTaskService
.cancel({
id: lookRelevant.lookForm.id,
...cancelRelevant.cancelForm,
})
.then(async (res) => {
if (res.code == 0) {
cancelRelevant.showCancelDialog = false;
fetchData();
$message.success(res.data);
} else {
$message.error(res.err);
}
});
});
})
.catch(() => {});
}
});
};
// 关闭取消任务弹窗
const closeCancelDialog = () => {
cancelRef.value.resetFields();
};
// 默认时间设置
const setDefaultCancelDialog = () => {
const start = new Date(new Date().toLocaleDateString());
const end = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
pageBasicsData.screenForm.date = [
$common.fomatDateTime(start),
$common.fomatDateTime(end),
];
};
// 设置查询日期格式
const setDateFormat = () => {
for (const key in pageBasicsData.screenForm) {
if (key.indexOf("Time") > -1) {
delete pageBasicsData.screenForm[key];
}
}
let dateArr = pageBasicsData.screenForm.date;
if (pageBasicsData.screenForm.dateType == 0) {
// 生成日期
pageBasicsData.screenForm.createTimeStart = dateArr[0];
pageBasicsData.screenForm.createTimeEnd = dateArr[1];
} else if (pageBasicsData.screenForm.dateType == 1) {
// 派发日期
pageBasicsData.screenForm.sendTimeStart = dateArr[0];
pageBasicsData.screenForm.sendTimeEnd = dateArr[1];
} else if (pageBasicsData.screenForm.dateType == 2) {
// 响应日期
pageBasicsData.screenForm.confirmTimeStart = dateArr[0];
pageBasicsData.screenForm.confirmTimeEnd = dateArr[1];
} else if (pageBasicsData.screenForm.dateType == 3) {
// 作业日期
pageBasicsData.screenForm.actionTimeStart = dateArr[0];
pageBasicsData.screenForm.actionTimeEnd = dateArr[1];
} else if (pageBasicsData.screenForm.dateType == 4) {
// 完成日期
pageBasicsData.screenForm.finishTimeStart = dateArr[0];
pageBasicsData.screenForm.finishTimeEnd = dateArr[1];
} else if (pageBasicsData.screenForm.dateType == 5) {
// 过期日期
pageBasicsData.screenForm.expireTimeStart = dateArr[0];
pageBasicsData.screenForm.expireTimeEnd = dateArr[1];
}
};
// 获取表格数据
const fetchData = () => {
setDateFormat();
const { page, rows } = pageProps;
return new Promise(() => {
purifierTaskService
.pageList({
page,
rows,
...pageBasicsData.screenForm,
})
.then((res) => {
if (res.code == 0) {
pageBasicsData.loading = false;
tableData.value = res.data.rows;
pageProps.records = res.data.records;
}
});
});
};
//查询
const restSearch = () => {
pageProps.page = 1;
fetchData();
};
// 清空搜索
const clearScreen = () => {
screenFormRef.value.resetFields();
pageBasicsData.screenForm.districtId = pageBasicsData.districtList[0].id;
delete pageBasicsData.screenForm.gridAndScenes;
fetchData();
};
// 获取所属站点
const fetchDistricts = () => {
return new Promise(() => {
dropdownService.getDistrict().then(async (res) => {
if (res.code == 0) {
pageBasicsData.districtList = res.data;
if (pageBasicsData.districtList?.length) {
pageBasicsData.screenForm.districtId =
pageBasicsData.districtList[0].id;
fetchData();
fetchTaskScene(pageBasicsData.screenForm.districtId);
fetchTaskPerson(pageBasicsData.screenForm.districtId);
} else {
$message.error("暂无站点信息,请配置站点!");
}
}
});
});
};
// 查看任务
const lookTask = () => {
return new Promise(() => {
purifierTaskService
.look({ id: lookRelevant.lookForm.id })
.then(async (res) => {
if (res.code == 0) {
taskDetailData.value = res.data;
showLookDialog.value = true;
}
});
});
};
// 获取任务场景
const fetchTaskScene = (id) => {
return new Promise(() => {
dropdownService.gridSceneTree({ districtId: id }).then(async (res) => {
if (res.code == 0) {
pageBasicsData.taskSceneList = res.data.childNode;
}
});
});
};
// 获取任务人员
const fetchTaskPerson = (id) => {
return new Promise(() => {
dropdownService.principalList({ districtId: id }).then(async (res) => {
pageBasicsData.personSelectList = res.data;
});
});
};
// 自定义表格头
const fetchTableAttr = (tableAttr) => {
tableHeader.value = tableAttr;
};
// 表格按钮
const rowButtonClick = ({ row, $column }) => {
for (let i in row) {
lookRelevant.lookForm[i] = row[i];
}
buttonsClickFun.data[$column.enName]();
};
const {
tableData,
rowButtons,
pageProps,
tableHeader,
pageChange,
buttonsClickFun,
$message,
$messageBox,
$common,
selectItems,
} = templateHooks(fetchData);
//#endregion 函数定义 end
</script>
<script>
export default {
name: "PurifierTask",
};
</script>
<style lang="scss" scoped>
.task-box {
box-sizing: border-box;
height: calc(100vh - 146px);
flex: 1;
padding: 10px;
background-color: #fff;
.search-area {
padding: 10px 0 10px 10px;
display: flex;
align-items: center;
}
}
.dialog-footer button:first-child {
margin-right: 10px;
}
.dialog-item {
width: 100%;
display: flex;
align-items: center;
margin-left: 30px;
.dialog-item-left {
margin-right: 30px;
div {
margin-bottom: 30px;
}
}
.dialog-item-right {
.el-button {
margin-bottom: 26px;
}
}
}
:deep(.el-upload-list__item-status-label) {
position: absolute;
right: -25px;
top: 0;
line-height: inherit;
}
:deep(.el-upload-list__item .el-icon--close) {
position: absolute;
top: 5px;
right: -10px;
cursor: pointer;
opacity: 0.75;
color: #292d3e;
}
.content-test {
width: 200px;
font-size: 14px;
.btn {
width: 30px;
height: 30px;
}
}
.statistics {
background-color: #fff;
border: 1px solid rgba(150, 145, 145, 0);
border-radius: 2px;
box-sizing: border-box;
.statistics-top {
font-size: 16px;
height: 30px;
line-height: 30px;
padding-left: 6px;
border-bottom: 1px solid #f0f0f0;
font-weight: bold;
background: #f0f0f0;
}
.statistics-bottom {
line-height: 25px;
font-size: 15px;
color: #606266;
padding-left: 6px;
background: #fff;
margin-top: 10px;
margin-bottom: 10px;
}
}
.look-collapse {
.collapse-item {
:deep(.el-collapse-item__header) {
background-color: #f0f0f0;
}
.title-icon {
color: #409eff;
margin: 0 4px;
font-size: 18px;
font-weight: bold;
margin-top: -1px;
}
.title-content {
font-size: 18px;
font-weight: bold;
margin-left: 10px;
}
}
}
.task-dictionaries {
.task-dictionaries-item {
:deep(.el-collapse-item__header) {
background-color: #f0f0f0;
}
.task-dictionaries-icon {
color: #409eff;
margin: 0 4px;
font-size: 18px;
font-weight: bold;
margin-top: -1px;
}
.task-dictionaries-content {
font-size: 18px;
font-weight: bold;
margin-left: 10px;
}
}
}
</style>