1、新增结算模块

2、调整业务模块
3、调整客商模块
This commit is contained in:
2026-08-20 06:33:01 +08:00
parent 4199255186
commit fd5b1484e6
59 changed files with 11745 additions and 1104 deletions
+313
View File
@@ -0,0 +1,313 @@
<template>
<basic-container class="insurance-ocr-template-page">
<div class="insurance-ocr-template-page__toolbar">
<el-button
v-if="hasPermission('insurance_ocr_template_add')"
type="primary"
icon="el-icon-plus"
@click="openDialog()"
>
新增
</el-button>
<el-button
v-if="hasPermission('insurance_ocr_template_delete')"
type="danger"
plain
icon="el-icon-delete"
:disabled="!selectionList.length"
@click="handleRemove(selectionIds)"
>
批量删除
</el-button>
<div class="insurance-ocr-template-page__search">
<el-input
v-model="query.name"
clearable
maxlength="100"
placeholder="模板名称"
@keyup.enter="search"
@clear="search"
/>
<el-button type="primary" icon="el-icon-search" @click="search">查询</el-button>
<el-button icon="el-icon-refresh" @click="resetSearch">重置</el-button>
</div>
</div>
<el-table
v-loading="loading"
:data="data"
border
@selection-change="selectionChange"
>
<el-table-column type="selection" width="48" />
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column prop="name" label="模板名称" min-width="220" show-overflow-tooltip />
<el-table-column label="已配置字段" min-width="150">
<template #default="{ row }">{{ getMappingCount(row.mappingConfig) }}</template>
</el-table-column>
<el-table-column prop="updateUserName" label="更新人" min-width="120" />
<el-table-column prop="updateTime" label="更新时间" min-width="180" />
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-link
v-if="hasPermission('insurance_ocr_template_view')"
type="primary"
@click="openDialog(row, true)"
>
查看
</el-link>
<el-link
v-if="hasPermission('insurance_ocr_template_edit')"
type="primary"
@click="openDialog(row)"
>
编辑
</el-link>
<el-link
v-if="hasPermission('insurance_ocr_template_delete')"
type="danger"
@click="handleRemove(row.id)"
>
删除
</el-link>
</template>
</el-table-column>
</el-table>
<empty-pagination
:page="page"
@size-change="sizeChange"
@current-change="currentChange"
@load="onLoad"
/>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="860px"
append-to-body
destroy-on-close
@closed="resetForm"
>
<el-form ref="templateForm" :model="form" :rules="rules" label-width="100px" :disabled="readonly">
<el-form-item label="模板名称" prop="name">
<el-input v-model="form.name" maxlength="100" show-word-limit />
</el-form-item>
<el-form-item label="字段映射" required>
<el-table :data="mappingRows" border class="insurance-ocr-template-page__mapping-table">
<el-table-column prop="key" label="键名" min-width="240" />
<el-table-column label="自定义映射值" min-width="500">
<template #default="{ row }">
<el-input
v-model="row.value"
maxlength="100"
show-word-limit
placeholder="请输入保险单据中的对应字段名称"
/>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="!readonly" type="primary" :loading="submitLoading" @click="handleSubmit">
确定
</el-button>
</template>
</el-dialog>
</basic-container>
</template>
<script>
import { mapGetters } from 'vuex';
import { getDetail, getList, remove, submit } from '@/api/base/insurance-ocr-template';
const insuranceFieldKeys = [
'保险类型',
'保单号',
'开始日期',
'结束日期',
'保额',
'保费',
'发票号',
'开票日期',
'备注',
];
const createMappingRows = mappingConfig => {
let valueMap = {};
try {
const mappings = JSON.parse(mappingConfig || '[]');
if (Array.isArray(mappings)) {
valueMap = mappings.reduce((result, item) => {
if (insuranceFieldKeys.includes(item?.key)) result[item.key] = item.value || '';
return result;
}, {});
}
} catch (error) {
valueMap = {};
}
return insuranceFieldKeys.map(key => ({ key, value: valueMap[key] || '' }));
};
export default {
data() {
return {
loading: false,
submitLoading: false,
dialogVisible: false,
readonly: false,
data: [],
selectionList: [],
query: { name: '' },
form: { id: '', name: '' },
mappingRows: createMappingRows(),
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
currentPage: 1,
total: 0,
},
rules: {
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
},
};
},
computed: {
...mapGetters(['permission', 'userInfo']),
isAdmin() {
return String(this.userInfo.authority || '').includes('admin');
},
selectionIds() {
return this.selectionList.map(item => item.id).join(',');
},
dialogTitle() {
if (this.readonly) return '查看保险OCR识别模板';
return this.form.id ? '编辑保险OCR识别模板' : '新增保险OCR识别模板';
},
},
methods: {
hasPermission(code) {
return this.isAdmin || this.permission?.[code] === true;
},
onLoad() {
this.loading = true;
getList(this.page.currentPage, this.page.pageSize, this.query)
.then(res => {
const pageData = res.data.data || {};
this.data = pageData.records || [];
this.page.total = pageData.total || 0;
this.selectionList = [];
})
.finally(() => {
this.loading = false;
});
},
search() {
this.page.currentPage = 1;
this.onLoad();
},
resetSearch() {
this.query.name = '';
this.search();
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
this.onLoad();
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
this.page.currentPage = 1;
this.onLoad();
},
selectionChange(selectionList) {
this.selectionList = selectionList;
},
openDialog(row, readonly = false) {
this.readonly = readonly;
if (!row?.id) {
this.dialogVisible = true;
return;
}
getDetail(row.id).then(res => {
const detail = res.data.data || {};
this.form = { id: detail.id, name: detail.name || '' };
this.mappingRows = createMappingRows(detail.mappingConfig);
this.dialogVisible = true;
});
},
resetForm() {
this.form = { id: '', name: '' };
this.mappingRows = createMappingRows();
this.readonly = false;
this.submitLoading = false;
this.$refs.templateForm?.clearValidate();
},
handleSubmit() {
const hasMappingValue = this.mappingRows.some(item => String(item.value || '').trim());
if (!hasMappingValue) {
this.$message.warning('请至少填写一个字段映射值');
return;
}
this.$refs.templateForm.validate(valid => {
if (!valid) return;
this.submitLoading = true;
submit({
id: this.form.id || undefined,
name: String(this.form.name || '').trim(),
mappingConfig: JSON.stringify(
this.mappingRows.map(item => ({ key: item.key, value: String(item.value || '').trim() }))
),
})
.then(() => {
this.$message.success('操作成功');
this.dialogVisible = false;
this.onLoad();
})
.finally(() => {
this.submitLoading = false;
});
});
},
handleRemove(ids) {
this.$confirm('确定删除选中的保险OCR识别模板吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
remove(ids).then(() => {
this.$message.success('操作成功');
this.onLoad();
});
});
},
getMappingCount(mappingConfig) {
return createMappingRows(mappingConfig).filter(item => String(item.value || '').trim()).length;
},
},
};
</script>
<style lang="scss" scoped>
.insurance-ocr-template-page {
&__toolbar {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}
&__search {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
width: 380px;
}
&__mapping-table {
width: 100%;
}
}
</style>