- 新增 deploy/docker/:Docker 本机模拟部署,含 Dockerfile、docker-compose、deploy.sh 一键脚本 - 新增 deploy/remote/:远程服务器部署,含 SSH 自动上传、重启、回滚脚本 - 新增 deploy/README.md:完整使用手册,含现状分析、落地调整工作清单、命令速查 - 新增 build.sh/start.sh:本地构建和启动脚本(含飞书通知) - 新增前端 .env.docker 环境配置,API 指向测试服务器 - 前端 package.json 新增 build-docker 命令 - 更新 .gitignore:排除 IDE 配置、SQL 数据、Docker 敏感文件 - 前端 UI 样式优化(多个页面组件) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
536 lines
15 KiB
Vue
536 lines
15 KiB
Vue
<template>
|
|
<el-skeleton :rows="30" :loading="pageBasicsData.loading" />
|
|
<div class="task-box" v-if="!pageBasicsData.loading">
|
|
<qu-search-area ref="topSearchRef" :model="pageBasicsData.screenForm" @search="restSearch" @reset="clearScreen">
|
|
<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="userId">
|
|
<div class="screen-item">
|
|
<el-select
|
|
filterable
|
|
clearable
|
|
placeholder="请选择管理人员"
|
|
v-model="pageBasicsData.screenForm.userId"
|
|
>
|
|
<el-option
|
|
v-for="item in pageBasicsData.personSelectList"
|
|
:key="item.id"
|
|
:label="item.name"
|
|
:value="item.id"
|
|
></el-option>
|
|
</el-select>
|
|
</div>
|
|
</el-form-item>
|
|
<el-form-item label="手机号" prop="mobile">
|
|
<div class="screen-item">
|
|
<el-input
|
|
placeholder="请输入手机号码"
|
|
clearable
|
|
v-model="pageBasicsData.screenForm.mobile"
|
|
></el-input>
|
|
</div>
|
|
</el-form-item>
|
|
</qu-search-area>
|
|
<!-- 表格 -->
|
|
<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"
|
|
showOverflowTooltip
|
|
:tableButtons="[
|
|
{ cnName: '新建', enName: 'add', theme: 'success', icon: 'plus' },
|
|
{ cnName: '导出', enName: 'export', theme: 'primary', icon: 'top' },
|
|
]"
|
|
@buttonClick="buttonClick"
|
|
></qu-table>
|
|
</div>
|
|
|
|
<el-dialog
|
|
width="600px"
|
|
v-model="addOrEditRelevant.openDialog"
|
|
:title="addOrEditRelevant.currentForm.id ? '编辑' : '新建'"
|
|
@close="closeDialog"
|
|
>
|
|
<el-form
|
|
label-width="130px"
|
|
ref="addOrEditRef"
|
|
:model="addOrEditRelevant.currentForm"
|
|
>
|
|
<el-form-item
|
|
label="所属站点"
|
|
prop="districtId"
|
|
:rules="{
|
|
required: true,
|
|
message: '请选择所属站点',
|
|
trigger: 'change',
|
|
}"
|
|
>
|
|
<el-select
|
|
style="width: 350px"
|
|
filterable
|
|
placeholder="请选择所属站点"
|
|
:disabled="addOrEditRelevant.currentForm.id ? true : false"
|
|
v-model="addOrEditRelevant.currentForm.districtId"
|
|
>
|
|
<el-option
|
|
:label="item.name"
|
|
:value="item.id"
|
|
v-for="item in pageBasicsData.districtList"
|
|
:key="item.id"
|
|
></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item
|
|
label="管理人员"
|
|
prop="userIds"
|
|
:rules="{
|
|
required: true,
|
|
message: '请选择管理人员',
|
|
trigger: 'change',
|
|
}"
|
|
>
|
|
<el-input
|
|
style="width: 350px"
|
|
placeholder="请选择管理人员"
|
|
disabled
|
|
v-model="addOrEditRelevant.currentForm.userIds"
|
|
v-if="addOrEditRelevant.functionaryList.length <= 0"
|
|
/>
|
|
<div
|
|
style="
|
|
width: 350px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 5px;
|
|
background-color: #f5f7fa;
|
|
"
|
|
v-else
|
|
>
|
|
<el-tag
|
|
style="margin: 5px"
|
|
v-for="tag in addOrEditRelevant.functionaryList"
|
|
:key="tag.name"
|
|
:type="tag.type"
|
|
>
|
|
{{ tag.name }}
|
|
</el-tag>
|
|
</div>
|
|
<el-button
|
|
v-if="!addOrEditRelevant.currentForm.id"
|
|
type="primary"
|
|
size="small"
|
|
round
|
|
style="margin-left: 5px"
|
|
@click="goSelectPrincipal"
|
|
>去选择</el-button
|
|
>
|
|
</el-form-item>
|
|
<el-form-item
|
|
label="管理区域"
|
|
prop="scenes"
|
|
:rules="{
|
|
required: true,
|
|
message: '请选择管理区域',
|
|
trigger: 'change',
|
|
}"
|
|
>
|
|
<el-cascader
|
|
style="width: 350px"
|
|
ref="sceneRef"
|
|
placeholder=""
|
|
v-model="addOrEditRelevant.currentForm.scenes"
|
|
:options="addOrEditRelevant.scenesOptions"
|
|
:props="{
|
|
expandTrigger: 'hover',
|
|
checkStrictly: false,
|
|
children: 'childNode',
|
|
label: 'name',
|
|
value: 'id',
|
|
multiple: true,
|
|
}"
|
|
clearable
|
|
:show-all-levels="false"
|
|
collapse-tags
|
|
collapse-tags-tooltip
|
|
@change="taskSceneHandleChange"
|
|
@focus="
|
|
() => {
|
|
if (addOrEditRelevant.scenesOptions.length <= 0) {
|
|
$message.warning('当前选择的站点暂无管理区域,请重新选择!');
|
|
}
|
|
}
|
|
"
|
|
>
|
|
</el-cascader>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<span class="dialog-footer">
|
|
<el-button style="width: 90px" @click="closeDialog">取消</el-button>
|
|
<el-button style="width: 90px" type="primary" @click="submit"
|
|
>提交</el-button
|
|
>
|
|
</span>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<!-- 选择负责人 -->
|
|
<div v-if="showSelectPrincipal">
|
|
<el-dialog v-model="showSelectPrincipal" title="选择负责人" fullscreen>
|
|
<selectPrincipal
|
|
@closePrincipalDialog="closePrincipalDialog"
|
|
:districtId="addOrEditRelevant.currentForm.districtId"
|
|
:selectedPersonnel="addOrEditRelevant.functionaryList"
|
|
/>
|
|
</el-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup>
|
|
import { ref, reactive, onMounted, watch, nextTick } from "vue";
|
|
import templateHooks from "@/Hooks/templateHooks.js";
|
|
import { userReportService } from "@/ApiService/taskCenterService";
|
|
import { dropdownService } from "@/ApiService/dropdownService";
|
|
import selectPrincipal from "@/Components/userReportManage/selectPrincipal.vue";
|
|
|
|
//页面基础数据
|
|
const pageBasicsData = reactive({
|
|
loading: true, // 页面加载状态
|
|
tableHeight: 200, //表格高度
|
|
screenForm: {
|
|
districtId: "",
|
|
userId: "",
|
|
mobile: "",
|
|
},
|
|
districtList: [], // 所属站点下拉列表
|
|
personSelectList: [], // 管理人员下拉
|
|
});
|
|
const topSearchRef = ref(); //顶部搜索区域ref
|
|
const screenFormRef = ref(); //搜索区ref
|
|
|
|
// 新建or编辑
|
|
const addOrEditRelevant = reactive({
|
|
openDialog: false,
|
|
currentForm: {
|
|
districtId: "",
|
|
userIds: [],
|
|
scenes:[],
|
|
serviceAreas: [],
|
|
},
|
|
functionaryList: [],
|
|
scenesOptions: [],
|
|
});
|
|
const addOrEditRef = ref();
|
|
const sceneRef = ref();
|
|
const showSelectPrincipal = ref(false); //选择人员
|
|
|
|
//#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] = "";
|
|
}
|
|
}
|
|
}
|
|
fetchTaskPerson(val);
|
|
}
|
|
);
|
|
// add/edit 站点变化
|
|
watch(
|
|
() => addOrEditRelevant.currentForm.districtId,
|
|
(val) => {
|
|
if (val && addOrEditRelevant.openDialog) {
|
|
fetchTaskScene(val);
|
|
}
|
|
}
|
|
);
|
|
//#endregion watch定义end
|
|
onMounted(() => {
|
|
fetchDistricts();
|
|
buttonsClickFun.data = {
|
|
edit: () => {
|
|
if (addOrEditRelevant.currentForm.serviceAreas?.length > 0) {
|
|
addOrEditRelevant.currentForm.scenes =
|
|
addOrEditRelevant.currentForm.serviceAreas.map((item) => item.id);
|
|
}
|
|
const {
|
|
mobile,
|
|
userId: id,
|
|
userName: name,
|
|
} = addOrEditRelevant.currentForm;
|
|
addOrEditRelevant.functionaryList.push({ mobile, id, name });
|
|
addOrEditRelevant.openDialog = true;
|
|
},
|
|
delete: () => {
|
|
$messageBox
|
|
.confirm("此操作将永久删除该数据,是否继续?", "提示", {
|
|
confirmButtonText: "确定",
|
|
cancelButtonText: "取消",
|
|
type: "warning",
|
|
center: true,
|
|
})
|
|
.then(() => {
|
|
userReportService
|
|
.delete({
|
|
id: addOrEditRelevant.currentForm.id,
|
|
})
|
|
.then((res) => {
|
|
if (res.code == 0) {
|
|
$message.success(res.data);
|
|
fetchData();
|
|
} else {
|
|
$message.error(res.err);
|
|
}
|
|
});
|
|
})
|
|
.catch(() => {});
|
|
},
|
|
};
|
|
});
|
|
//#region 函数定义start
|
|
// 顶部按钮事件
|
|
const buttonClick = ({ enName }) => {
|
|
if (enName == "add") {
|
|
addOrEditRelevant.currentForm.id = "";
|
|
addOrEditRelevant.currentForm.districtId = "";
|
|
addOrEditRelevant.openDialog = true;
|
|
}
|
|
if (enName == "export") {
|
|
const { page, rows } = pageProps;
|
|
userReportService.userReportExport({
|
|
page,
|
|
rows,
|
|
...pageBasicsData.screenForm,
|
|
});
|
|
}
|
|
};
|
|
// 编辑or新增提交
|
|
const submit = () => {
|
|
addOrEditRelevant.currentForm.userIds = addOrEditRelevant.functionaryList.map(
|
|
(item) => item.id
|
|
);
|
|
let requestMethods = addOrEditRelevant.currentForm.id
|
|
? userReportService.update
|
|
: userReportService.add;
|
|
addOrEditRelevant.currentForm.serviceAreas = taskSceneHandleChange();
|
|
const { id, districtId, userId, serviceAreas, userIds } =
|
|
addOrEditRelevant.currentForm;
|
|
addOrEditRef.value.validate((valid) => {
|
|
if (valid) {
|
|
$messageBox
|
|
.confirm("您确定要提交么?", "提示", {
|
|
confirmButtonText: "确定",
|
|
cancelButtonText: "取消",
|
|
type: "warning",
|
|
})
|
|
.then(() => {
|
|
requestMethods({
|
|
id,
|
|
districtId,
|
|
userIds,
|
|
userId,
|
|
serviceAreas,
|
|
}).then((res) => {
|
|
if (res.code == 0) {
|
|
fetchData();
|
|
closeDialog();
|
|
} else {
|
|
$message.error(res.err);
|
|
}
|
|
});
|
|
})
|
|
.catch(() => {});
|
|
}
|
|
});
|
|
};
|
|
// 关闭弹窗
|
|
const closeDialog = () => {
|
|
addOrEditRef.value.resetFields();
|
|
addOrEditRelevant.functionaryList = [];
|
|
for (const key in addOrEditRelevant.currentForm) {
|
|
addOrEditRelevant.currentForm[key] = "";
|
|
}
|
|
addOrEditRelevant.openDialog = false;
|
|
};
|
|
// 选择负责人
|
|
const goSelectPrincipal = () => {
|
|
if (!addOrEditRelevant.currentForm.districtId) {
|
|
$message.warning("清选择站点后再进行选择!");
|
|
return;
|
|
}
|
|
showSelectPrincipal.value = true;
|
|
};
|
|
// 关闭负责人弹窗
|
|
const closePrincipalDialog = (val) => {
|
|
let list = [];
|
|
if (val.length) {
|
|
val.forEach((item) => {
|
|
list.push({
|
|
id: item.id,
|
|
name: item.name,
|
|
mobile: item.mobile,
|
|
});
|
|
});
|
|
addOrEditRelevant.functionaryList = list;
|
|
} else {
|
|
addOrEditRelevant.functionaryList = [];
|
|
}
|
|
showSelectPrincipal.value = false;
|
|
};
|
|
// 任务场景级联事件
|
|
const taskSceneHandleChange = () => {
|
|
let checkArr = sceneRef.value.getCheckedNodes();
|
|
let scenes = [];
|
|
checkArr.forEach((item) => {
|
|
scenes.push({
|
|
gridId: item.data.gridId,
|
|
id: item.data.id,
|
|
isscene: item.data.isscene,
|
|
level: item.data.level,
|
|
name: item.data.name,
|
|
sceneId: item.data.sceneId,
|
|
});
|
|
});
|
|
return scenes;
|
|
};
|
|
// 获取表格数据
|
|
const fetchData = () => {
|
|
const { page, rows, sidx, sord } = pageProps;
|
|
userReportService
|
|
.pageList({
|
|
page,
|
|
rows,
|
|
sidx,
|
|
sord,
|
|
...pageBasicsData.screenForm,
|
|
})
|
|
.then((res) => {
|
|
if (res.code == 0) {
|
|
pageBasicsData.loading = false;
|
|
tableData.value = res.data.rows;
|
|
pageProps.records = res.data.records;
|
|
}
|
|
});
|
|
};
|
|
// 管理人员下拉
|
|
const fetchTaskPerson = (id) => {
|
|
dropdownService.principalList({ districtId: id }).then(async (res) => {
|
|
pageBasicsData.personSelectList = res.data;
|
|
});
|
|
};
|
|
// 获取任务场景
|
|
const fetchTaskScene = (id) => {
|
|
return new Promise(() => {
|
|
dropdownService.gridSceneTree({ districtId: id }).then(async (res) => {
|
|
if (res.code == 0) {
|
|
addOrEditRelevant.scenesOptions = res.data.childNode;
|
|
} else {
|
|
$message.error(res.err);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
// 获取所属站点
|
|
const fetchDistricts = () => {
|
|
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();
|
|
} else {
|
|
$message.error("暂无站点信息,请配置站点!");
|
|
}
|
|
}
|
|
});
|
|
};
|
|
// 清空搜索
|
|
const clearScreen = () => {
|
|
screenFormRef.value.resetFields();
|
|
fetchData();
|
|
};
|
|
// 自定义表格头
|
|
const fetchTableAttr = (tableAttr) => {
|
|
tableHeader.value = tableAttr;
|
|
};
|
|
// 表格按钮
|
|
const rowButtonClick = ({ row, $column }) => {
|
|
for (let i in row) {
|
|
addOrEditRelevant.currentForm[i] = row[i];
|
|
}
|
|
buttonsClickFun.data[$column.enName]();
|
|
};
|
|
const {
|
|
tableData,
|
|
rowButtons,
|
|
pageProps,
|
|
tableHeader,
|
|
pageChange,
|
|
buttonsClickFun,
|
|
restSearch,
|
|
$message,
|
|
$messageBox,
|
|
$common,
|
|
} = templateHooks(fetchData);
|
|
//#endregion 函数定义 end
|
|
</script>
|
|
<script>
|
|
export default {
|
|
name: "UserReportManage",
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.task-box {
|
|
box-sizing: border-box;
|
|
height: calc(100vh - var(--page-top-offset));
|
|
flex: 1;
|
|
padding: 10px;
|
|
background-color: var(--color-bg-card);
|
|
.search-area {
|
|
padding: var(--spacing-md) var(--spacing-lg);
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
}
|
|
</style>
|