diff --git a/src/api/credit/creditMpCustomer/model/index.ts b/src/api/credit/creditMpCustomer/model/index.ts
index 915d366..ea95430 100644
--- a/src/api/credit/creditMpCustomer/model/index.ts
+++ b/src/api/credit/creditMpCustomer/model/index.ts
@@ -26,6 +26,8 @@ export interface CreditMpCustomer {
region?: string;
// 文件路径
files?: string;
+ // 步骤, 0未受理1已受理2材料提交3合同签订4执行回款5完结
+ step?: number;
// 是否有数据
hasData?: string;
// 备注
@@ -60,4 +62,5 @@ export interface CreditMpCustomer {
export interface CreditMpCustomerParam extends PageParam {
id?: number;
keywords?: string;
+ step?: number;
}
diff --git a/src/views/credit/creditMpCustomer/components/search.vue b/src/views/credit/creditMpCustomer/components/search.vue
index 148cae0..81f1d40 100644
--- a/src/views/credit/creditMpCustomer/components/search.vue
+++ b/src/views/credit/creditMpCustomer/components/search.vue
@@ -1,12 +1,12 @@
-
-
-
-
- 添加
-
+
+
+
+
+
+
@@ -32,6 +32,21 @@
@search="handleSearch"
@pressEnter="handleSearch"
/>
+
+
+ {{ item.text }}
+
+
@@ -66,8 +81,18 @@
}>();
const keywords = ref('');
+ const step = ref(undefined);
const selection = computed(() => props.selection || []);
+ const stepOptions = [
+ { value: 0, text: '未受理' },
+ { value: 1, text: '已受理' },
+ { value: 2, text: '材料提交' },
+ { value: 3, text: '合同签订' },
+ { value: 4, text: '执行回款' },
+ { value: 5, text: '完结' }
+ ];
+
// 新增
const add = () => {
emit('add');
@@ -75,7 +100,7 @@
// 搜索
const handleSearch = () => {
- emit('search', { keywords: keywords.value });
+ emit('search', { keywords: keywords.value || undefined, step: step.value });
};
// 导出
diff --git a/src/views/credit/creditMpCustomer/index.vue b/src/views/credit/creditMpCustomer/index.vue
index bd4055f..3540b0a 100644
--- a/src/views/credit/creditMpCustomer/index.vue
+++ b/src/views/credit/creditMpCustomer/index.vue
@@ -24,7 +24,7 @@
-
+
@@ -39,21 +39,36 @@
-
-
+
+
+
+
+ {{ file.name || `附件${index + 1}` }}
+
+
+ -
+
+
+ {{ getStepText(record.step) }}
+
+
显示
隐藏
-
修改
删除
-
@@ -95,6 +109,13 @@ import {
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
import {exportCreditData} from '../utils/export';
+type NormalizedFile = {
+ name?: string;
+ url: string;
+ thumbnail?: string;
+ isImage: boolean;
+};
+
// 表格实例
const tableRef = ref | null>(null);
@@ -110,6 +131,7 @@ const showMove = ref(false);
const loading = ref(true);
// 搜索关键词
const searchText = ref('');
+const searchStep = ref(undefined);
// 表格数据源
const datasource: DatasourceFunction = ({
@@ -122,6 +144,8 @@ const datasource: DatasourceFunction = ({
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
if (filters) {
(params as any).status = filters.status;
+ const stepFilter = (filters as any).step;
+ (params as any).step = Array.isArray(stepFilter) ? stepFilter[0] : stepFilter;
}
return pageCreditMpCustomer({
...params,
@@ -131,6 +155,107 @@ const datasource: DatasourceFunction = ({
});
};
+const stepOptions = [
+ { value: 0, text: '未受理', color: 'default' },
+ { value: 1, text: '已受理', color: 'blue' },
+ { value: 2, text: '材料提交', color: 'cyan' },
+ { value: 3, text: '合同签订', color: 'purple' },
+ { value: 4, text: '执行回款', color: 'orange' },
+ { value: 5, text: '完结', color: 'green' }
+] as const;
+
+const getStepText = (step: unknown) => {
+ const value = typeof step === 'string' ? Number(step) : (step as number | undefined);
+ const match = stepOptions.find((d) => d.value === value);
+ return match?.text ?? '-';
+};
+
+const getStepColor = (step: unknown) => {
+ const value = typeof step === 'string' ? Number(step) : (step as number | undefined);
+ const match = stepOptions.find((d) => d.value === value);
+ return match?.color ?? 'default';
+};
+
+const isImageUrl = (url: string) => {
+ const cleanUrl = url.split('?')[0] ?? '';
+ return /\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(cleanUrl);
+};
+
+const guessNameFromUrl = (url: string) => {
+ const cleanUrl = (url.split('?')[0] ?? '').trim();
+ const last = cleanUrl.split('/').pop() || '';
+ try {
+ return decodeURIComponent(last) || url;
+ } catch {
+ return last || url;
+ }
+};
+
+const tryParseJson = (value: string) => {
+ try {
+ return JSON.parse(value);
+ } catch {
+ return undefined;
+ }
+};
+
+const filesCache = new Map();
+
+const normalizeFiles = (raw: unknown): NormalizedFile[] => {
+ if (!raw) return [];
+
+ if (Array.isArray(raw)) {
+ return raw
+ .map((item: any) => {
+ if (!item) return null;
+ if (typeof item === 'string') {
+ return {
+ url: item,
+ thumbnail: item,
+ name: guessNameFromUrl(item),
+ isImage: isImageUrl(item)
+ } satisfies NormalizedFile;
+ }
+ const url = item.url || item.path || item.href;
+ if (!url || typeof url !== 'string') return null;
+ const thumbnail = typeof item.thumbnail === 'string' ? item.thumbnail : undefined;
+ const name = typeof item.name === 'string' ? item.name : guessNameFromUrl(url);
+ const isImage = typeof item.isImage === 'boolean' ? item.isImage : isImageUrl(url);
+ return {url, thumbnail, name, isImage} satisfies NormalizedFile;
+ })
+ .filter(Boolean) as NormalizedFile[];
+ }
+
+ if (typeof raw === 'string') {
+ const text = raw.trim();
+ if (!text) return [];
+
+ const cached = filesCache.get(text);
+ if (cached) return cached;
+
+ // 兼容:后端返回 JSON 数组字符串(示例:"[{\"name\":\"...\",\"url\":\"...\"}]")
+ let parsed: any = tryParseJson(text);
+ if (typeof parsed === 'string') {
+ parsed = tryParseJson(parsed) ?? parsed;
+ }
+ if (Array.isArray(parsed)) {
+ const result = normalizeFiles(parsed);
+ if (filesCache.size > 500) filesCache.clear();
+ filesCache.set(text, result);
+ return result;
+ }
+
+ // 兜底:单个 url 或逗号分隔 url
+ const parts = text.includes(',') ? text.split(',') : [text];
+ const result = normalizeFiles(parts.map((p) => p.trim()).filter(Boolean));
+ if (filesCache.size > 500) filesCache.clear();
+ filesCache.set(text, result);
+ return result;
+ }
+
+ return [];
+};
+
// 完整的列配置(包含所有字段)
const allColumns = ref([
{
@@ -143,7 +268,7 @@ const allColumns = ref([
title: '用户信息',
dataIndex: 'userInfo',
key: 'userInfo',
- width: 300,
+ width: 240,
},
{
title: '拖欠方',
@@ -187,6 +312,14 @@ const allColumns = ref([
key: 'city',
align: 'center'
},
+ {
+ title: '步骤',
+ dataIndex: 'step',
+ key: 'step',
+ width: 120,
+ align: 'center',
+ filters: stepOptions.map((d) => ({ text: d.text, value: d.value }))
+ },
// {
// title: '所在辖区',
// dataIndex: 'region',
@@ -243,7 +376,7 @@ const allColumns = ref([
{
title: '操作',
key: 'action',
- width: 180,
+ width: 120,
fixed: 'right',
align: 'center',
hideInSetting: true
@@ -258,6 +391,7 @@ const defaultVisibleColumns = [
'price',
'years',
'city',
+ 'step',
'files',
// 'status',
'createTime',
@@ -276,7 +410,10 @@ const reload = (where?: CreditMpCustomerParam) => {
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
searchText.value = where.keywords ?? '';
}
- const targetWhere = where ?? {keywords: searchText.value || undefined};
+ if (where && Object.prototype.hasOwnProperty.call(where, 'step')) {
+ searchStep.value = where.step;
+ }
+ const targetWhere = where ?? {keywords: searchText.value || undefined, step: searchStep.value};
selection.value = [];
tableRef?.value?.reload({where: targetWhere});
};
@@ -307,6 +444,7 @@ const exportData = () => {
{title: '所在省份', dataIndex: 'province'},
{title: '所在城市', dataIndex: 'city'},
{title: '所在辖区', dataIndex: 'region'},
+ {title: '步骤', dataIndex: 'step'},
{title: '文件路径', dataIndex: 'files'},
{title: '是否有数据', dataIndex: 'hasData'},
{title: '备注', dataIndex: 'comments'},
@@ -320,7 +458,8 @@ const exportData = () => {
],
fetchData: () =>
listCreditMpCustomer({
- keywords: searchText.value || undefined
+ keywords: searchText.value || undefined,
+ step: searchStep.value
})
});
};