1212 lines
34 KiB
Vue
1212 lines
34 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<!-- 搜索表单 -->
|
||
<el-form
|
||
:inline="true"
|
||
label-width="80px"
|
||
label-position="right"
|
||
size="small"
|
||
ref="searchFormRef"
|
||
:model="searchParams"
|
||
>
|
||
<el-card class="search-box">
|
||
<!-- 关键修改:使用 flex 布局实现自适应换行 -->
|
||
<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
||
<el-form-item prop="pro_name" label="工程名称" style="margin-bottom: 0; width: 320px">
|
||
<el-input
|
||
clearable
|
||
placeholder="请输入工程名称"
|
||
v-model="searchParams.pro_name"
|
||
style="width: 100%; min-width: 200px;"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<!-- <el-form-item prop="pro_code" label="工程编号" style="margin-bottom: 0; width: 320px">-->
|
||
<!-- <el-input-->
|
||
<!-- clearable-->
|
||
<!-- placeholder="请输入工程编号"-->
|
||
<!-- v-model="searchParams.pro_code"-->
|
||
<!-- style="width: 100%; min-width: 200px;"-->
|
||
<!-- />-->
|
||
<!-- </el-form-item>-->
|
||
|
||
<!-- <el-form-item prop="org_name" label="建管单位" style="margin-bottom: 0; width: 320px">-->
|
||
<!-- <el-input-->
|
||
<!-- clearable-->
|
||
<!-- placeholder="请输入单位名称"-->
|
||
<!-- v-model="searchParams.org_name"-->
|
||
<!-- style="width: 100%; min-width: 200px;"-->
|
||
<!-- />-->
|
||
<!-- </el-form-item>-->
|
||
|
||
<el-form-item prop="project_type" label="工程类型" style="margin-bottom: 0; width: 320px">
|
||
<el-select
|
||
clearable
|
||
placeholder="选择工程类型"
|
||
v-model="searchParams.project_type"
|
||
style="width: 100%; min-width: 200px;"
|
||
>
|
||
<el-option
|
||
v-for="item in projectTypeList"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<!-- 按钮区域 -->
|
||
<div style="display: flex; gap: 10px; margin-left: auto;">
|
||
<el-button @click="getProjectListData" size="mini" icon="el-icon-search" type="primary" class="primary-lease">
|
||
查询
|
||
</el-button>
|
||
<el-button @click="onReset" icon="el-icon-refresh" size="mini" class="primary-lease">重置</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<el-row>
|
||
|
||
</el-row>
|
||
</el-card>
|
||
</el-form>
|
||
|
||
<!-- 数据列表 -->
|
||
<el-card class="content-box">
|
||
<el-row style="margin-bottom: 16px; display: flex; justify-content: flex-end; align-items: center; gap: 10px;">
|
||
<el-button
|
||
size="mini"
|
||
@click="handleAdd"
|
||
type="primary"
|
||
class="primary-lease"
|
||
>
|
||
工程新建
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="danger"
|
||
class="primary-lease"
|
||
@click="handleBatchDelete"
|
||
:disabled="selectedRows.length === 0"
|
||
>
|
||
批量删除
|
||
</el-button>
|
||
</el-row>
|
||
|
||
|
||
<div class="table-container">
|
||
<el-table
|
||
:data="projectList"
|
||
show-overflow-tooltip
|
||
border stripe height="100%"
|
||
@selection-change="handleSelectionChange"
|
||
>
|
||
<!--复选列-->
|
||
<el-table-column type="selection" width="55" align="center"/>
|
||
|
||
<el-table-column align="center" label="序号" type="index" width="80"/>
|
||
|
||
<el-table-column align="center" prop="pro_name" label="工程名称"/>
|
||
|
||
<el-table-column align="center" label="工程编号">
|
||
<template slot-scope="scope">
|
||
<a
|
||
style="cursor: pointer; color: #00a288; text-decoration: underline"
|
||
@click="handleToDetails(scope.row.id)"
|
||
>
|
||
{{ scope.row.pro_code }}
|
||
</a>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="center" prop="dict_label" label="工程类型"/>
|
||
<el-table-column align="center" prop="voltage" label="电压等级"/>
|
||
<el-table-column align="center" prop="scale" label="规模"/>
|
||
<el-table-column align="center" prop="province" label="所在省"/>
|
||
<el-table-column align="center" prop="city" label="所在市"/>
|
||
<el-table-column align="center" prop="county" label="所在区/县"/>
|
||
|
||
<el-table-column align="center" prop="mechanize_rate" label="机械化率"/>
|
||
<el-table-column align="center" label="操作" :width="220">
|
||
<template slot-scope="scope">
|
||
|
||
|
||
|
||
<!-- 查看详情按钮(复用编辑按钮样式,仅改文字和方法) -->
|
||
<!-- <el-button-->
|
||
<!-- size="small"-->
|
||
<!-- type="info"-->
|
||
<!-- class="primary-lease"-->
|
||
<!-- @click="handleViewDetails(scope.row)"-->
|
||
<!-- >-->
|
||
<!-- 查看-->
|
||
<!-- </el-button>-->
|
||
|
||
|
||
|
||
<!-- 编辑按钮:移除 v-if 条件,直接显示 -->
|
||
<el-button
|
||
size="small"
|
||
type="primary"
|
||
class="primary-lease"
|
||
@click="handleEdit(scope.row)"
|
||
>
|
||
编辑
|
||
</el-button>
|
||
<!-- 删除按钮:移除 v-if 条件,直接显示 -->
|
||
<el-popconfirm
|
||
width="220"
|
||
icon="el-icon-info"
|
||
icon-color="#626AEF"
|
||
title="确定删除该项工程吗?"
|
||
@confirm="handleDelete(scope.row.id)"
|
||
>
|
||
<template slot="reference">
|
||
<el-button size="small" type="danger" class="primary-lease" style="margin-left: 8px;">
|
||
删除
|
||
</el-button>
|
||
</template>
|
||
</el-popconfirm>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
<!-- 分页组件 -->
|
||
<div class="pagination-wrapper">
|
||
<el-pagination
|
||
background
|
||
layout="total,sizes,prev, pager, next"
|
||
:total="total"
|
||
:page-size="searchParams.pageSize"
|
||
:current-page="searchParams.pageNum"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
/>
|
||
</div>
|
||
</el-card>
|
||
|
||
<!-- 新增/编辑对话框 -->
|
||
<el-dialog
|
||
width="1000px"
|
||
@close="handleDialogClose"
|
||
destroy-on-close
|
||
:title="dialogTitle"
|
||
:visible.sync="addOrEditDialogVisible"
|
||
custom-class="simple-dialog"
|
||
>
|
||
<el-form
|
||
label-width="100px"
|
||
label-position="right"
|
||
ref="addOrEditFormRef"
|
||
:model="addOrEditForm"
|
||
:rules="addOrEditFormRules"
|
||
class="simple-form"
|
||
label-class="el-form-item__label"
|
||
>
|
||
<el-row :gutter="20">
|
||
<el-col :span="24">
|
||
<el-row :gutter="15">
|
||
<el-col :span="12">
|
||
<el-form-item label="工程名称" prop="pro_name">
|
||
<el-input
|
||
v-model="addOrEditForm.pro_name"
|
||
placeholder="请输入工程名称"
|
||
style="width: 100%"
|
||
maxlength="50"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="工程编号" prop="pro_code">
|
||
<el-input
|
||
v-model="addOrEditForm.pro_code"
|
||
placeholder="请输入工程编号"
|
||
style="width: 100%"
|
||
maxlength="30"
|
||
show-word-limit
|
||
:disabled="!isAdd || isView"
|
||
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
|
||
<el-row :gutter="15">
|
||
<el-col :span="12">
|
||
<el-form-item label="电压等级" prop="voltage">
|
||
<el-input
|
||
v-model="addOrEditForm.voltage"
|
||
placeholder="请输入电压等级(如:500)"
|
||
style="width: 100%"
|
||
maxlength="10"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="规模" prop="scale">
|
||
<el-input
|
||
v-model="addOrEditForm.scale"
|
||
placeholder="请输入规模"
|
||
style="width: 100%"
|
||
maxlength="50"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
|
||
<el-col :span="12">
|
||
<el-form-item label="工程类型" prop="project_type"> <!-- 注意prop要与表单字段对齐 -->
|
||
<el-select
|
||
clearable
|
||
style="width: 100%"
|
||
placeholder="请选择工程类型"
|
||
v-model="addOrEditForm.project_type"
|
||
:disabled="isView"
|
||
>
|
||
<el-option
|
||
v-for="item in projectTypeList"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
|
||
<el-col :span="12">
|
||
<el-form-item label="建管单位" prop="org_name">
|
||
<el-input
|
||
v-model="addOrEditForm.org_name"
|
||
placeholder="请输入单位"
|
||
style="width: 100%"
|
||
maxlength="50"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
|
||
|
||
<el-col :span="12">
|
||
<el-form-item label="机械化率" prop="mechanize_rate">
|
||
<el-input
|
||
v-model="addOrEditForm.mechanize_rate"
|
||
placeholder="请输入机械化率"
|
||
style="width: 100%"
|
||
maxlength="50"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
|
||
|
||
<el-row :gutter="15">
|
||
<el-col :span="12">
|
||
<el-form-item label="开工时间" prop="start_time">
|
||
<el-date-picker
|
||
type="date"
|
||
placeholder="选择开工时间"
|
||
v-model="addOrEditForm.start_time"
|
||
value-format="yyyy-MM-dd"
|
||
style="width: 100%"
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="投产时间" prop="put_time">
|
||
<el-date-picker
|
||
type="date"
|
||
placeholder="选择投产时间"
|
||
v-model="addOrEditForm.put_time"
|
||
value-format="yyyy-MM-dd"
|
||
style="width: 100%"
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="15">
|
||
<el-col :span="8">
|
||
<el-form-item label="所在省" prop="province">
|
||
<el-select
|
||
clearable
|
||
style="width: 100%"
|
||
placeholder="请选择所在省"
|
||
v-model="addOrEditForm.province"
|
||
@change="loadCities"
|
||
>
|
||
<el-option
|
||
v-for="item in provinceOptions"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="所在市" prop="city">
|
||
<el-select
|
||
clearable
|
||
style="width: 100%"
|
||
placeholder="请选择所在市"
|
||
v-model="addOrEditForm.city"
|
||
@change="loadDistricts"
|
||
:disabled="!addOrEditForm.province"
|
||
>
|
||
<el-option
|
||
v-for="item in cityOptions"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="所在区/县" prop="county">
|
||
<el-select
|
||
clearable
|
||
style="width: 100%"
|
||
placeholder="请选择所在区/县"
|
||
v-model="addOrEditForm.county"
|
||
:disabled="!addOrEditForm.city"
|
||
>
|
||
<el-option
|
||
v-for="item in districtOptions"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row>
|
||
<el-col :span="24">
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input
|
||
type="textarea"
|
||
v-model="addOrEditForm.remark"
|
||
placeholder="请输入备注内容"
|
||
:rows="3"
|
||
style="width: 100%"
|
||
maxlength="100"
|
||
show-word-limit
|
||
:disabled="isView"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button @click="addOrEditDialogVisible = false" class="cancel-btn">取消</el-button>
|
||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading" class="confirm-btn" v-if="!isView">
|
||
<span v-if="!submitLoading">{{ isAdd ? '新增' : '保存' }}</span>
|
||
<span v-else>提交中...</span>
|
||
</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
listProject,
|
||
getProject,
|
||
addProject,
|
||
updateProject,
|
||
delProject,
|
||
getProjectTypeList,
|
||
delProjectBatch // 新增:导入批量删除API
|
||
} from '@/api/system/project'
|
||
import { Message } from 'element-ui'
|
||
import { getProvinces, getCities, getCounties } from '@/api/system/region'
|
||
|
||
export default {
|
||
name: 'ProjectManagement',
|
||
data() {
|
||
return {
|
||
total: 0,
|
||
projectList: [],
|
||
selectedRows: [], // 存储选中的表格行
|
||
provinceOptions: [], // 省份下拉选项
|
||
cityOptions: [], // 城市下拉选项
|
||
districtOptions: [], // 区县下拉选项
|
||
dialogTitle: '新增工程',
|
||
addOrEditDialogVisible: false,
|
||
submitLoading: false,
|
||
isAdd: true,
|
||
isView: false,
|
||
|
||
// 搜索参数
|
||
searchParams: {
|
||
pro_name: '',
|
||
pro_code: '',
|
||
project_type: '',
|
||
org_name: '',
|
||
dict_value:'',
|
||
pageSize: 10,
|
||
pageNum: 1
|
||
},
|
||
|
||
// 表单数据
|
||
addOrEditForm: {
|
||
id: '',
|
||
pro_name: '',
|
||
pro_code: '',
|
||
project_type: '',
|
||
org_name: '',
|
||
contractUnit: '',
|
||
mechanize_rate: '',
|
||
remark: '',
|
||
voltage: '',
|
||
scale: '',
|
||
province: '',
|
||
city: '',
|
||
county: '',
|
||
start_time: '',
|
||
put_time: '',
|
||
},
|
||
|
||
projectTypeList: [],
|
||
|
||
// 表单验证规则
|
||
addOrEditFormRules: {
|
||
// 以下字段保持必填
|
||
pro_name: [
|
||
{ required: true, message: '请输入工程名称', trigger: 'blur' }
|
||
],
|
||
pro_code: [
|
||
{ required: true, message: '请输入工程编号', trigger: 'blur' }
|
||
],
|
||
voltage: [
|
||
{ required: true, message: '请输入电压等级', trigger: 'blur' }
|
||
],
|
||
scale: [
|
||
{ required: true, message: '请输入规模', trigger: 'blur' }
|
||
],
|
||
project_type: [
|
||
{ required: true, message: '请选择工程类型', trigger: 'change' }
|
||
],
|
||
province: [
|
||
{ required: true, message: '请选择所在省', trigger: 'blur' }
|
||
],
|
||
city: [
|
||
{ required: true, message: '请选择所在市', trigger: 'blur' }
|
||
],
|
||
county: [
|
||
{ required: true, message: '请选择所在区/县', trigger: 'blur' }
|
||
],
|
||
|
||
start_time: [
|
||
|
||
{ message: '请选择开工时间', trigger: 'change' }
|
||
],
|
||
put_time: [
|
||
{ message: '请选择投产时间', trigger: 'change' },
|
||
{ validator: this.validateTimeDifference, trigger: 'change' }
|
||
],
|
||
mechanize_rate: [
|
||
|
||
{
|
||
pattern: /^(100(\.0{1,2})?|0(\.\d{1,2})?|[1-9]\d{0,1}(\.\d{1,2})?)$/,
|
||
message: '请输入 0 ~ 100 之间的有效数字,且不能以 0 开头(如 01、010)',
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
org_name: [
|
||
// 非必填,仅保留长度限制(可选)
|
||
{ max: 50, message: '单位名称不能超过50个字符', trigger: 'blur' }
|
||
],
|
||
remark: [
|
||
{ max: 100, message: '备注不能超过100个字符', trigger: 'blur' }
|
||
],
|
||
contractUnit: [] // 完全非必填,留空数组
|
||
}
|
||
}
|
||
},
|
||
|
||
mounted() {
|
||
this.loadProvinces() // 页面加载时加载省份
|
||
this.getProjectListData()
|
||
this.loadProjectTypes()
|
||
},
|
||
|
||
methods: {
|
||
|
||
// 自定义校验:投产时间必须晚于开工时间
|
||
validateTimeDifference(rule, value, callback) {
|
||
const startTime = this.addOrEditForm.start_time; // 开工时间
|
||
const endTime = value; // 投产时间(当前校验字段的值)
|
||
|
||
// 若未选择投产时间,直接通过(非必填)
|
||
if (!endTime) return callback();
|
||
|
||
// 若已选择开工时间,校验时间差
|
||
if (startTime) {
|
||
const startDate = new Date(startTime);
|
||
const endDate = new Date(endTime);
|
||
// 若投产时间早于或等于开工时间,提示错误
|
||
if (endDate <= startDate) {
|
||
return callback(new Error('投产时间必须晚于开工时间'));
|
||
}
|
||
}
|
||
|
||
// 校验通过
|
||
callback();
|
||
},
|
||
|
||
async loadProvinces() {
|
||
try {
|
||
const res = await getProvinces()
|
||
if (res.code === 200) {
|
||
// 关键转换:将 areaCode → value,name → label
|
||
this.provinceOptions = res.data.map(item => ({
|
||
value: item.areaCode, // 下拉框的选项值(存储用)
|
||
label: item.short_name // 下拉框的显示文本(用户看)
|
||
}))
|
||
} else {
|
||
Message.error('加载省份失败:' + (res.message || '未知错误'))
|
||
}
|
||
} catch (error) {
|
||
console.error('省份加载异常:', error)
|
||
Message.error('网络异常,无法加载省份数据')
|
||
}
|
||
},
|
||
|
||
// 加载城市
|
||
async loadCities(provinceAreaCode) {
|
||
console.log('loadCities param:', provinceAreaCode)
|
||
|
||
// 关键改动:当省份改变时,清空城市和区县的选项及表单值
|
||
// 即使 provinceAreaCode 为空(例如用户清空了省份选择),也执行清空操作
|
||
this.cityOptions = [];
|
||
this.districtOptions = [];
|
||
this.addOrEditForm.city = '';
|
||
this.addOrEditForm.county = '';
|
||
|
||
// 如果没有传入有效的省份编码,则直接返回
|
||
if (!provinceAreaCode || !/^\d{6,12}$/.test(provinceAreaCode)) {
|
||
console.error('❌ 传入了无效的 provinceAreaCode:', provinceAreaCode);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await getCities(provinceAreaCode)
|
||
if (res.code === 200) {
|
||
this.cityOptions = res.data.map(item => ({
|
||
value: item.areaCode,
|
||
label: item.short_name
|
||
}))
|
||
} else {
|
||
Message.error('加载城市失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('城市加载异常:', error)
|
||
Message.error('无法加载城市数据')
|
||
}
|
||
},
|
||
|
||
// 加载区县
|
||
async loadDistricts(cityAreaCode) {
|
||
console.log('loadDistricts param:', cityAreaCode)
|
||
|
||
// 关键改动:当城市改变时,清空区县的选项及表单值
|
||
// 即使 cityAreaCode 为空,也执行清空操作
|
||
this.districtOptions = [];
|
||
this.addOrEditForm.county = '';
|
||
|
||
// 如果没有传入有效的城市编码,则直接返回
|
||
if (!cityAreaCode || !/^\d{6,12}$/.test(cityAreaCode)) {
|
||
console.error('❌ 传入了无效的 cityAreaCode:', cityAreaCode);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await getCounties(cityAreaCode)
|
||
if (res.code === 200) {
|
||
this.districtOptions = res.data.map(item => ({
|
||
value: item.areaCode,
|
||
label: item.name
|
||
}))
|
||
} else {
|
||
Message.error('加载区县失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('区县加载异常:', error)
|
||
Message.error('无法加载区县数据')
|
||
}
|
||
},
|
||
|
||
|
||
|
||
// 获取工程列表
|
||
async getProjectListData() {
|
||
try {
|
||
const res = await listProject(this.searchParams)
|
||
if (res.code === 200) {
|
||
this.projectList = res.data.rows || []
|
||
this.total = res.data.total || 0
|
||
} else {
|
||
Message.error(res.message || '获取工程列表失败')
|
||
}
|
||
} catch (error) {
|
||
Message.error('网络错误,获取工程列表失败')
|
||
}
|
||
},
|
||
|
||
// 加载工程类型
|
||
async loadProjectTypes() {
|
||
try {
|
||
const res = await getProjectTypeList()
|
||
if (res.code === 200) {
|
||
this.projectTypeList = res.data.map(item => ({
|
||
label: item.dict_label,
|
||
value: item.dict_value
|
||
}))
|
||
} else {
|
||
Message.error('获取工程类型失败:' + (res.message || ''))
|
||
}
|
||
} catch (error) {
|
||
Message.error('加载工程类型时发生网络错误')
|
||
}
|
||
},
|
||
|
||
// 重置搜索
|
||
onReset() {
|
||
this.searchParams = {
|
||
pro_name: '',
|
||
pro_code: '',
|
||
project_type: '',
|
||
org_name: '',
|
||
pageSize: this.searchParams.pageSize,
|
||
pageNum: 1
|
||
}
|
||
this.$refs.searchFormRef?.clearValidate()
|
||
this.getProjectListData()
|
||
},
|
||
|
||
// 表格选择变化
|
||
handleSelectionChange(selection) {
|
||
this.selectedRows = selection
|
||
},
|
||
|
||
// 详情页跳转
|
||
handleToDetails(id) {
|
||
this.$router.push({name: 'demand-details', query: {id}})
|
||
},
|
||
|
||
// 新增工程
|
||
handleAdd() {
|
||
this.isAdd = true
|
||
this.isView = false
|
||
this.dialogTitle = '新增工程'
|
||
this.addOrEditForm = {
|
||
id: '',
|
||
pro_name: '',
|
||
pro_code: '',
|
||
project_type: '',
|
||
org_name: '',
|
||
contractUnit: '',
|
||
remark: '',
|
||
voltage: '',
|
||
scale: '',
|
||
province: '',
|
||
city: '',
|
||
county: '',
|
||
start_time: '',
|
||
put_time: ''
|
||
}
|
||
this.$refs.addOrEditFormRef?.clearValidate()
|
||
this.addOrEditDialogVisible = true
|
||
},
|
||
|
||
// 查看详情
|
||
async handleViewDetails(row) {
|
||
this.isView = true
|
||
this.dialogTitle = '查看工程详情'
|
||
try {
|
||
const res = await getProject(row.id)
|
||
if (res.code === 200) {
|
||
this.addOrEditForm = {...res.data}
|
||
this.addOrEditDialogVisible = true
|
||
} else {
|
||
Message.error(res.message || '获取工程详情失败')
|
||
}
|
||
} catch (error) {
|
||
Message.error('网络错误,获取工程详情失败')
|
||
}
|
||
},
|
||
|
||
async handleEdit(row) {
|
||
this.isAdd = false;
|
||
this.isView = false;
|
||
this.dialogTitle = '编辑工程';
|
||
|
||
try {
|
||
// 1. 获取工程详情
|
||
const res = await getProject(row.id);
|
||
if (res.code !== 200) return this.$message.error('获取详情失败');
|
||
|
||
// 拿到原始数据
|
||
const projectData = res.data;
|
||
|
||
// ================== 核心修改开始 ==================
|
||
// 2. 处理机械化率的格式:去除百分号,并转换为数字
|
||
if (projectData.mechanize_rate && typeof projectData.mechanize_rate === 'string') {
|
||
// 使用 replace('%', '') 去掉百分号
|
||
// 使用 parseFloat() 将字符串转换为数字
|
||
projectData.mechanize_rate = parseFloat(projectData.mechanize_rate.replace('%', ''));
|
||
}
|
||
// ================== 核心修改结束 ==================
|
||
|
||
// 3. 确保省份列表已加载(含 areaCode 映射)
|
||
await this.loadProvinces();
|
||
|
||
// 4. 省份名称 -> 编码
|
||
const targetProvince = this.provinceOptions.find(item => item.label === projectData.province);
|
||
const provinceCode = targetProvince ? targetProvince.value : '';
|
||
if (!provinceCode) {
|
||
Message.warning(`未找到“${projectData.province}”对应的编码,请手动选择`);
|
||
this.addOrEditForm = { ...projectData }; // 这里也会使用处理后的数据
|
||
this.addOrEditDialogVisible = true;
|
||
return;
|
||
}
|
||
|
||
// 5. 用编码加载城市列表
|
||
await this.loadCities(provinceCode);
|
||
// 城市名称 -> 编码
|
||
const targetCity = this.cityOptions.find(item => item.label === projectData.city);
|
||
const cityCode = targetCity ? targetCity.value : '';
|
||
|
||
// 6. 用编码加载区县列表
|
||
await this.loadDistricts(cityCode);
|
||
// 区县名称 -> 编码
|
||
const targetCounty = this.districtOptions.find(item => item.label === projectData.county);
|
||
const countyCode = targetCounty ? targetCounty.value : '';
|
||
|
||
// 7. 表单赋值(此时 projectData.mechanize_rate 已经是数字 80 了)
|
||
this.addOrEditForm = {
|
||
...projectData,
|
||
province: provinceCode,
|
||
city: cityCode,
|
||
county: countyCode
|
||
};
|
||
|
||
this.addOrEditDialogVisible = true;
|
||
this.$nextTick(() => this.$refs.addOrEditFormRef?.clearValidate());
|
||
} catch (error) {
|
||
console.error('编辑失败:', error);
|
||
Message.error('网络错误,编辑失败');
|
||
}
|
||
},
|
||
|
||
|
||
// 提交表单
|
||
async handleSubmit() {
|
||
const valid = await this.$refs.addOrEditFormRef?.validate()
|
||
if (!valid) return
|
||
|
||
// 处理机械化率:添加%符号
|
||
if (this.addOrEditForm.mechanize_rate) {
|
||
this.addOrEditForm.mechanize_rate = `${this.addOrEditForm.mechanize_rate}%`
|
||
}
|
||
|
||
this.submitLoading = true
|
||
try {
|
||
let res = this.isAdd ? await addProject(this.addOrEditForm) : await updateProject(this.addOrEditForm)
|
||
if (res.code === 200) {
|
||
Message.success(this.isAdd ? '新增工程成功' : '编辑工程成功')
|
||
this.addOrEditDialogVisible = false
|
||
this.getProjectListData()
|
||
} else {
|
||
Message.error(res.message || (this.isAdd ? '新增工程失败' : '编辑工程失败'))
|
||
}
|
||
} catch (error) {
|
||
Message.error('网络错误,操作失败')
|
||
} finally {
|
||
this.submitLoading = false
|
||
}
|
||
},
|
||
|
||
// 删除工程
|
||
async handleDelete(id) {
|
||
try {
|
||
const res = await delProject(id)
|
||
if (res.code === 200) {
|
||
Message.success('删除工程成功')
|
||
this.getProjectListData()
|
||
} else {
|
||
Message.error(res.message || '删除工程失败')
|
||
}
|
||
} catch (error) {
|
||
Message.error('网络错误,删除工程失败')
|
||
}
|
||
},
|
||
|
||
// 批量删除 - 修复后的方法
|
||
async handleBatchDelete() {
|
||
if (this.selectedRows.length === 0) {
|
||
Message.warning('请选择要删除的工程')
|
||
return
|
||
}
|
||
|
||
try {
|
||
await this.$confirm(
|
||
`确定删除选中的 ${this.selectedRows.length} 个工程吗?`,
|
||
'提示',
|
||
{
|
||
type: 'warning',
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消'
|
||
}
|
||
)
|
||
|
||
const ids = this.selectedRows.map(row => row.id)
|
||
const res = await delProjectBatch(ids)
|
||
|
||
if (res.code === 200) {
|
||
Message.success(`成功删除 ${this.selectedRows.length} 个工程`)
|
||
this.getProjectListData()
|
||
this.selectedRows = [] // 清空选中状态
|
||
} else {
|
||
Message.error(res.message || '批量删除失败')
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
Message.error('网络错误,批量删除失败')
|
||
}
|
||
}
|
||
},
|
||
|
||
// 关闭对话框
|
||
handleDialogClose() {
|
||
this.isView = false
|
||
this.$refs.addOrEditFormRef?.clearValidate()
|
||
},
|
||
|
||
// 分页大小改变
|
||
handleSizeChange(val) {
|
||
this.searchParams.pageSize = val
|
||
this.getProjectListData()
|
||
},
|
||
|
||
// 当前页码改变
|
||
handleCurrentChange(val) {
|
||
this.searchParams.pageNum = val
|
||
this.getProjectListData()
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* 样式部分保持不变 */
|
||
::v-deep .upload-tip .el-form-item__label {
|
||
color: transparent;
|
||
}
|
||
|
||
.el-pagination {
|
||
justify-content: flex-end;
|
||
padding: 5px 0;
|
||
}
|
||
|
||
::v-deep .el-pagination.is-background .el-pager li.is-active {
|
||
background-color: #3cb4a6;
|
||
}
|
||
|
||
::v-deep .el-form--inline .el-form-item {
|
||
margin-right: 6px;
|
||
width: 95%;
|
||
}
|
||
|
||
.img-list {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.img-items {
|
||
width: 100px;
|
||
height: 100px;
|
||
margin-right: 8px;
|
||
position: relative;
|
||
|
||
img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.mask-img {
|
||
visibility: hidden;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: #000;
|
||
opacity: 0.5;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.delete-icon {
|
||
font-size: 20px;
|
||
cursor: pointer;
|
||
z-index: 9;
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
|
||
.img-items:hover .mask-img {
|
||
visibility: visible;
|
||
}
|
||
}
|
||
|
||
.app-container-content {
|
||
::v-deep .el-dialog {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
margin: 0 !important;
|
||
position: absolute !important;
|
||
top: 50% !important;
|
||
left: 50% !important;
|
||
transform: translate(-50%, -50%) !important;
|
||
max-height: 100vh !important;
|
||
|
||
.el-dialog__body {
|
||
flex: 1;
|
||
overflow-y: scroll !important;
|
||
padding: 20px 40px;
|
||
}
|
||
|
||
.dialog-content {
|
||
padding: 20px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.search-box {
|
||
margin-bottom: 20px;
|
||
border-radius: 8px;
|
||
padding: 0;
|
||
|
||
::v-deep .el-card__body {
|
||
padding: 20px !important;
|
||
}
|
||
}
|
||
|
||
.el-form-item--small.el-form-item {
|
||
margin-bottom: 0px;
|
||
}
|
||
|
||
.content-box {
|
||
border-radius: 8px;
|
||
height: calc(100vh - 210px);
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
|
||
::v-deep .el-card__body {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
height: 100% !important;
|
||
padding: 20px;
|
||
}
|
||
|
||
.el-row:first-child {
|
||
margin-bottom: 16px;
|
||
flex-shrink: 0;
|
||
|
||
.el-col {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
}
|
||
|
||
.table-container {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
margin-bottom: 0;
|
||
min-height: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.pagination-wrapper {
|
||
flex-shrink: 0;
|
||
padding-top: 6px;
|
||
margin-top: auto;
|
||
text-align: right;
|
||
|
||
::v-deep .pagination-container {
|
||
padding: 0px 20px !important;
|
||
margin-bottom: 30px;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-table {
|
||
&.el-table--striped .el-table__body {
|
||
tr.el-table__row--striped td {
|
||
background-color: #F6FBFA !important;
|
||
}
|
||
}
|
||
|
||
.el-table__header {
|
||
background: #E9F0EE;
|
||
|
||
th {
|
||
background: #E9F0EE !important;
|
||
color: #606266;
|
||
font-weight: 600;
|
||
height: 50px;
|
||
}
|
||
}
|
||
|
||
&.el-table--striped .el-table__body tr.el-table__row:hover > td.el-table__cell {
|
||
background-color: #CCF1E9 !important;
|
||
}
|
||
}
|
||
}
|
||
|
||
.dialog-table {
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
|
||
::v-deep .el-table {
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
|
||
&.el-table--striped .el-table__body {
|
||
tr.el-table__row--striped td {
|
||
background-color: #F6FBFA !important;
|
||
}
|
||
}
|
||
|
||
.el-table__header {
|
||
background: #E9F0EE;
|
||
|
||
th {
|
||
background: #E9F0EE !important;
|
||
color: #606266;
|
||
font-weight: 600;
|
||
height: 45px;
|
||
font-size: 14px;
|
||
border-bottom: 2px solid #e4e7ed;
|
||
}
|
||
}
|
||
|
||
.el-table__body {
|
||
tr {
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover {
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
td {
|
||
padding: 12px 8px;
|
||
font-size: 13px;
|
||
border-bottom: 1px solid #f0f2f5;
|
||
}
|
||
}
|
||
}
|
||
|
||
&.el-table--striped .el-table__body tr.el-table__row:hover > td.el-table__cell {
|
||
background-color: #CCF1E9 !important;
|
||
}
|
||
|
||
&::before {
|
||
display: none;
|
||
}
|
||
|
||
&::after {
|
||
display: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
.simple-dialog {
|
||
.el-dialog__header {
|
||
padding: 15px 20px;
|
||
border-bottom: 1px solid #eee;
|
||
|
||
.el-dialog__title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.el-dialog__body {
|
||
padding: 20px;
|
||
}
|
||
|
||
.el-dialog__footer {
|
||
padding: 10px 20px;
|
||
border-top: 1px solid #eee;
|
||
text-align: right;
|
||
}
|
||
}
|
||
|
||
.simple-form {
|
||
.el-form-item {
|
||
margin-bottom: 15px;
|
||
|
||
.el-form-item__label {
|
||
color: #333;
|
||
padding-right: 10px;
|
||
|
||
&::before {
|
||
content: '*';
|
||
color: #ff4d4f;
|
||
margin-right: 4px;
|
||
}
|
||
|
||
&.no-required::before {
|
||
content: '';
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.el-input, .el-select, .el-date-picker {
|
||
width: 100%;
|
||
}
|
||
|
||
.el-textarea {
|
||
width: 100%;
|
||
|
||
&:focus {
|
||
border-color: #1890ff;
|
||
}
|
||
}
|
||
}
|
||
|
||
.dialog-footer {
|
||
.cancel-btn {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.confirm-btn {
|
||
background-color: #1890ff;
|
||
border-color: #1890ff;
|
||
}
|
||
}
|
||
</style>
|