<template>
<div class="project-management-block">
<!-- 弹窗组件 -->
<side-slope-dialog
:visible="dialogVisible"
:mode="currentMode"
:initial-form="currentForm"
@update:visible="dialogVisible = $event"
@success="handleDialogSuccess" />
<div class="project-management-block--header">
<el-form
size="mini"
:inline="true"
class="fr ml10"
align="left">
<el-input
v-model="searchParams.projectName"
placeholder="项目名称或编号"
size="mini"
clearable
@clear="resetSearch"
style="width: 140px;"
class="mr10" />
<el-select
v-model="searchParams.status"
placeholder="项目状态"
size="mini"
clearable
@clear="resetSearch"
style="width: 140px;"
class="mr10">
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
filterable />
</el-select>
<el-date-picker
v-model="searchProjectDate"
value-format="timestamp"
size="mini"
class="mr10"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
<el-button
type="primary"
size="mini"
style="width: 80px;"
@click="handleSearch"
class="mr10"
>查询
</el-button>
<el-button
type="success"
size="mini"
style="width: 80px;"
@click="openCreateDialog"
class="mr10"
>新建
</el-button>
</el-form>
</div>
<div class="project-management-block--content" >
<!-- 项目数据表格 -->
<el-table
:data="tableData"
border
stripe
style="width: 100%;
flex: 1;"
height="100%"
row-key="id"
>
<el-table-column
label="序号"
type="index"
width="120">
</el-table-column>
<el-table-column
label="项目名称"
prop="projectName"
width="250">
</el-table-column>
<el-table-column
label="项目编号"
prop="projectCode"
width="220">
</el-table-column>
<el-table-column
label="项目周期"
width="250">
<template slot-scope="scope">
<span v-if="scope.row">{{ `${formatDate(scope.row.projectStartDate)} 至 ${formatDate(scope.row.projectEndDate)}` }}</span>
</template>
</el-table-column>
<el-table-column
label="项目状态"
width="150">
<template slot-scope="scope">
{{ getStatusText(scope.row.status)}}
</template>
</el-table-column>
<el-table-column
label="边坡总数"
prop="sideSlopeTotalCount"
width="150">
</el-table-column>
<el-table-column
label="已完成边坡数"
prop="sideSlopeCompleteCount"
width="194">
</el-table-column>
<el-table-column
label="完成率"
width="150">
<template slot-scope="scope">
{{ `${((scope.row.sideSlopeCompleteCount / scope.row.sideSlopeTotalCount) * 100).toFixed(1)}%` }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="195">
<template
slot-scope="scope">
<div
v-if="scope.row.id"
style="display: flex;
justify-content: center;">
<el-button
size="mini"
type="primary"
@click="openViewDialog(scope.row)"
style="padding: 4px 8px;
font-size: 12px"
>查看
</el-button>
<el-button
size="mini"
type="info"
@click="openEditDialog(scope.row)"
style="padding: 4px 8px;
font-size: 12px"
>编辑
</el-button>
<el-button
size="mini"
type="danger"
@click="deleteItem(scope.row)"
style="padding: 4px 8px;
font-size: 12px"
>删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="project-management-block--footer">
<el-pagination
background
layout="total,prev, pager, next,jumper"
:current-page.sync="pageParams.pageNo"
:page-size="pageParams.pageSize"
:total="pageParams.total"/>
</div>
</div>
</template>
<script>
// 导入模块
import SideSlopeDialog from './SideSlopeDialog.vue' // 项目详情弹窗组件
import { mapCfg } from '@/utils' // 字典配置映射工具
//接口
import {
getPeriodicInspectionPageList,
deletePeriodicInspection
} from '../../api/testProject'
import moment from 'moment'
// 组件定义
export default {
name: 'ProjectManagement', // 组件名称
components: {
SideSlopeDialog // 注册弹窗组件
},
// 数据模型
data() {
return {
// 搜索参数对象
searchParams: {
projectName: '', // 项目名称/编号搜索词
status: '', // 项目状态筛选值
projectStartDate: '', // 项目开始日期
projectEndDate: '' // 项目结束日期
},
// 日期范围选择器绑定值
searchProjectDate: [],
// 表格数据源
tableData: [],
// 分页参数
pageParams: {
pageNo: 1, // 当前页码
pageSize: 10, // 每页条数
total: 0 // 总数据量
},
// 弹窗控制参数
dialogVisible: false, // 弹窗显示状态
currentMode: '', // 弹窗模式: 'create'/'edit'/'view'
currentForm: null // 当前表单数据
}
},
// 监听器
watch: {
//监听日期范围选择器变化:将选择器值同步到搜索参数对象
searchProjectDate(newVal) {
if (newVal && newVal.length === 2) {
this.searchParams.projectStartDate = newVal[0]
this.searchParams.projectEndDate = newVal[1]
} else {
this.searchParams.projectStartDate = ''
this.searchParams.projectEndDate = ''
}
}
},
// 生命周期钩子
async created() {
// 初始化状态选项
// this.getStatus()
// 加载表格数据
this.loadTableData()
},
computed:{
statusOptions() {
const dictList = mapCfg('Inspection.Periodic.PeriodicInspectionStatus')()
return dictList.map(item => ({
value: item.key,
label: item.value
}))
},
},
// 方法/函数
methods: {
// 工具方法
//根据状态值获取状态文本
getStatusText(statusValue) {
const option = this.statusOptions.find((opt) => opt.value === statusValue)
return option ? option.label : ''
},
// 格式化时间
formatDate(date) {
if (!date) return "";
return moment(date).format(`YYYY-MM-DD`);
},
// 弹窗操作方法
//创建项目弹窗
openCreateDialog() {
this.currentMode = 'create'
// 重置表单数据
this.currentForm = {
projectCode: '',
projectName: '',
projectStartDate: '',
projectEndDate: '',
projectUser: '',
remark: '',
sideSlopeDetailList: []
}
this.dialogVisible = true
},
//编辑项目弹窗
openEditDialog(row) {
this.currentMode = 'edit'
// 复制当前行数据到表单
this.currentForm = {
...row,
projectStartDate: row.projectStartDate,
projectEndDate: row.projectEndDate
}
this.dialogVisible = true
},
//查看项目弹窗
openViewDialog(row) {
this.currentMode = 'view'
// 复制当前行数据到表单
this.currentForm = {
...row,
projectStartDate: row.projectStartDate,
projectEndDate: row.projectEndDate
}
this.dialogVisible = true
},
// 弹窗操作成功回调,刷新表格数据(返回第一页)
handleDialogSuccess() {
this.pageParams.pageNo = 1
this.loadTableData()
},
// 数据操作方法
//加载表格数据,根据搜索参数和分页设置获取项目数据
async loadTableData() {
// 转换日期为时间戳格式
const startTime = this.searchParams.projectStartDate
? new Date(this.searchParams.projectStartDate).getTime()
: null
const endTime = this.searchParams.projectEndDate
? new Date(this.searchParams.projectEndDate).getTime()
: null
// 构造API参数
const params = {
pageNo: this.pageParams.pageNo,
pageSize: this.pageParams.pageSize,
searchKey: this.searchParams.projectName,
status: this.searchParams.status,
startTime,
endTime
}
try {
// 调用API获取项目数据
const res = await getPeriodicInspectionPageList(params)
this.tableData = res.entities || []
this.pageParams.total = res.entityCount || 0
} catch (error) {
console.error('加载项目列表失败', error)
this.tableData = []
this.pageParams.total = 0
}
},
//搜索方法重置到第一页并重新加载数据
handleSearch() {
this.pageParams.pageNo = 1
this.loadTableData()
},
//重置搜索条件,清空所有搜索参数并重新加载数据
resetSearch() {
this.searchParams = {
projectName: '',
status: '',
projectStartDate: '',
projectEndDate: ''
}
this.searchProjectDate = []
this.handleSearch()
},
//删除项目
async deleteItem(row) {
try {
// 显示确认对话框
await this.$confirm('确定要删除该项目吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
// 调用删除API
await deletePeriodicInspection({ periodicId: row.id })
this.$message.success('删除成功')
// 如果删除的是最后一页的最后一条,返回上一页
if (this.tableData.length === 1 && this.pageParams.pageNo > 1) {
this.pageParams.pageNo -= 1
}
// 重新加载数据
this.loadTableData()
} catch (error) {
// 用户取消删除时不显示错误
if (error !== 'cancel') {
this.$message.error('删除失败')
}
}
},
}
}
</script>
<style lang="scss" scoped>
.project-management-block {
width: 100%;
height: 100%;
position: relative;
background-color: #fff;
&--header {
height: 50px;
box-sizing: border-box;
padding: 10px;
border-bottom: 1px solid #ebeef5;
}
&--content {
display: block;
padding: 10px;
height: calc(100% - 90px);
position: relative;
z-index: 10;
}
&--footer {
border-top: 1px solid #ebeef5;
padding: 4px 10px 0 10px;
position: relative;
z-index: 11;
text-align: center;
}
}
/* 优化表格样式 */
::v-deep .el-table {
flex: 1;
min-height: 0; // 防止flex布局溢出
/* 单元格样式 */
th,
td {
padding: 4px 0;
}
/* 表头样式 */
.el-table__header-wrapper {
line-height: 1;
th {
.cell {
line-height: 1.2;
}
}
}
}
/* 分页组件样式优化,确保在不同缩放比例下可见 */
::v-deep .el-pagination {
padding: 4px 5px;
.btn-prev,
.btn-next,
.el-pager li,
.el-pagination__jump {
min-width: 28px;
height: 28px;
line-height: 28px;
margin: 0 2px;
}
.el-pagination__total,
.el-pagination__jump {
font-size: 12px;
}
}
/* 响应式调整 */
@media screen and (max-width: 1200px) {
.project-management-block--header .el-col {
margin-bottom: 8px;
}
::v-deep .el-pagination {
display: flex;
flex-wrap: wrap;
justify-content: center;
&>* {
margin-bottom: 5px;
}
}
}
</style>/* * @Author: liuhm * @Date: 2024-9-26 14:43:05 * @Last Modified by: liuhm * @Last
Modified time: 2024-9-26 14:43:09 */ /**
|-------------------------------------------------- | | 任务管理 |
|-------------------------------------------------- */
<template>
<el-card class="custom">
<!-- 头部 START -->
<div slot="header" class="plr10 clearfix">
<div class="fl header-seach-box">
<el-form :model="searchFormData" class="fl mr5">
<el-cascader
style="width: 200px"
v-model="searchFormData.orgId"
clearable
class="ml10"
filterable
:options="maintenanceCompanyList"
:props="{
value: 'id',
label: 'name',
emitPath: false,
checkStrictly: true,
children: 'childrenList'
}"
size="mini"
placeholder="请选择管养单位"
></el-cascader>
<el-select
style="width: 200px"
v-model="searchFormData.routeId"
clearable
class="ml10"
filterable
size="mini"
placeholder="请选择巡查路线"
>
<el-option
v-for="item in routerList"
:key="item.id"
:label="item.routeCode"
:value="item.id"
>
</el-option>
</el-select>
<div v-if="hasFunctionCode(functionList, 'PERM_10244')" class="fr ml5">
<el-button size="mini" icon="el-icon-search " @click="searchTable" />
</div>
</el-form>
</div>
</div>
<!-- 头部 END -->
<!-- 内容 START -->
<el-table
v-loading="tableLoading"
size="mini"
:data="dataSource"
:height="`${cardContentHeight + 35}px`"
row-key="id"
style="width: 100%"
border
stripe
:cell-class-name="cellClass"
>
<el-table-column label="序号" width="50" type="index" align="left" />
<el-table-column label="管养单位" prop="orgName" width="230" align="left" />
<el-table-column label="巡查时间" align="center" width="200" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ `${formatDate(scope.row.inspectStartDate)} -${formatDate(scope.row.inspectEndDate)}` }}</span>
</template>
</el-table-column>
<el-table-column
label="巡查路线"
prop="routeName"
width="280"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ scope.row.routeCode +scope.row.routeName }}</span>
</template>
</el-table-column>
<el-table-column
label="巡查状态"
prop="status"
width="100"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<span>{{ scope.row.status | DailyInspectionStatusMap }}</span>
</template>
</el-table-column>
<el-table-column
label="巡检人"
prop="inspectUser"
align="center"
show-overflow-tooltip
/>
<el-table-column
label="记录人"
prop="recorder"
align="center"
show-overflow-tooltip
>
</el-table-column>
<el-table-column label="操作" fixed="right" width="140" align="center">
<template slot-scope="scope">
<ul class="table-button-list">
<!-- <template v-if="hasFunctionCode(functionList, 'PERM_10249')">
<li @click="detailDailyInspection(scope.row)">
<img src="@/assets/images/table/chakan.png" />详情
</li>
</template> -->
<template v-if="hasFunctionCode(functionList, 'PERM_10246')">
<li @click="modifyDailyInspection(scope.row)">
<img src="@/assets/images/table/bianji.png" />编辑
</li>
</template>
<!-- <template v-if="hasFunctionCode(functionList, 'PERM_10247')">
<li @click="deleteDailyInspection(scope.row)">
<img src="@/assets/images/table/shanchu.png" />删除
</li>
</template> -->
</ul>
<!-- <el-button-group>
<template v-if="hasFunctionCode(functionList, 'PERM_10249')">
<el-button
size="mini"
type="primary"
icon="el-icon-view"
@click="detailDailyInspection(scope.row)"
></el-button>
</template>
<template v-if="hasFunctionCode(functionList, 'PERM_10246')">
<el-button
size="mini"
type="primary"
icon="el-icon-edit-outline"
@click="modifyDailyInspection(scope.row)"
></el-button>
</template>
<template v-if="hasFunctionCode(functionList, 'PERM_10247')">
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
@click="deleteDailyInspection(scope.row)"
></el-button>
</template>
<template v-if="hasFunctionCode(functionList, 'PERM_10248')">
<el-button
size="mini"
icon="el-icon-document-checked"
@click="completeDailyInspection(scope.row)"
></el-button>
</template>
</el-button-group> -->
</template>
</el-table-column>
</el-table>
<el-pagination
class="mt10"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page.pageNo"
:page-sizes="[10, 20, 30, 40, 50]"
:page-size="page.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="entityCount"
>
</el-pagination>
<!-- 内容 END -->
<!-- 组件 START -->
<template>
<InspectionDialog ref="InspectionDialog" />
</template>
<!-- 组件 END -->
</el-card>
</template>
<script>
// 接口
import {
getDailyInspectionList,
deleteDailyInspection,
completeDailyInspection,
getDailyDiseaseDetailPageList
} from "@/api/dailyInspection";
import {
getMaintenanceCompanyList,
getRouteList
} from "@/api/commonAnalysis"
// 组件
import InspectionDialog from "./inspection-dialog/InspectionDialog";
// mixin
import autoHeight from "@/mixin/autoHeight";
import { CONFIRM as CONF } from "@/optionsCfg/Message.js";
import { DIALOG_CLOSED_TYPE as DIALOG } from "@/optionsCfg/Constants";
import moment from "moment";
import { mapCfg } from "@/utils";
export default {
name: "DailyInspection",
components: {
InspectionDialog,
},
mixins: [autoHeight],
data() {
return {
searchFormData: {
orgId: "", // 管养单位id
routeId: "", // 巡查路线id
status: "", // 巡查状态
},
tableLoading: false,
dataSource: [],
page: {
pageSize: 20,
pageNo: 1,
},
searchTime:[],
entityCount: 0,
routerList: [],
maintenanceCompanyList:[],
functionList: this.$store.getters.getFunction,
deviceTypeOpt: [], // 设备类型配置
bridgeMonitorTypeOpt: [], // 监测类型列表
isFirstLoad: false,
};
},
created() {
this.isFirstLoad = true;
this.getRouteList();
this.getMaintenanceCompanyList();
this.loadTableData();
},
filters: {
//边坡与路线位置关系
DailyInspectionStatusMap(key) {
const config = mapCfg("Inspection.Daliy.DailyInspectionStatus")();
let name = "";
config.forEach((item) => {
if (item.key === key) {
name = item.value;
}
});
return name;
},
},
computed: {
dailyInspectionStatusConfig() {
const DailyInspectionStatus = mapCfg("Inspection.Daliy.DailyInspectionStatus")().map((item) => {
return {
value: item.key,
label: item.value,
};
});
return DailyInspectionStatus;
},
},
methods: {
// 加载表格数据
loadTableData() {
this.tableLoading = true;
const params = {
pageSize: this.page.pageSize,
pageNo: this.page.pageNo,
status: this.searchFormData.status,
routeId: this.searchFormData.routeId,
orgId: this.searchFormData.orgId,
startTime: this.searchTime && this.searchTime[0],
endTime: this.searchTime && this.searchTime[1],
};
getDailyInspectionList(params)
.then((res) => {
if (res) {
this.dataSource = res.entities || [];
this.entityCount = res.entityCount;
if (res.pageCount < this.page.pageNo) {
this.page.pageNo = res.pageCount;
this.loadTableData();
}
}
})
.catch((e) => {
this.$message.error(e && e.message);
console.warn(e);
})
.finally((_) => {
this.tableLoading = false;
});
},
// 搜索
searchTable() {
this.page.pageNo = 1;
this.loadTableData();
},
// 格式化时间
formatDate(date) {
if (!date) return "";
return moment(date).format(`YYYY-MM-DD`);
},
// 更改一页显示数量时
handleSizeChange(pageSize) {
this.page.pageNo = 1;
this.page.pageSize = pageSize;
this.loadTableData();
},
// 分页改变时
handleCurrentChange(page) {
this.page.pageNo = page;
this.loadTableData();
},
// 获取养护单位列表
async getMaintenanceCompanyList() {
try {
const res = await getMaintenanceCompanyList();
if (res) {
this.maintenanceCompanyList = res;
}
} catch (err) {
console.log(err);
}
},
// 获取巡查路线列表编号
async getRouteList() {
try {
const res = await getRouteList();
if (res) {
this.routerList = res;
}
} catch (err) {
console.log(err);
}
},
// 添加边坡基本信息
addDailyInspection() {
this.$refs["InspectionDialog"].open();
this.$refs["InspectionDialog"].onClosed = (args) => {
if (DIALOG.CONFIRM === args.option) {
this.page.pageNo = 1;
this.loadTableData();
}
};
},
//查看边坡基本信息
async detailDailyInspection(row) {
try {
// this.$store.commit("SHOW_WAITING");
this.$refs["InspectionDialog"].open(row);
this.$refs["InspectionDialog"].onClosed = (args) => {
if (DIALOG.CONFIRM === args.option) {
// this.page.pageNo = 1
this.loadTableData();
}
};
} catch (e) {
console.warn(e);
this.$store.commit("CLOSE_WAITING");
}
},
// 修改边坡基本信息
async modifyDailyInspection(row) {
try {
this.$store.commit("SHOW_WAITING");
this.$refs["InspectionDialog"].open(row);
this.$refs["InspectionDialog"].onClosed = (args) => {
if (DIALOG.CONFIRM === args.option) {
// this.page.pageNo = 1
this.loadTableData();
}
};
} catch (e) {
console.warn(e);
this.$store.commit("CLOSE_WAITING");
}finally {
this.$store.commit("CLOSE_WAITING");
}
},
// 删除项目
async deleteDailyInspection(row) {
try {
await this.$confirm(CONF.DELETE, CONF.TITLE, {
closeOnClickModal: false,
confirmButtonText: CONF.YES,
cancelButtonText: CONF.NO,
type: "warning",
});
} catch (e) {
return;
} // eslint-disable-line
try {
await this.deleteSideSlopeInfo({ dailyId : row.id });
} catch (e) {
console.warn(e);
this.$message.error(e && e.message);
}
},
// 删除项目接口
async deleteSideSlopeInfo(id) {
try {
this.$store.commit("SHOW_WAITING");
const res = await deleteDailyInspection(id);
if (res) {
this.page.pageNo = 1;
this.loadTableData();
this.$message.success("删除成功");
}
} catch (e) {
console.warn(e);
this.$message.error(e && e.message);
} finally {
this.$store.commit("CLOSE_WAITING");
}
},
cellClass({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 3) return "table-align";
},
async uploadBridgeDeviceInfo(file) {
// 设备导入
this.$store.commit("SHOW_WAITING");
try {
const formData = new FormData();
formData.append("file", file.file);
const res = await importBridgeDeviceInfo(formData);
if (res) {
this.$message.success("导入成功");
this.page.pageNo = 1;
this.loadTableData();
}
} catch (e) {
console.warn(e);
this.$message.error(e && e.message);
} finally {
this.$store.commit("CLOSE_WAITING");
}
},
downLoadFile() {
if (!this.searchFormData.bridgeId) {
this.$message.warning("请选择桥梁");
return;
}
const bridgeList = this.$store.state.bridge.bridgeList.filter(
(item) => item.id === this.searchFormData.bridgeId
);
if (bridgeList[0] && bridgeList[0].hasOwnProperty("bridgeNo")) {
const bridgeCode = bridgeList[0].bridgeNo;
downloadMonitorDeviceInfo(bridgeCode)
.then((res) => {
if (res && res.message) {
console.warn(res);
this.$message.error(res && res.message);
}
})
.catch((e) => {
this.$message.error(e && e.message);
console.warn(e);
});
} else {
this.$message.warning("暂无桥梁");
}
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-button-group > .el-button:not(:last-child) {
margin-right: 0;
}
.header-seach-box {
height: 46px;
box-sizing: border-box;
padding: 9px 0;
}
::v-deep .table-align .el-tooltip {
padding-left: 28%;
text-align: left;
}
::v-deep .el-table th > .cell {
color: #000;
}
::v-deep .el-table th {
background-color: #eff3f8;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
background-color: rgb(239, 243, 248, 0.6);
}
.table-button-list{
grid-template-columns: repeat(1, 1fr);
}
</style>
projectManagement的组件应用方式参考Inspection帮我修改