代码修改

This commit is contained in:
沈鸿 2025-07-01 10:57:25 +08:00
parent f52947abab
commit 488748c992

View File

@ -0,0 +1,621 @@
<template>
<div class="custom-page">
<!-- 关键词搜索 -->
<el-form :inline="true" :model="searchForm" class="search-bar">
<el-form-item label="关键词">
<el-input v-model="searchForm.name" placeholder="请输入关键词" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<avue-crud ref="crudRef" v-model:page="pageData" :data="crudData" :option="crudOptions" :table-loading="loading">
<template v-if="activeTab === '0'" #menu-left>
<el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
</template>
<template #menu="scope">
<custom-table-operate :actions="getActions(scope.row)" :data="scope" />
</template>
</avue-crud>
<!-- 新增弹窗 -->
<el-dialog :key="dialogTitle" v-model="dialogVisible" :title="dialogTitle" width="60%" align-center :draggable="true">
<el-form :model="formData" label-width="120px" class="custom-form" :disabled="isReadonly">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="证件类型" prop="idType">
<el-select v-model="formData.idType" placeholder="请选择证件类型" disabled>
<el-option label="身份证" value="101" />
<el-option label="护照" value="2" />
<el-option label="港澳身份证" value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="证件号码" prop="idCard">
<el-input v-model="formData.idCard" placeholder="请输入证件号码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1"></el-radio>
<el-radio value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系方式" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入联系方式" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="居住地行政区划" prop="addressArr">
<area-select v-model="formData.addressArr" :label="null" />
<!-- <el-input v-model="formData.detailAddress" placeholder="请选择居住地行政区划" /> -->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="具体地址" prop="detailAddress">
<el-input v-model="formData.detailAddress" placeholder="请输入具体地址" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="种植面积" prop="area">
<el-input v-model="formData.area" placeholder="请输入种植面积" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="种植作物" prop="planCrop">
<!-- <el-select v-model="formData.planCrop" placeholder="种植作物" style="width: 380px" :clearable="true">
<el-option v-for="item in cropsOptions" :key="item.id" :label="item.cropsName" :value="item.id" />
</el-select> -->
<url-select
v-model="formData.planCrop"
url="/land-resource/crops/page"
:params="{ status: '0' }"
label-key="cropsName"
value-key="id"
placeholder="请选择种植作物"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="!isReadonly" type="primary" @click="handleSave">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, reactive, onMounted, watch, nextTick } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { CRUD_OPTIONS } from '@/config';
import { fetchFarmerList, fetchFarmerById, saveFarmerList, editFarmer, approveFarmer, deleteFarmers } from '@/apis/businessEntity';
import { pageCropsList } from '@/apis/landResourceManagement/cropsManagement/index.js';
// ---------------------------------------------------------------------
// 1.
// 'superadmin''auditor''submitter'
// ---------------------------------------------------------------------
const role = ref('superadmin'); // 'superadmin' / 'auditor' / 'submitter'
//
const isSuperAdmin = computed(() => role.value === 'superadmin');
const isAuditor = computed(() => role.value === 'auditor');
// ---------------------------------------------------------------------
// 2. Tab
// ---------------------------------------------------------------------
const activeTab = ref('2');
const dialogTitle = ref('新增');
const isReadonly = ref(false);
//
const searchForm = ref({
name: '',
idCard: '',
phone: '',
status: '',
userId: '',
});
const loading = ref(false);
const crudRef = ref();
//
const pageData = ref({
currentPage: 1,
pageSize: 10,
total: 0,
});
//
const crudData = ref([]);
//
const dialogVisible = ref(false);
//
const defaultFormData = {
name: '',
idType: '101',
idCard: '',
sex: '1',
age: '',
phone: '',
provinceCode: '', //
cityCode: '', //
countyCode: '', //
townCode: '', //
villageCode: '', //
address: '',
addressArr: [],
detailAddress: '',
area: '',
planCrop: '',
reason: '',
};
// 使
const formData = ref({ ...defaultFormData });
//
const resetForm = () => {
formData.value = { ...defaultFormData };
};
// ==============================
// CRUD
// ==============================
const crudOptions = reactive({
...CRUD_OPTIONS,
header: false,
column: [
{ label: '主体编码', prop: 'id' },
{ label: '姓名', prop: 'name' },
{
label: '证件类型',
prop: 'idType',
formatter: (row, column, cellValue) => {
return cellValue === '101' ? '身份证' : '其它';
},
},
{ label: '证件号码', prop: 'idCard' },
{
label: '性别',
prop: 'sex',
formatter: (row, column, cellValue) => {
return cellValue === '1' ? '男' : '女';
},
},
{ label: '年龄', prop: 'age' },
{ label: '联系方式', prop: 'phone' },
{ label: '所属行政区划', prop: 'address' },
{ label: '种植作物', prop: 'planCropName' },
{ label: '数据来源', prop: 'dataSource' },
{ label: '创建时间', prop: 'createTime' },
],
});
// ---------------------------------------------------------------------
// 3. API/
// ---------------------------------------------------------------------
async function getData() {
loading.value = true;
try {
const params = {
...searchForm.value,
status: activeTab.value,
current: pageData.value.currentPage,
size: pageData.value.pageSize,
};
const response = await fetchFarmerList(params);
if (response.code === 200 && response.data) {
crudData.value = response.data.records;
console.log('获取数据成功:', crudData.value);
pageData.value = {
currentPage: response.data.current,
pageSize: response.data.size,
total: response.data.total,
};
} else {
ElMessage.error(response.msg || '获取数据失败');
}
} catch (error) {
ElMessage.error('获取数据失败,请稍后重试');
} finally {
loading.value = false;
}
}
//
const cropsOptions = ref([]);
//
const fetchCropsList = async () => {
try {
// pageCropsList
const res = await pageCropsList({ status: '0' });
if (res.code === 200) {
console.log('res :>> ', res.data.records);
cropsOptions.value = res.data.records;
console.log('object :>> ', cropsOptions.value);
}
} catch (error) {
console.error('获取种植作物列表失败:', error);
}
};
function handleSearch() {
getData();
}
function handleReset() {
searchForm.value.keyword = '';
handleSearch();
}
function handleTabChange(tab) {
handleSearch();
}
//
const handleAdd = () => {
isReadonly.value = false; //
resetForm();
dialogTitle.value = '新增';
dialogVisible.value = true;
};
// address
watch(
() => formData.value.addressArr,
(newValue) => {
if (newValue.length === 5) {
formData.value.provinceCode = newValue[0] || '';
formData.value.cityCode = newValue[1] || '';
formData.value.countyCode = newValue[2] || '';
formData.value.townCode = newValue[3] || '';
formData.value.villageCode = newValue[4] || '';
} else {
ElMessageBox.alert('行政区划数据错误');
}
}
);
// saveFarmerList
const handleSave = async () => {
try {
let response;
if (dialogTitle.value === '新增') {
console.log('新增formData.value.arr :>> ', formData.value.addressArr);
// saveFarmerList
response = await saveFarmerList(formData.value);
if (response.code === 200) {
ElMessage.success('新增成功');
}
} else if (dialogTitle.value === '编辑') {
// editFarmer
response = await editFarmer(formData.value);
if (response.code === 200) {
ElMessage.success('编辑成功');
}
}
if (response && response.code === 200) {
dialogVisible.value = false;
getData(); //
}
} catch (error) {
if (dialogTitle.value === '新增') {
ElMessage.error('新增失败,请稍后重试');
} else {
ElMessage.error('编辑失败,请稍后重试');
}
}
};
const getFarmerById = async (id) => {
try {
const response = await fetchFarmerById(id);
if (response.code === 200 && response.data) {
return response.data;
} else {
ElMessage.error(response.msg || '获取数据失败');
return null;
}
} catch (error) {
ElMessage.error('获取数据失败,请稍后重试');
return null;
}
};
//
async function handleView(row) {
dialogTitle.value = '查看';
isReadonly.value = true; //
const data = await getFarmerById(row.id);
if (data) {
const addressArr = [data.provinceCode, data.cityCode, data.countyCode, data.townCode, data.villageCode].filter(Boolean);
formData.value = {
...data,
addressArr: addressArr,
};
}
nextTick(() => {
dialogVisible.value = true;
});
}
// /
async function handleEdit(row) {
if (row.status === '2') {
try {
await ElMessageBox.confirm('编辑后数据将需要重新审核,是否继续?', '确认编辑', {
confirmButtonText: '继续编辑',
cancelButtonText: '取消',
type: 'warning',
});
} catch {
return;
}
}
const data = await getFarmerById(row.id);
if (data) {
const addressArr = [data.provinceCode, data.cityCode, data.countyCode, data.townCode, data.villageCode].filter(Boolean);
formData.value = {
...data,
addressArr: addressArr,
};
}
dialogTitle.value = '编辑';
isReadonly.value = false;
nextTick(() => {
dialogVisible.value = true;
});
}
//
function handleSubmit(row) {
ElMessageBox.confirm('确定提交审核吗?', '提交审核').then(() => {
const params = {
id: row.id,
status: '1',
reason: row.reason || '',
};
approveFarmer(params)
.then(() => {
row.rejectReason = ''; //
getData(); //
})
.catch(() => {
ElMessage.error('提交审核失败,请稍后重试');
});
});
}
//
function handleResubmit(row) {
ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => {
const params = {
id: row.id,
status: '1', //
reason: '重新提交审核',
};
approveFarmer(params)
.then(() => {
console.log(`ID=${row.id} 重新提交审核`);
row.status = '1';
row.rejectReason = '';
getData();
ElMessage.success('已重新提交,状态已变为"待审核"');
})
.catch((error) => {
console.error('重新提交失败:', error);
ElMessage.error(error.response?.data?.msg || '重新提交失败');
});
});
}
//
function handleWithdraw(row) {
ElMessageBox.confirm('确认撤销本次审核吗?', '撤销').then(() => {
const params = {
id: row.id,
status: '0', //
reason: '用户主动撤销',
};
approveFarmer(params)
.then(() => {
console.log(`ID=${row.id} 撤销审核`);
row.status = '0';
getData();
ElMessage.success('已撤销,状态已变为"待提交"');
})
.catch((error) => {
console.error('撤销失败:', error);
ElMessage.error(error.response?.data?.msg || '撤销失败');
});
});
}
//
function handleApprove(row) {
ElMessageBox.confirm('确认通过审核?', '审核通过').then(() => {
const params = {
id: row.id,
status: '2', //
reason: '审核通过',
};
approveFarmer(params)
.then(() => {
console.log(`ID=${row.id} 审核通过`);
row.status = '2';
getData();
ElMessage.success('审核已通过');
})
.catch((error) => {
console.error('审核通过操作失败:', error);
ElMessage.error(error.response?.data?.msg || '审核操作失败');
});
});
}
//
function handleReject(row) {
ElMessageBox.prompt('请输入驳回原因', '审核驳回', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/, //
inputErrorMessage: '驳回原因不能为空',
})
.then(({ value }) => {
const params = {
id: row.id,
status: '3', //
reason: value.trim(),
};
return approveFarmer(params).then(() => {
console.log(`ID=${row.id} 驳回,原因:${value.trim()}`);
row.status = '3';
row.rejectReason = value.trim();
getData();
ElMessage.success('已驳回');
});
})
.catch((error) => {
if (error !== 'cancel') {
console.error('驳回操作失败:', error);
ElMessage.error(error.response?.data?.msg || '驳回操作失败');
}
});
}
// /
function showRejectReason(row) {
ElMessageBox.alert(row.reason || '无驳回原因', '驳回原因');
}
async function handleDelete(row) {
try {
await ElMessageBox.confirm('确定删除该条记录?', '删除提示');
console.log(`删除 ID=${row.id}`);
await deleteFarmers(row.id); // ID
await getData();
ElMessage.success('已删除');
} catch (error) {
if (error !== 'cancel') {
ElMessage.error(`删除失败: ${error.message || '请稍后重试'}`);
}
}
}
//
const ACTION_MAP = {
view: { name: '查看', icon: 'view', handler: handleView },
edit: { name: '编辑', icon: 'edit', handler: handleEdit },
submit: { name: '提交审核', icon: 'submit', handler: handleSubmit },
delete: { type: 'danger', name: '删除', icon: 'delete', handler: handleDelete },
approve: { name: '通过', icon: 'approve', handler: handleApprove },
reject: { name: '驳回', icon: 'reject', handler: handleReject },
withdraw: { name: '撤销', icon: 'withdraw', handler: handleWithdraw },
resubmit: { name: '重新提交', icon: 'resubmit', handler: handleResubmit },
reason: { name: '驳回原因', icon: 'reason', handler: showRejectReason },
modify: { name: '修改', icon: 'edit', handler: handleEdit },
};
//
const ROLE_STATUS_ACTIONS = {
superadmin: {
0: ['view', 'edit', 'submit', 'delete'],
1: ['view', 'approve', 'reject', 'withdraw', 'delete'],
2: ['view', 'modify', 'delete'],
3: ['view', 'edit', 'reason', 'resubmit', 'delete'],
},
auditor: {
0: [],
1: ['view', 'approve', 'reject'],
2: ['view', 'delete'],
3: ['view', 'reason', 'delete'],
},
submitter: {
0: ['view', 'edit', 'submit', 'delete'],
1: ['view', 'withdraw', 'delete'],
2: ['view', 'modify', 'delete'],
3: ['view', 'edit', 'reason', 'resubmit', 'delete'],
},
};
//
function getActions(row) {
const currentRole = role.value;
const status = row.status;
const actionKeys = ROLE_STATUS_ACTIONS[currentRole]?.[status] || [];
return actionKeys.map((key) => {
const action = ACTION_MAP[key];
return {
...action,
event: () => action.handler(row),
};
});
}
// ---------------------------------------------------------------------
// 4. crudData
// ---------------------------------------------------------------------
onMounted(() => {
getData();
fetchCropsList(); //
});
</script>
<style scoped lang="scss">
// :deep(.avue-crud__header) {
// display: none;
// }
.custom-page {
padding: 20px;
height: calc(100vh - 150px);
overflow-y: auto;
.search-bar {
margin-bottom: 20px;
}
}
:deep(.el-dialog__body) {
padding: 20px;
height: calc(100vh - 300px);
overflow-y: auto;
}
.custom-form {
padding: 20px;
.el-form-item {
margin-bottom: 22px;
}
.el-input,
.el-select,
.el-cascader,
.el-date-picker {
width: 500px;
max-width: 100%; //
box-sizing: border-box; // padding/border
}
}
</style>