Files
IRS-ui-develop/src/views/config/projectReviewPolicy/index.vue
2025-12-28 19:55:42 +08:00

260 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-card shadow="never" class="mb-4 overflow-auto">
<template #header>
<div class="card-header">
<div class="flex items-center">
<el-button type="primary" icon="plus" @click="handleAddRow">
{{ $t('projectReviewPolicy.addRow') }}
</el-button>
</div>
</div>
</template>
<el-table
:data="state.dataList"
style="width: 100%"
v-loading="state.loading"
border
row-key="id"
>
<el-table-column type="index" :label="$t('projectReviewPolicy.index')" width="60" />
<el-table-column prop="projectType" label="投资类别">
<template #default="{ row, $index }">
<el-select
v-model="row.projectType"
:placeholder="$t('projectReviewPolicy.selectProjectType')"
@change="handleFieldChange($index)"
style="width: 100%"
>
<el-option
v-for="item in investmentCategoryOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :label="$t('projectReviewPolicy.finalReminderPeriod')">
<template #default="{ row, $index }">
<el-select
v-model="row.finalReminderPeriod"
@change="handleFieldChange($index)"
style="width: 100%"
>
<el-option
v-for="item in finalReminderPeriodOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :label="$t('projectReviewPolicy.advanceReminder')">
<template #default="{ row, $index }">
<el-select
v-model="row.advanceReminderPeriod"
@change="handleFieldChange($index)"
style="width: 100%"
>
<el-option
v-for="item in advanceReminderPeriodOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :label="$t('projectReviewPolicy.action')" width="120">
<template #default="{ row, $index }">
<el-button
text
size="small"
type="danger"
icon="delete"
@click="handleDeleteRow($index, row)"
>
{{ $t('common.delBtn') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-4 flex justify-end">
<el-button type="primary" @click="handleSaveAll" :loading="saving">
{{ $t('projectReviewPolicy.saveAll') }}
</el-button>
</div>
</el-card>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useMessage } from '/@/hooks/message';
import {
fetchProjectReviewPolicyPage,
addProjectReviewPolicy,
updateProjectReviewPolicy,
deleteProjectReviewPolicy
} from '/@/api/config/projectReviewPolicy';
import { debounce } from 'lodash';
import { investmentCategoryOptions } from '/@/hooks/enums';
const { t } = useI18n();
const message = useMessage();
// 定义项目类型选项
const projectTypeOptions = ref([
{ value: '1', label: t('projectReviewPolicy.infrastructure') },
{ value: '2', label: t('projectReviewPolicy.industrial') },
{ value: '3', label: t('projectReviewPolicy.civilEngineering') },
{ value: '4', label: t('projectReviewPolicy.other') }
]);
// 最后提醒期限选项 (1-9年)
const finalReminderPeriodOptions = ref([
{ value: 1, label: '1' + t('projectReviewPolicy.year') },
{ value: 2, label: '2' + t('projectReviewPolicy.year') },
{ value: 3, label: '3' + t('projectReviewPolicy.year') },
{ value: 4, label: '4' + t('projectReviewPolicy.year') },
{ value: 5, label: '5' + t('projectReviewPolicy.year') },
{ value: 6, label: '6' + t('projectReviewPolicy.year') },
{ value: 7, label: '7' + t('projectReviewPolicy.year') },
{ value: 8, label: '8' + t('projectReviewPolicy.year') },
{ value: 9, label: '9' + t('projectReviewPolicy.year') }
]);
// 提前提醒选项 (无、提前3、15、30、60、90天)
const advanceReminderPeriodOptions = ref([
{ value: 0, label: t('projectReviewPolicy.none') },
{ value: 3, label: t('projectReviewPolicy.advance') + '3' + t('projectReviewPolicy.day') },
{ value: 15, label: t('projectReviewPolicy.advance') + '15' + t('projectReviewPolicy.day') },
{ value: 30, label: t('projectReviewPolicy.advance') + '30' + t('projectReviewPolicy.day') },
{ value: 60, label: t('projectReviewPolicy.advance') + '60' + t('projectReviewPolicy.day') },
{ value: 90, label: t('projectReviewPolicy.advance') + '90' + t('projectReviewPolicy.day') }
]);
// 表格状态
const state = reactive({
dataList: [] as any[],
loading: false,
});
// 保存状态
const saving = ref(false);
// 防抖保存函数
const debouncedSave = debounce(async (row, type) => {
try {
if (type === 'add') {
const res = await addProjectReviewPolicy(row);
// 更新ID
row.id = res.data?.id || row.id;
message.success(t('projectReviewPolicy.saveSuccess'));
} else if (type === 'update') {
await updateProjectReviewPolicy(row);
message.success(t('projectReviewPolicy.updateSuccess'));
}
} catch (err: any) {
message.error(err?.msg || err?.message || t('common.operateFail'));
}
}, 800);
// 字段变更处理
const handleFieldChange = (index: number) => {
const row = state.dataList[index];
if (!row) return;
// 如果是新行且没有ID则添加
if (!row.id || row.id === '') {
debouncedSave(row, 'add');
} else {
// 否则更新现有行
debouncedSave(row, 'update');
}
};
// 添加行
const handleAddRow = () => {
state.dataList.push({
id: '',
projectType: '',
finalReminderPeriod: 1,
finalReminderUnit: '年',
advanceReminderPeriod: 30,
advanceReminderUnit: '天',
createTime: ''
});
};
// 删除行
const handleDeleteRow = async (index: number, row: any) => {
try {
if (row.id) {
// 如果有ID从服务器删除
await deleteProjectReviewPolicy(row.id);
}
// 从前端列表中移除
state.dataList.splice(index, 1);
message.success(t('projectReviewPolicy.deleteSuccess'));
} catch (err: any) {
message.error(err?.msg || err?.message || t('common.operateFail'));
}
};
// 保存所有数据
const handleSaveAll = async () => {
saving.value = true;
try {
// 取消所有待处理的防抖调用
debouncedSave.cancel();
// 处理所有未保存的数据
const promises = state.dataList.map(item => {
if (!item.id || item.id === '') {
return addProjectReviewPolicy(item);
} else {
return updateProjectReviewPolicy(item);
}
});
await Promise.all(promises);
message.success(t('projectReviewPolicy.saveAllSuccess'));
await getDataList();
} catch (err: any) {
message.error(err?.msg || err?.message || t('common.operateFail'));
} finally {
saving.value = false;
}
};
// 获取数据列表
const getDataList = async () => {
try {
state.loading = true;
const res = await fetchProjectReviewPolicyPage({ page: 1, size: 1000 });
state.dataList = res.data?.records || [];
} catch (err: any) {
message.error(err?.msg || err?.message || t('common.operateFail'));
} finally {
state.loading = false;
}
};
// 初始化加载数据
onMounted(() => {
getDataList();
});
</script>