bonus-ui/src/views/system/project/index.vue

1212 lines
34 KiB
Vue
Raw Normal View History

2025-11-14 18:04:39 +08:00
<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 → valuename → label
this.provinceOptions = res.data.map(item => ({
value: item.areaCode, // 下拉框的选项值(存储用)
2025-11-18 10:02:29 +08:00
label: item.short_name // 下拉框的显示文本(用户看)
2025-11-14 18:04:39 +08:00
}))
} 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,
2025-11-18 10:02:29 +08:00
label: item.short_name
2025-11-14 18:04:39 +08:00
}))
} 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>