Compare commits
36 Commits
17487cce2b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 147c34f4f9 | |||
| ce3f22f4ae | |||
| 54827a9876 | |||
| a0a4cc7a8d | |||
| 56063e9bcd | |||
| 72c431967d | |||
| 1b115edabe | |||
| 41a1fcb4ed | |||
| c79c68e7a1 | |||
| 5182112b72 | |||
| a9d008fb90 | |||
| 6827855b78 | |||
| 3f2ab2cc40 | |||
| a0170f820e | |||
| a9d513fca4 | |||
| fe20f0f0b3 | |||
| b1147f7a3d | |||
| c29daa5293 | |||
| b4f3dcbb18 | |||
| ddb311b82f | |||
| 6a9be80811 | |||
| 75d31dd09e | |||
| d3345d14d6 | |||
| ff186910da | |||
| 338a2b9d72 | |||
| 36806bac58 | |||
| 952a082752 | |||
| 9febd8016c | |||
| f01e3359ec | |||
| 8d1d9d9de9 | |||
| c16b857505 | |||
| d97d279670 | |||
| c18120fe81 | |||
| 2d7e44e0ad | |||
| c5908f4376 | |||
| f78aa97bd1 |
@@ -1,6 +1,7 @@
|
|||||||
VITE_APP_NAME=后台管理(开发环境)
|
VITE_APP_NAME=后台管理(开发环境)
|
||||||
#VITE_API_URL=http://127.0.0.1:9200/api
|
VITE_API_URL=http://127.0.0.1:9200/api
|
||||||
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
||||||
|
|
||||||
|
|
||||||
#VITE_API_URL=https://cms-api.s209.websoft.top/api
|
#VITE_API_URL=https://ysb-api.websoft.top/api
|
||||||
|
#VITE_SERVER_API_URL=https://server.websoft.top/api
|
||||||
|
|||||||
62
a.html
Normal file
62
a.html
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<p><strong>桂乐淘后台管理手册</strong></p>
|
||||||
|
<p><strong>后台登录信息:</strong></p>
|
||||||
|
<p><strong>地址:</strong><a href="login"><strong>https://glt.websoft.top/login</strong></a><strong><br /></strong><strong>账号:13800010584</strong><strong><br /></strong><strong>验证码:183911</strong></p>
|
||||||
|
<p><strong>一、创建管理员账号</strong></p>
|
||||||
|
<p>(一)创建流程</p>
|
||||||
|
<p>主页-用户管理-设置手机号-角色设置(将该手机号设置为对应的角色权限)-打开管理员开关,即可创建管理员账号-搜索到对应管理员手机号-勾选该账号-重置密码-复制密码给管理员-打开后台登录地址-使用手机号+登录密码+核验码进行登录-登录成功后再自行修改登录密码。</p>
|
||||||
|
<p><strong> <img src="https://oss.wsdns.cn/20260306/4ce09bd61eb549a3b955490ba2b489d8.png" /></strong></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/a2814cc44e5c41909a513b53b13e2918.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/205744c621a045b5a2557456dabd25de.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/f151c0a2571540f1bb54f73e0009db07.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/fcc150c5e8294b9d990c0eb7db51eed4.png" /></p>
|
||||||
|
<p> </p>
|
||||||
|
<p>(二)角色管理</p>
|
||||||
|
<p>新建或修改角色-分配权限(按角色需要勾选权限)</p>
|
||||||
|
<p>1.角色设置</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/44dcfdd7e424434788c52a5e3b129b05.png" /></p>
|
||||||
|
<p>2.角色名称</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/d7405372b30647f99042a1667fba1713.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/406cb1aab12c45d4ac6aa550bb76b0c2.png" /></p>
|
||||||
|
<p><strong> </strong></p>
|
||||||
|
<p><strong>二、业务管理(创建商品-创建水票-配送)</strong></p>
|
||||||
|
<p>(一)商品创建流程</p>
|
||||||
|
<p>新增或编辑商品,按字段填写或上传商品信息,保存后即可(可自主管理上下架及商品排序),在商品管理模块添加的是普通的快递商品,不属于水票套票</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/9547293d358c4de0834f39301a68967a.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/8f7fd971e3bf48c8bf57ee8ff88dc6b0.png" /></p>
|
||||||
|
<p> </p>
|
||||||
|
<p>(二)水票套票创建及配送</p>
|
||||||
|
<p>基于商品管理里的商品信息,进入水票-模板管理-填写模板规则</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/72f6691aacab43d5accacc3d585b2c57.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/62a4c06e5d7c4f35980eeb4f661fb7a2.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/4e6a9764ffe24079ae90701254d695ea.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/0528a0acf7a9483b973a521f8255e6a9.png" /></p>
|
||||||
|
<p>(三)配送</p>
|
||||||
|
<p>用户购买水票后,系统自动释放水票模板的首期水票,并自动生成配送订单到用户指定地址(须在电子围栏内)</p>
|
||||||
|
<p>配送员添加:接单-配送员管理-新增/修改配送员信息</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/853717ca88a046b7bd11f82a7dd1a17d.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/9d5b41ccbc7243629b98bd1b5e96d000.png" /></p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/5bdaadaa39e14046bf1d08c34d745bc3.png" /></p>
|
||||||
|
<p> </p>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong> </strong></p>
|
||||||
|
<p><strong>三、分销</strong></p>
|
||||||
|
<p>(一)分销用户</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/964092d296074f0a9df2b9f46d7ef9f4.png" /></p>
|
||||||
|
<p>(二)推荐关系</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/f299eb173590496c84cd545425c82438.png" /></p>
|
||||||
|
<p>(三)分销订单</p>
|
||||||
|
<p><strong><img src="https://oss.wsdns.cn/20260306/ddf51b18abee477eabc3335d5535e9c4.png" /></strong></p>
|
||||||
|
<p><strong>用户操作手册</strong></p>
|
||||||
|
<p><strong>一、水票购买</strong></p>
|
||||||
|
<p>用户可按指引购买水票,选择地址时,如不在电子围栏范围内,无法付款配送。</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/880543fbd60a44d98f79445df0f45115.png" /> <img src="https://oss.wsdns.cn/20260306/f7f628046e384e51a3df99caa320a8a8.png" /><img src="https://oss.wsdns.cn/20260306/515f0893e8d24e0c8ba4a2288f3b67f9.png" /></p>
|
||||||
|
<p><strong>二、我的水票</strong></p>
|
||||||
|
<p>用户查看自己购买过的水票明细及使用、释放情况等</p>
|
||||||
|
<p><img src="https://oss.wsdns.cn/20260306/a482517619654972a713a628109f2cf7.png" /></p>
|
||||||
|
<p><strong> </strong></p>
|
||||||
|
<p><strong>三</strong><strong>、</strong><strong>立即送水</strong></p>
|
||||||
|
<p>用户查看自己购买过的水票明细及使用、释放情况等</p>
|
||||||
|
<p> <img src="https://oss.wsdns.cn/20260306/66a9645153d94ca6b598ae9813516179.png" /><img src="https://oss.wsdns.cn/20260306/06ecf42a53f8411a88ade40e797ed9e9.png" /></p>
|
||||||
|
<p><strong>三、</strong><strong>分享中心</strong></p>
|
||||||
|
<p>用户查看自己的推广佣金情况、推广的用户列表,申请提现等</p>
|
||||||
|
<p> <img src="https://oss.wsdns.cn/20260306/eb6d0d4240374549945a14f6c6b3e179.png" /><img src="https://oss.wsdns.cn/20260306/6036ca3fe4a0438baa3a680a62d2da7b.png" /></p>
|
||||||
@@ -26,4 +26,3 @@ export async function refreshCreditCompanyId(
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ export async function pageCreditAdministrativeLicense(
|
|||||||
) {
|
) {
|
||||||
const res = await request.get<
|
const res = await request.get<
|
||||||
ApiResult<PageResult<CreditAdministrativeLicense>>
|
ApiResult<PageResult<CreditAdministrativeLicense>>
|
||||||
>('/credit/credit-administrative-license/page', { params: withCreditUserScope(params) });
|
>('/credit/credit-administrative-license/page', {
|
||||||
|
params: withCreditUserScope(params)
|
||||||
|
});
|
||||||
if (res.data.code === 0) {
|
if (res.data.code === 0) {
|
||||||
return res.data.data;
|
return res.data.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export interface CreditAdministrativeLicense {
|
|||||||
validityEnd?: string;
|
validityEnd?: string;
|
||||||
// 许可机关
|
// 许可机关
|
||||||
licensingAuthority?: string;
|
licensingAuthority?: string;
|
||||||
@TableField("License_content")
|
|
||||||
// 许可内容
|
// 许可内容
|
||||||
licenseContent?: string;
|
licenseContent?: string;
|
||||||
// 数据来源单位
|
// 数据来源单位
|
||||||
|
|||||||
@@ -127,3 +127,30 @@ export async function importCreditCaseFiling(file: File, companyId?: number) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入历史立案信息司法大数据
|
||||||
|
*/
|
||||||
|
export async function importCreditCaseFilingHistory(
|
||||||
|
file: File,
|
||||||
|
companyId?: number
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
if (companyId != null) {
|
||||||
|
formData.append('companyId', String(companyId));
|
||||||
|
}
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-case-filing/import/history',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,6 +123,28 @@ export async function importCreditCompany(file: File) {
|
|||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入客户
|
||||||
|
*/
|
||||||
|
export async function importCustomer(file: File) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
formData.append('isCustomer', '1');
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-company/import',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据企业匹配名称查询关联信息
|
* 根据企业匹配名称查询关联信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -108,6 +108,56 @@ export interface CreditCompany {
|
|||||||
cechnologyLevel?: string;
|
cechnologyLevel?: string;
|
||||||
// 是否小微企业
|
// 是否小微企业
|
||||||
smallEnterprise?: string;
|
smallEnterprise?: string;
|
||||||
|
// 记录数
|
||||||
|
creditAdministrativeLicense?: number;
|
||||||
|
// 记录数
|
||||||
|
creditBankruptcy?: number;
|
||||||
|
// 记录数
|
||||||
|
creditBranch?: number;
|
||||||
|
// 记录数
|
||||||
|
creditBreachOfTrust?: number;
|
||||||
|
// 记录数
|
||||||
|
creditCaseFiling?: number;
|
||||||
|
// 记录数
|
||||||
|
creditCompetitor?: number;
|
||||||
|
// 记录数
|
||||||
|
creditCourtAnnouncement?: number;
|
||||||
|
// 记录数
|
||||||
|
creditCourtSession?: number;
|
||||||
|
// 记录数
|
||||||
|
creditCustomer?: number;
|
||||||
|
// 记录数
|
||||||
|
creditDeliveryNotice?: number;
|
||||||
|
// 记录数
|
||||||
|
creditExternal?: number;
|
||||||
|
// 记录数
|
||||||
|
creditFinalVersion?: number;
|
||||||
|
// 记录数
|
||||||
|
creditGqdj?: number;
|
||||||
|
// 记录数
|
||||||
|
creditHistoricalLegalPerson?: number;
|
||||||
|
// 记录数
|
||||||
|
creditJudgmentDebtor?: number;
|
||||||
|
// 记录数
|
||||||
|
creditJudicialDocument?: number;
|
||||||
|
// 记录数
|
||||||
|
creditJudiciary?: number;
|
||||||
|
// 记录数
|
||||||
|
creditMediation?: number;
|
||||||
|
// 记录数
|
||||||
|
creditNearbyCompany?: number;
|
||||||
|
// 记录数
|
||||||
|
creditPatent?: number;
|
||||||
|
// 记录数
|
||||||
|
creditRiskRelation?: number;
|
||||||
|
// 记录数
|
||||||
|
creditSupplier?: number;
|
||||||
|
// 记录数
|
||||||
|
creditSuspectedRelationship?: number;
|
||||||
|
// 记录数
|
||||||
|
creditUser?: number;
|
||||||
|
// 记录数
|
||||||
|
creditXgxf?: number;
|
||||||
// 备注
|
// 备注
|
||||||
comments?: string;
|
comments?: string;
|
||||||
// 是否推荐
|
// 是否推荐
|
||||||
@@ -133,7 +183,8 @@ export interface CreditCompany {
|
|||||||
*/
|
*/
|
||||||
export interface CreditCompanyParam extends PageParam {
|
export interface CreditCompanyParam extends PageParam {
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
type?: number;
|
||||||
|
isCustomer?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,3 +134,30 @@ export async function importCreditDeliveryNotice(
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入历史送达公告司法大数据
|
||||||
|
*/
|
||||||
|
export async function importCreditDeliveryNoticeHistory(
|
||||||
|
file: File,
|
||||||
|
companyId?: number
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
if (companyId != null) {
|
||||||
|
formData.append('companyId', String(companyId));
|
||||||
|
}
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-delivery-notice/import/history',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ export async function pageCreditHistoricalLegalPerson(
|
|||||||
) {
|
) {
|
||||||
const res = await request.get<
|
const res = await request.get<
|
||||||
ApiResult<PageResult<CreditHistoricalLegalPerson>>
|
ApiResult<PageResult<CreditHistoricalLegalPerson>>
|
||||||
>('/credit/credit-historical-legal-person/page', { params: withCreditUserScope(params) });
|
>('/credit/credit-historical-legal-person/page', {
|
||||||
|
params: withCreditUserScope(params)
|
||||||
|
});
|
||||||
if (res.data.code === 0) {
|
if (res.data.code === 0) {
|
||||||
return res.data.data;
|
return res.data.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export interface CreditJudgmentDebtor {
|
|||||||
id?: number;
|
id?: number;
|
||||||
// 案号
|
// 案号
|
||||||
caseNumber?: string;
|
caseNumber?: string;
|
||||||
// 被执行人名称
|
//
|
||||||
name?: string;
|
name?: string;
|
||||||
// 证件号/组织机构代码
|
// 证件号/组织机构代码
|
||||||
code?: string;
|
code?: string;
|
||||||
@@ -44,6 +44,14 @@ export interface CreditJudgmentDebtor {
|
|||||||
updateTime?: string;
|
updateTime?: string;
|
||||||
// 历史ID
|
// 历史ID
|
||||||
historyId?: number;
|
historyId?: number;
|
||||||
|
// 原告/上诉人
|
||||||
|
plaintiffAppellant?: string;
|
||||||
|
// 被告/被上诉人
|
||||||
|
appellee?: string;
|
||||||
|
// 其他当事人/第三人
|
||||||
|
otherPartiesThirdParty?: string;
|
||||||
|
// 被执行人名称
|
||||||
|
name1?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export interface CreditJudicialDocument {
|
|||||||
id?: number;
|
id?: number;
|
||||||
// 文书标题
|
// 文书标题
|
||||||
title?: string;
|
title?: string;
|
||||||
|
// 文书类型
|
||||||
|
documentType?: string;
|
||||||
// 数据类型
|
// 数据类型
|
||||||
dataType?: string;
|
dataType?: string;
|
||||||
// 原告/上诉人
|
// 原告/上诉人
|
||||||
|
|||||||
@@ -125,3 +125,30 @@ export async function importCreditMediation(file: File, companyId?: number) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入历史诉前调解司法大数据
|
||||||
|
*/
|
||||||
|
export async function importCreditMediationHistory(
|
||||||
|
file: File,
|
||||||
|
companyId?: number
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
if (companyId != null) {
|
||||||
|
formData.append('companyId', String(companyId));
|
||||||
|
}
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-mediation/import/history',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|||||||
105
src/api/credit/creditMpCustomer/index.ts
Normal file
105
src/api/credit/creditMpCustomer/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { CreditMpCustomer, CreditMpCustomerParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询小程序端客户
|
||||||
|
*/
|
||||||
|
export async function pageCreditMpCustomer(params: CreditMpCustomerParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<CreditMpCustomer>>>(
|
||||||
|
'/credit/credit-mp-customer/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询小程序端客户列表
|
||||||
|
*/
|
||||||
|
export async function listCreditMpCustomer(params?: CreditMpCustomerParam) {
|
||||||
|
const res = await request.get<ApiResult<CreditMpCustomer[]>>(
|
||||||
|
'/credit/credit-mp-customer',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加小程序端客户
|
||||||
|
*/
|
||||||
|
export async function addCreditMpCustomer(data: CreditMpCustomer) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-mp-customer',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改小程序端客户
|
||||||
|
*/
|
||||||
|
export async function updateCreditMpCustomer(data: CreditMpCustomer) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-mp-customer',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除小程序端客户
|
||||||
|
*/
|
||||||
|
export async function removeCreditMpCustomer(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-mp-customer/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除小程序端客户
|
||||||
|
*/
|
||||||
|
export async function removeBatchCreditMpCustomer(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-mp-customer/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询小程序端客户
|
||||||
|
*/
|
||||||
|
export async function getCreditMpCustomer(id: number) {
|
||||||
|
const res = await request.get<ApiResult<CreditMpCustomer>>(
|
||||||
|
'/credit/credit-mp-customer/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
66
src/api/credit/creditMpCustomer/model/index.ts
Normal file
66
src/api/credit/creditMpCustomer/model/index.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序端客户
|
||||||
|
*/
|
||||||
|
export interface CreditMpCustomer {
|
||||||
|
// ID
|
||||||
|
id?: number;
|
||||||
|
// 拖欠方
|
||||||
|
toUser?: string;
|
||||||
|
// 拖欠金额
|
||||||
|
price?: string;
|
||||||
|
// 拖欠年数
|
||||||
|
years?: string;
|
||||||
|
// 链接
|
||||||
|
url?: string;
|
||||||
|
// 状态
|
||||||
|
statusTxt?: string;
|
||||||
|
// 企业ID
|
||||||
|
companyId?: number;
|
||||||
|
// 所在省份
|
||||||
|
province?: string;
|
||||||
|
// 所在城市
|
||||||
|
city?: string;
|
||||||
|
// 所在辖区
|
||||||
|
region?: string;
|
||||||
|
// 文件路径
|
||||||
|
files?: string;
|
||||||
|
// 步骤, 0未受理1已受理2材料提交3合同签订4执行回款5完结
|
||||||
|
step?: number;
|
||||||
|
// 是否有数据
|
||||||
|
hasData?: string;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 是否推荐
|
||||||
|
recommend?: number;
|
||||||
|
// 排序(数字越小越靠前)
|
||||||
|
sortNumber?: number;
|
||||||
|
// 状态, 0正常, 1冻结
|
||||||
|
status?: number;
|
||||||
|
// 是否删除, 0否, 1是
|
||||||
|
deleted?: number;
|
||||||
|
// 用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 昵称
|
||||||
|
nickname?: string;
|
||||||
|
// 头像
|
||||||
|
avatar?: string;
|
||||||
|
// 手机号
|
||||||
|
phone?: string;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序端客户搜索条件
|
||||||
|
*/
|
||||||
|
export interface CreditMpCustomerParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
step?: number;
|
||||||
|
}
|
||||||
@@ -115,11 +115,7 @@ export async function importCreditNearbyCompany(
|
|||||||
file: File,
|
file: File,
|
||||||
companyId?: number
|
companyId?: number
|
||||||
) {
|
) {
|
||||||
const formData = new FormData();
|
const formData = buildImportFormData(file, companyId);
|
||||||
formData.append('file', file);
|
|
||||||
if (companyId != null) {
|
|
||||||
formData.append('companyId', String(companyId));
|
|
||||||
}
|
|
||||||
const res = await request.post<ApiResult<unknown>>(
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
'/credit/credit-nearby-company/import',
|
'/credit/credit-nearby-company/import',
|
||||||
formData,
|
formData,
|
||||||
@@ -134,3 +130,104 @@ export async function importCreditNearbyCompany(
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入附近企业(多文件,同一次请求)
|
||||||
|
*
|
||||||
|
* 约定:后端需支持 multipart 同名字段 `file` 多次出现(常见于 MultipartFile[] file)
|
||||||
|
*/
|
||||||
|
export async function importCreditNearbyCompanyMulti(
|
||||||
|
files: File[] | FileList,
|
||||||
|
companyId?: number
|
||||||
|
) {
|
||||||
|
const formData = buildImportFormData(files, companyId);
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/credit/credit-nearby-company/import',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildImportFormData(
|
||||||
|
fileOrFiles: File | File[] | FileList,
|
||||||
|
companyId?: number
|
||||||
|
) {
|
||||||
|
const formData = new FormData();
|
||||||
|
if (Array.isArray(fileOrFiles)) {
|
||||||
|
fileOrFiles.forEach((f) => formData.append('file', f));
|
||||||
|
} else if (fileOrFiles instanceof FileList) {
|
||||||
|
Array.from(fileOrFiles).forEach((f) => formData.append('file', f));
|
||||||
|
} else {
|
||||||
|
formData.append('file', fileOrFiles);
|
||||||
|
}
|
||||||
|
if (companyId != null) {
|
||||||
|
formData.append('companyId', String(companyId));
|
||||||
|
}
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportBatchCreditNearbyCompanyItem {
|
||||||
|
fileName: string;
|
||||||
|
success: boolean;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportBatchCreditNearbyCompanyResult {
|
||||||
|
total: number;
|
||||||
|
success: number;
|
||||||
|
failure: number;
|
||||||
|
items: ImportBatchCreditNearbyCompanyItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入附近企业(多文件)
|
||||||
|
*
|
||||||
|
* 说明:
|
||||||
|
* - 目前复用单文件导入接口,前端循环调用实现“多文件导入”
|
||||||
|
* - 不会在有失败时 reject(便于上层展示部分成功/失败明细)
|
||||||
|
*/
|
||||||
|
export async function importBatchCreditNearbyCompany(
|
||||||
|
files: File[] | FileList,
|
||||||
|
companyId?: number,
|
||||||
|
options?: {
|
||||||
|
/** 遇到失败是否立即停止,默认 false(继续导入后续文件) */
|
||||||
|
stopOnError?: boolean;
|
||||||
|
}
|
||||||
|
): Promise<ImportBatchCreditNearbyCompanyResult> {
|
||||||
|
const list = Array.isArray(files) ? files : Array.from(files);
|
||||||
|
const items: ImportBatchCreditNearbyCompanyItem[] = [];
|
||||||
|
const stopOnError = options?.stopOnError ?? false;
|
||||||
|
|
||||||
|
for (const file of list) {
|
||||||
|
try {
|
||||||
|
const msg = await importCreditNearbyCompany(file, companyId);
|
||||||
|
items.push({ fileName: file.name, success: true, message: msg });
|
||||||
|
} catch (e: unknown) {
|
||||||
|
items.push({
|
||||||
|
fileName: file.name,
|
||||||
|
success: false,
|
||||||
|
message: e instanceof Error ? e.message : String(e)
|
||||||
|
});
|
||||||
|
if (stopOnError) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = items.filter((d) => d.success).length;
|
||||||
|
const failure = items.length - success;
|
||||||
|
return {
|
||||||
|
total: list.length,
|
||||||
|
success,
|
||||||
|
failure,
|
||||||
|
items
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ export async function pageCreditSuspectedRelationship(
|
|||||||
) {
|
) {
|
||||||
const res = await request.get<
|
const res = await request.get<
|
||||||
ApiResult<PageResult<CreditSuspectedRelationship>>
|
ApiResult<PageResult<CreditSuspectedRelationship>>
|
||||||
>('/credit/credit-suspected-relationship/page', { params: withCreditUserScope(params) });
|
>('/credit/credit-suspected-relationship/page', {
|
||||||
|
params: withCreditUserScope(params)
|
||||||
|
});
|
||||||
if (res.data.code === 0) {
|
if (res.data.code === 0) {
|
||||||
return res.data.data;
|
return res.data.data;
|
||||||
}
|
}
|
||||||
|
|||||||
105
src/api/shop/shopCommunity/index.ts
Normal file
105
src/api/shop/shopCommunity/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopCommunity, ShopCommunityParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询小区
|
||||||
|
*/
|
||||||
|
export async function pageShopCommunity(params: ShopCommunityParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopCommunity>>>(
|
||||||
|
'/shop/shop-community/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询小区列表
|
||||||
|
*/
|
||||||
|
export async function listShopCommunity(params?: ShopCommunityParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopCommunity[]>>(
|
||||||
|
'/shop/shop-community',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加小区
|
||||||
|
*/
|
||||||
|
export async function addShopCommunity(data: ShopCommunity) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-community',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改小区
|
||||||
|
*/
|
||||||
|
export async function updateShopCommunity(data: ShopCommunity) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-community',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除小区
|
||||||
|
*/
|
||||||
|
export async function removeShopCommunity(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-community/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除小区
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopCommunity(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-community/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询小区
|
||||||
|
*/
|
||||||
|
export async function getShopCommunity(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopCommunity>>(
|
||||||
|
'/shop/shop-community/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
35
src/api/shop/shopCommunity/model/index.ts
Normal file
35
src/api/shop/shopCommunity/model/index.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小区
|
||||||
|
*/
|
||||||
|
export interface ShopCommunity {
|
||||||
|
// ID
|
||||||
|
id?: number;
|
||||||
|
// 小区名称
|
||||||
|
name?: string;
|
||||||
|
// 小区编号
|
||||||
|
code?: string;
|
||||||
|
// 详细地址
|
||||||
|
address?: string;
|
||||||
|
// 排序(数字越小越靠前)
|
||||||
|
sortNumber?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 状态, 0正常, 1冻结
|
||||||
|
status?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小区搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopCommunityParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
code?: string;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ export interface ShopDealerCapital {
|
|||||||
id?: number;
|
id?: number;
|
||||||
// 分销商用户ID
|
// 分销商用户ID
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
// 分销商昵称
|
||||||
|
nickName?: string;
|
||||||
// 订单ID
|
// 订单ID
|
||||||
orderId?: number;
|
orderId?: number;
|
||||||
// 订单编号
|
// 订单编号
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ export interface ShopDealerOrder {
|
|||||||
title?: string;
|
title?: string;
|
||||||
// 买家用户昵称
|
// 买家用户昵称
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
|
// 真实姓名
|
||||||
|
realName?: string;
|
||||||
// 订单编号
|
// 订单编号
|
||||||
orderNo?: string;
|
orderNo?: string;
|
||||||
// 订单总金额(不含运费)
|
// 订单总金额(不含运费)
|
||||||
@@ -52,6 +54,10 @@ export interface ShopDealerOrder {
|
|||||||
isSettled?: number;
|
isSettled?: number;
|
||||||
// 结算时间
|
// 结算时间
|
||||||
settleTime?: number;
|
settleTime?: number;
|
||||||
|
// 是否解冻(0否 1是)
|
||||||
|
isUnfreeze?: number;
|
||||||
|
// 解冻时间
|
||||||
|
unfreezeTime?: number;
|
||||||
// 订单备注
|
// 订单备注
|
||||||
comments?: string;
|
comments?: string;
|
||||||
// 商城ID
|
// 商城ID
|
||||||
|
|||||||
@@ -6,8 +6,16 @@ import type { PageParam } from '@/api';
|
|||||||
export interface ShopDealerUser {
|
export interface ShopDealerUser {
|
||||||
// 主键ID
|
// 主键ID
|
||||||
id?: number;
|
id?: number;
|
||||||
|
// 类型 0经销商 1企业 2集团
|
||||||
|
type?: number;
|
||||||
// 自增ID
|
// 自增ID
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
// 头像
|
||||||
|
avatar?: string;
|
||||||
|
// 店铺名称
|
||||||
|
dealerName?: string;
|
||||||
|
// 小区名称
|
||||||
|
community?: string;
|
||||||
// 姓名
|
// 姓名
|
||||||
realName?: string;
|
realName?: string;
|
||||||
// 手机号
|
// 手机号
|
||||||
@@ -34,6 +42,8 @@ export interface ShopDealerUser {
|
|||||||
thirdNum?: number;
|
thirdNum?: number;
|
||||||
// 专属二维码
|
// 专属二维码
|
||||||
qrcode?: string;
|
qrcode?: string;
|
||||||
|
// 配送员所属门店
|
||||||
|
shopName?: string;
|
||||||
// 是否删除
|
// 是否删除
|
||||||
isDelete?: number;
|
isDelete?: number;
|
||||||
// 租户id
|
// 租户id
|
||||||
@@ -56,5 +66,7 @@ export interface ShopDealerUser {
|
|||||||
*/
|
*/
|
||||||
export interface ShopDealerUserParam extends PageParam {
|
export interface ShopDealerUserParam extends PageParam {
|
||||||
id?: number;
|
id?: number;
|
||||||
|
realName?: string;
|
||||||
|
mobile?: string;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export interface ShopGoods {
|
|||||||
supplierMerchantId?: number;
|
supplierMerchantId?: number;
|
||||||
supplierName?: string;
|
supplierName?: string;
|
||||||
// 状态(0:未上架,1:上架)
|
// 状态(0:未上架,1:上架)
|
||||||
isShow?: number;
|
isShow?: boolean;
|
||||||
// 状态, 0上架 1待上架 2待审核 3审核不通过
|
// 状态, 0上架 1待上架 2待审核 3审核不通过
|
||||||
status?: number;
|
status?: number;
|
||||||
// 备注
|
// 备注
|
||||||
@@ -124,6 +124,21 @@ export interface ShopGoods {
|
|||||||
canUseDate?: string;
|
canUseDate?: string;
|
||||||
ensureTag?: string;
|
ensureTag?: string;
|
||||||
expiredDay?: number;
|
expiredDay?: number;
|
||||||
|
|
||||||
|
// --- 分销/佣金(新字段,后端保持 snake_case)---
|
||||||
|
// 是否开启分销佣金:0关闭 1开启
|
||||||
|
isOpenCommission?: number;
|
||||||
|
// 分佣类型:10固定金额 20百分比
|
||||||
|
commissionType?: number;
|
||||||
|
// 一级/二级/三级分销佣金(单位以服务端为准)
|
||||||
|
firstMoney?: number;
|
||||||
|
secondMoney?: number;
|
||||||
|
thirdMoney?: number;
|
||||||
|
// 一级/二级分红(单位以服务端为准)
|
||||||
|
firstDividend?: number;
|
||||||
|
secondDividend?: number;
|
||||||
|
// 配送奖金
|
||||||
|
deliveryMoney?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BathSet {
|
export interface BathSet {
|
||||||
|
|||||||
@@ -135,3 +135,18 @@ export async function shopOrderTotal(params?: ShopOrderParam) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请|同意退款
|
||||||
|
*/
|
||||||
|
export async function refundShopOrder(data: ShopOrder) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/shop-order/refund',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ export interface ShopOrder {
|
|||||||
icCard?: string;
|
icCard?: string;
|
||||||
// 头像
|
// 头像
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
// 昵称(部分接口会返回)
|
||||||
|
nickname?: string;
|
||||||
|
// 兼容字段:部分接口可能返回 name
|
||||||
|
name?: string;
|
||||||
// 真实姓名
|
// 真实姓名
|
||||||
realName?: string;
|
realName?: string;
|
||||||
// 手机号码
|
// 手机号码
|
||||||
@@ -99,6 +103,8 @@ export interface ShopOrder {
|
|||||||
expressId?: number;
|
expressId?: number;
|
||||||
// 快递公司名称
|
// 快递公司名称
|
||||||
expressName?: string;
|
expressName?: string;
|
||||||
|
// 物流单号
|
||||||
|
expressNo?: string;
|
||||||
// 发货人
|
// 发货人
|
||||||
sendName?: string;
|
sendName?: string;
|
||||||
// 发货人联系方式
|
// 发货人联系方式
|
||||||
|
|||||||
105
src/api/shop/shopStore/index.ts
Normal file
105
src/api/shop/shopStore/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopStore, ShopStoreParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询门店
|
||||||
|
*/
|
||||||
|
export async function pageShopStore(params: ShopStoreParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopStore>>>(
|
||||||
|
'/shop/shop-store/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询门店列表
|
||||||
|
*/
|
||||||
|
export async function listShopStore(params?: ShopStoreParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopStore[]>>(
|
||||||
|
'/shop/shop-store',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加门店
|
||||||
|
*/
|
||||||
|
export async function addShopStore(data: ShopStore) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改门店
|
||||||
|
*/
|
||||||
|
export async function updateShopStore(data: ShopStore) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除门店
|
||||||
|
*/
|
||||||
|
export async function removeShopStore(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除门店
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopStore(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询门店
|
||||||
|
*/
|
||||||
|
export async function getShopStore(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopStore>>(
|
||||||
|
'/shop/shop-store/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
59
src/api/shop/shopStore/model/index.ts
Normal file
59
src/api/shop/shopStore/model/index.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店
|
||||||
|
*/
|
||||||
|
export interface ShopStore {
|
||||||
|
// 自增ID
|
||||||
|
id?: number;
|
||||||
|
// 店铺名称
|
||||||
|
name?: string;
|
||||||
|
// 门店地址
|
||||||
|
address?: string;
|
||||||
|
// 手机号码
|
||||||
|
phone?: string;
|
||||||
|
// 邮箱
|
||||||
|
email?: string;
|
||||||
|
// 门店经理
|
||||||
|
managerName?: string;
|
||||||
|
// 门店banner
|
||||||
|
shopBanner?: string;
|
||||||
|
// 所在省份
|
||||||
|
province?: string;
|
||||||
|
// 所在城市
|
||||||
|
city?: string;
|
||||||
|
// 所在辖区
|
||||||
|
region?: string;
|
||||||
|
// 经度和纬度
|
||||||
|
lngAndLat?: string;
|
||||||
|
// 位置
|
||||||
|
location?:string;
|
||||||
|
// 区域
|
||||||
|
district?: string;
|
||||||
|
// 轮廓
|
||||||
|
points?: string;
|
||||||
|
// 用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 状态
|
||||||
|
status?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 排序号
|
||||||
|
sortNumber?: number;
|
||||||
|
// 是否删除
|
||||||
|
isDelete?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopStoreParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
105
src/api/shop/shopStoreFence/index.ts
Normal file
105
src/api/shop/shopStoreFence/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopStoreFence, ShopStoreFenceParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function pageShopStoreFence(params: ShopStoreFenceParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopStoreFence>>>(
|
||||||
|
'/shop/shop-store-fence/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询黄家明_电子围栏列表
|
||||||
|
*/
|
||||||
|
export async function listShopStoreFence(params?: ShopStoreFenceParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreFence[]>>(
|
||||||
|
'/shop/shop-store-fence',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function addShopStoreFence(data: ShopStoreFence) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-fence',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function updateShopStoreFence(data: ShopStoreFence) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-fence',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function removeShopStoreFence(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-fence/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopStoreFence(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-fence/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export async function getShopStoreFence(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreFence>>(
|
||||||
|
'/shop/shop-store-fence/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
43
src/api/shop/shopStoreFence/model/index.ts
Normal file
43
src/api/shop/shopStoreFence/model/index.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 黄家明_电子围栏
|
||||||
|
*/
|
||||||
|
export interface ShopStoreFence {
|
||||||
|
// 自增ID
|
||||||
|
id?: number;
|
||||||
|
// 围栏名称
|
||||||
|
name?: string;
|
||||||
|
// 类型 0圆形 1方形
|
||||||
|
type?: number;
|
||||||
|
// 定位
|
||||||
|
location?: string;
|
||||||
|
// 经度
|
||||||
|
longitude?: string;
|
||||||
|
// 纬度
|
||||||
|
latitude?: string;
|
||||||
|
// 区域
|
||||||
|
district?: string;
|
||||||
|
// 电子围栏轮廓
|
||||||
|
points?: string;
|
||||||
|
// 排序(数字越小越靠前)
|
||||||
|
sortNumber?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 状态, 0正常, 1冻结
|
||||||
|
status?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 黄家明_电子围栏搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopStoreFenceParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
105
src/api/shop/shopStoreRider/index.ts
Normal file
105
src/api/shop/shopStoreRider/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopStoreRider, ShopStoreRiderParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询配送员
|
||||||
|
*/
|
||||||
|
export async function pageShopStoreRider(params: ShopStoreRiderParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopStoreRider>>>(
|
||||||
|
'/shop/shop-store-rider/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询配送员列表
|
||||||
|
*/
|
||||||
|
export async function listShopStoreRider(params?: ShopStoreRiderParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreRider[]>>(
|
||||||
|
'/shop/shop-store-rider',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加配送员
|
||||||
|
*/
|
||||||
|
export async function addShopStoreRider(data: ShopStoreRider) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-rider',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改配送员
|
||||||
|
*/
|
||||||
|
export async function updateShopStoreRider(data: ShopStoreRider) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-rider',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配送员
|
||||||
|
*/
|
||||||
|
export async function removeShopStoreRider(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-rider/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除配送员
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopStoreRider(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-rider/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询配送员
|
||||||
|
*/
|
||||||
|
export async function getShopStoreRider(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreRider>>(
|
||||||
|
'/shop/shop-store-rider/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
65
src/api/shop/shopStoreRider/model/index.ts
Normal file
65
src/api/shop/shopStoreRider/model/index.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配送员
|
||||||
|
*/
|
||||||
|
export interface ShopStoreRider {
|
||||||
|
// 主键ID
|
||||||
|
id?: string;
|
||||||
|
// 门店ID(shop_store.id)
|
||||||
|
storeId?: number;
|
||||||
|
// 门店名称(后端联表返回,提交时可不传)
|
||||||
|
storeName?: string;
|
||||||
|
// 配送点ID(shop_dealer.id)
|
||||||
|
dealerId?: number;
|
||||||
|
// 骑手编号(可选)
|
||||||
|
riderNo?: string;
|
||||||
|
// 姓名
|
||||||
|
realName?: string;
|
||||||
|
// 手机号
|
||||||
|
mobile?: string;
|
||||||
|
// 头像
|
||||||
|
avatar?: string;
|
||||||
|
// 身份证号(可选)
|
||||||
|
idCardNo?: string;
|
||||||
|
// 状态:1启用;0禁用
|
||||||
|
status?: number;
|
||||||
|
// 接单状态:0休息/下线;1在线;2忙碌
|
||||||
|
workStatus?: number;
|
||||||
|
// 是否开启自动派单:1是;0否
|
||||||
|
autoDispatchEnabled?: number;
|
||||||
|
// 派单优先级(同小区多骑手时可用,值越大越优先)
|
||||||
|
dispatchPriority?: number;
|
||||||
|
// 最大同时配送单数(0表示不限制)
|
||||||
|
maxOnhandOrders?: number;
|
||||||
|
// 是否计算工资(提成):1计算;0不计算(如三方配送点可设0)
|
||||||
|
commissionCalcEnabled?: number;
|
||||||
|
// 水每桶提成金额(元/桶)
|
||||||
|
waterBucketUnitFee?: string;
|
||||||
|
// 其他商品提成方式:1按订单固定金额;2按订单金额比例;3按商品规则(另表)
|
||||||
|
otherGoodsCommissionType?: number;
|
||||||
|
// 其他商品提成值:固定金额(元)或比例(%)
|
||||||
|
otherGoodsCommissionValue?: string;
|
||||||
|
// 用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 排序号
|
||||||
|
sortNumber?: number;
|
||||||
|
// 是否删除
|
||||||
|
isDelete?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配送员搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopStoreRiderParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
105
src/api/shop/shopStoreUser/index.ts
Normal file
105
src/api/shop/shopStoreUser/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopStoreUser, ShopStoreUserParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询店员
|
||||||
|
*/
|
||||||
|
export async function pageShopStoreUser(params: ShopStoreUserParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopStoreUser>>>(
|
||||||
|
'/shop/shop-store-user/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询店员列表
|
||||||
|
*/
|
||||||
|
export async function listShopStoreUser(params?: ShopStoreUserParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreUser[]>>(
|
||||||
|
'/shop/shop-store-user',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加店员
|
||||||
|
*/
|
||||||
|
export async function addShopStoreUser(data: ShopStoreUser) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-user',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改店员
|
||||||
|
*/
|
||||||
|
export async function updateShopStoreUser(data: ShopStoreUser) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-user',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除店员
|
||||||
|
*/
|
||||||
|
export async function removeShopStoreUser(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-user/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除店员
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopStoreUser(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-user/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询店员
|
||||||
|
*/
|
||||||
|
export async function getShopStoreUser(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreUser>>(
|
||||||
|
'/shop/shop-store-user/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
33
src/api/shop/shopStoreUser/model/index.ts
Normal file
33
src/api/shop/shopStoreUser/model/index.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店员
|
||||||
|
*/
|
||||||
|
export interface ShopStoreUser {
|
||||||
|
// 主键ID
|
||||||
|
id?: number;
|
||||||
|
// 配送点ID(shop_dealer.id)
|
||||||
|
storeId?: number;
|
||||||
|
// 用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 排序号
|
||||||
|
sortNumber?: number;
|
||||||
|
// 是否删除
|
||||||
|
isDelete?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店员搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopStoreUserParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
105
src/api/shop/shopStoreWarehouse/index.ts
Normal file
105
src/api/shop/shopStoreWarehouse/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { ShopStoreWarehouse, ShopStoreWarehouseParam } from './model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询仓库
|
||||||
|
*/
|
||||||
|
export async function pageShopStoreWarehouse(params: ShopStoreWarehouseParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<ShopStoreWarehouse>>>(
|
||||||
|
'/shop/shop-store-warehouse/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询仓库列表
|
||||||
|
*/
|
||||||
|
export async function listShopStoreWarehouse(params?: ShopStoreWarehouseParam) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreWarehouse[]>>(
|
||||||
|
'/shop/shop-store-warehouse',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加仓库
|
||||||
|
*/
|
||||||
|
export async function addShopStoreWarehouse(data: ShopStoreWarehouse) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-warehouse',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改仓库
|
||||||
|
*/
|
||||||
|
export async function updateShopStoreWarehouse(data: ShopStoreWarehouse) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-warehouse',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除仓库
|
||||||
|
*/
|
||||||
|
export async function removeShopStoreWarehouse(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-warehouse/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除仓库
|
||||||
|
*/
|
||||||
|
export async function removeBatchShopStoreWarehouse(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-store-warehouse/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询仓库
|
||||||
|
*/
|
||||||
|
export async function getShopStoreWarehouse(id: number) {
|
||||||
|
const res = await request.get<ApiResult<ShopStoreWarehouse>>(
|
||||||
|
'/shop/shop-store-warehouse/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
51
src/api/shop/shopStoreWarehouse/model/index.ts
Normal file
51
src/api/shop/shopStoreWarehouse/model/index.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓库
|
||||||
|
*/
|
||||||
|
export interface ShopStoreWarehouse {
|
||||||
|
// 自增ID
|
||||||
|
id?: number;
|
||||||
|
// 仓库名称
|
||||||
|
name?: string;
|
||||||
|
// 唯一标识
|
||||||
|
code?: string;
|
||||||
|
// 类型 中心仓,区域仓,门店仓
|
||||||
|
type?: string;
|
||||||
|
// 仓库地址
|
||||||
|
address?: string;
|
||||||
|
// 真实姓名
|
||||||
|
realName?: string;
|
||||||
|
// 联系电话
|
||||||
|
phone?: string;
|
||||||
|
// 所在省份
|
||||||
|
province?: string;
|
||||||
|
// 所在城市
|
||||||
|
city?: string;
|
||||||
|
// 所在辖区
|
||||||
|
region?: string;
|
||||||
|
// 经纬度
|
||||||
|
lngAndLat?: string;
|
||||||
|
// 用户ID
|
||||||
|
userId?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 排序号
|
||||||
|
sortNumber?: number;
|
||||||
|
// 是否删除
|
||||||
|
isDelete?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 创建时间
|
||||||
|
createTime?: string;
|
||||||
|
// 修改时间
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仓库搜索条件
|
||||||
|
*/
|
||||||
|
export interface ShopStoreWarehouseParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
126
src/components/SelectCommunity/components/select-data.vue
Normal file
126
src/components/SelectCommunity/components/select-data.vue
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="750"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:title="title"
|
||||||
|
:footer="null"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="userId"
|
||||||
|
:datasource="datasource"
|
||||||
|
:columns="columns"
|
||||||
|
:pagination="false"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<a-space>
|
||||||
|
<a-input-search
|
||||||
|
allow-clear
|
||||||
|
v-model:value="where.keywords"
|
||||||
|
placeholder="请输入搜索关键词"
|
||||||
|
style="width: 200px"
|
||||||
|
@search="reload"
|
||||||
|
@pressEnter="reload"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'roles'">
|
||||||
|
<a-tag v-for="(item, index) in record.roles" :key="index">{{
|
||||||
|
item.roleName
|
||||||
|
}}</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="done(record)">选择</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import {
|
||||||
|
ColumnItem,
|
||||||
|
DatasourceFunction
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import { EleProTable } from 'ele-admin-pro';
|
||||||
|
import useSearch from '@/utils/use-search';
|
||||||
|
import { pageShopCommunity } from "@/api/shop/shopCommunity";
|
||||||
|
import { ShopDealerUser } from "@/api/shop/shopDealerUser/model";
|
||||||
|
import {ShopCommunityParam} from "@/api/shop/shopCommunity/model";
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
// 弹窗是否打开
|
||||||
|
visible: boolean;
|
||||||
|
title?: string;
|
||||||
|
// 修改回显的数据
|
||||||
|
data?: ShopDealerUser | null;
|
||||||
|
type?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done', data: ShopDealerUser): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const { where } = useSearch<ShopCommunityParam>({
|
||||||
|
userId: undefined,
|
||||||
|
name: undefined,
|
||||||
|
keywords: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格配置
|
||||||
|
const columns = ref<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '小区名称',
|
||||||
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
|
||||||
|
where.type = 1;
|
||||||
|
return pageShopCommunity({
|
||||||
|
...where,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = () => {
|
||||||
|
tableRef?.value?.reload({ page: 1, where });
|
||||||
|
};
|
||||||
|
|
||||||
|
const done = (record: ShopDealerUser) => {
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done', record);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
||||||
71
src/components/SelectCommunity/index.vue
Normal file
71
src/components/SelectCommunity/index.vue
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-input
|
||||||
|
disabled
|
||||||
|
style="width: calc(100% - 32px)"
|
||||||
|
v-model:value="content"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
/>
|
||||||
|
<a-button @click="openEdit">
|
||||||
|
<template #icon><BulbOutlined class="ele-text-warning" /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-input-group>
|
||||||
|
<!-- 选择弹窗 -->
|
||||||
|
<select-data
|
||||||
|
v-model:visible="showEdit"
|
||||||
|
:data="current"
|
||||||
|
:title="placeholder"
|
||||||
|
:type="type"
|
||||||
|
@done="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { BulbOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import SelectData from './components/select-data.vue';
|
||||||
|
import { User } from '@/api/system/user/model';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
value?: any;
|
||||||
|
placeholder?: string;
|
||||||
|
index?: number;
|
||||||
|
type?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
placeholder: '请选择'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done', User): void;
|
||||||
|
(e: 'clear'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<User | null>(null);
|
||||||
|
const content = ref<any>();
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: User) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (row) => {
|
||||||
|
console.log(row,'sdfsd111')
|
||||||
|
row.index = Number(props.index);
|
||||||
|
emit('done', row);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.value) {
|
||||||
|
content.value = props.value;
|
||||||
|
}
|
||||||
|
// 查询租户列表
|
||||||
|
// const appList = ref<App[] | undefined>([]);
|
||||||
|
</script>
|
||||||
@@ -34,9 +34,9 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
<a-upload
|
<a-upload
|
||||||
v-else
|
v-else-if="type == 'image'"
|
||||||
:show-upload-list="false"
|
:show-upload-list="false"
|
||||||
:accept="'image/*,application/*'"
|
:accept="'image/*'"
|
||||||
:customRequest="onUpload"
|
:customRequest="onUpload"
|
||||||
>
|
>
|
||||||
<a-button type="primary" class="ele-btn-icon">
|
<a-button type="primary" class="ele-btn-icon">
|
||||||
@@ -46,6 +46,19 @@
|
|||||||
<span>上传图片</span>
|
<span>上传图片</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
|
<a-upload
|
||||||
|
v-else
|
||||||
|
:show-upload-list="false"
|
||||||
|
:accept="'image/*,application/*,text/*'"
|
||||||
|
:customRequest="onUpload"
|
||||||
|
>
|
||||||
|
<a-button type="primary" class="ele-btn-icon">
|
||||||
|
<template #icon>
|
||||||
|
<UploadOutlined />
|
||||||
|
</template>
|
||||||
|
<span>上传文件</span>
|
||||||
|
</a-button>
|
||||||
|
</a-upload>
|
||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -274,16 +287,36 @@
|
|||||||
// 上传文件
|
// 上传文件
|
||||||
const onUpload = (item) => {
|
const onUpload = (item) => {
|
||||||
const { file } = item;
|
const { file } = item;
|
||||||
if (!file.type.startsWith('image') && props.type != 'video') {
|
if (props.type == 'video') {
|
||||||
message.error('只能选择图片');
|
if (!file.type.startsWith('video')) {
|
||||||
|
message.error('只能选择视频');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (props.type == 'video') {
|
|
||||||
if (file.size / 1024 / 1024 > 100) {
|
if (file.size / 1024 / 1024 > 100) {
|
||||||
message.error('大小不能超过 100MB');
|
message.error('大小不能超过 100MB');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (props.type == 'image') {
|
||||||
|
if (!file.type.startsWith('image')) {
|
||||||
|
message.error('只能选择图片');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 默认:允许图片/文档等附件
|
||||||
|
const isAllowed =
|
||||||
|
file.type.startsWith('image') ||
|
||||||
|
file.type.startsWith('application') ||
|
||||||
|
file.type.startsWith('text') ||
|
||||||
|
file.type === 'application/octet-stream' ||
|
||||||
|
file.type === '';
|
||||||
|
if (!isAllowed) {
|
||||||
|
message.error('只能选择图片或文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (file.size / 1024 / 1024 > 10) {
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
message.error('大小不能超过 10MB');
|
message.error('大小不能超过 10MB');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,7 +16,16 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="image-upload-item">
|
<div v-else class="image-upload-item">
|
||||||
<YoutubeOutlined />
|
<a
|
||||||
|
class="file-item"
|
||||||
|
:href="stripOssImageProcess(item.url)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
:style="{ width: width + 'px', height: height + 'px' }"
|
||||||
|
>
|
||||||
|
<FileOutlined />
|
||||||
|
<span class="file-name">{{ item.name || guessNameFromUrl(item.url) }}</span>
|
||||||
|
</a>
|
||||||
<a class="image-upload-close" @click="onDeleteItem(index)">
|
<a class="image-upload-close" @click="onDeleteItem(index)">
|
||||||
<CloseOutlined />
|
<CloseOutlined />
|
||||||
</a>
|
</a>
|
||||||
@@ -47,12 +56,12 @@
|
|||||||
import {
|
import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
YoutubeOutlined
|
FileOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import SelectData from './components/select-data.vue';
|
import SelectData from './components/select-data.vue';
|
||||||
import { FileRecord } from '@/api/system/file/model';
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
import { isImage } from '@/utils/common';
|
import { isImage, stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -98,6 +107,16 @@
|
|||||||
const onDeleteItem = (index: number) => {
|
const onDeleteItem = (index: number) => {
|
||||||
emit('del', index);
|
emit('del', index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const guessNameFromUrl = (url: string) => {
|
||||||
|
const cleanUrl = (url?.split('?')[0] ?? '').trim();
|
||||||
|
const last = cleanUrl.split('/').pop() || '';
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(last) || url;
|
||||||
|
} catch {
|
||||||
|
return last || url;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.select-picture-btn {
|
.select-picture-btn {
|
||||||
@@ -112,6 +131,21 @@
|
|||||||
.image-upload-item {
|
.image-upload-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.file-item {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
border: 1px dashed var(--grey-7);
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
max-width: 240px;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.file-name {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
.image-upload-close {
|
.image-upload-close {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
|||||||
106
src/components/SelectShopStore/components/select-data.vue
Normal file
106
src/components/SelectShopStore/components/select-data.vue
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="800"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:title="title"
|
||||||
|
:footer="null"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:datasource="datasource"
|
||||||
|
:columns="columns"
|
||||||
|
:pagination="false"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<a-space>
|
||||||
|
<a-input-search
|
||||||
|
allow-clear
|
||||||
|
v-model:value="where.keywords"
|
||||||
|
placeholder="请输入门店关键词"
|
||||||
|
style="width: 240px"
|
||||||
|
@search="reload"
|
||||||
|
@pressEnter="reload"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="done(record)">选择</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import type {
|
||||||
|
ColumnItem,
|
||||||
|
DatasourceFunction
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import { EleProTable } from 'ele-admin-pro';
|
||||||
|
import useSearch from '@/utils/use-search';
|
||||||
|
import { pageShopStore } from '@/api/shop/shopStore';
|
||||||
|
import type { ShopStoreParam } from '@/api/shop/shopStore/model';
|
||||||
|
import type { ShopStore } from '@/api/shop/shopStore/model';
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
title?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done', data: ShopStore): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const { where } = useSearch<ShopStoreParam>({
|
||||||
|
id: undefined,
|
||||||
|
keywords: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
const columns = ref<ColumnItem[]>([
|
||||||
|
{ title: 'ID', dataIndex: 'id', width: 90 },
|
||||||
|
{ title: '门店名称', dataIndex: 'name' },
|
||||||
|
{ title: '电话', dataIndex: 'phone', width: 160 },
|
||||||
|
{ title: '地址', dataIndex: 'address' },
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
|
||||||
|
return pageShopStore({
|
||||||
|
...where,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
tableRef?.value?.reload({ page: 1, where: where as ShopStoreParam });
|
||||||
|
};
|
||||||
|
|
||||||
|
const done = (record: ShopStore) => {
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done', record);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
63
src/components/SelectShopStore/index.vue
Normal file
63
src/components/SelectShopStore/index.vue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-input
|
||||||
|
disabled
|
||||||
|
style="width: calc(100% - 32px)"
|
||||||
|
v-model:value="content"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
/>
|
||||||
|
<a-button @click="openEdit">
|
||||||
|
<template #icon><BulbOutlined class="ele-text-warning" /></template>
|
||||||
|
</a-button>
|
||||||
|
</a-input-group>
|
||||||
|
<!-- 选择弹窗 -->
|
||||||
|
<SelectData
|
||||||
|
v-model:visible="showEdit"
|
||||||
|
:title="placeholder"
|
||||||
|
@done="onChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { BulbOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import SelectData from './components/select-data.vue';
|
||||||
|
import type { ShopStore } from '@/api/shop/shopStore/model';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
value?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
placeholder: '选择门店'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done', data?: ShopStore): void;
|
||||||
|
(e: 'clear'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const showEdit = ref(false);
|
||||||
|
const content = ref<string>(props.value ?? '');
|
||||||
|
|
||||||
|
const openEdit = () => {
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (row?: ShopStore) => {
|
||||||
|
showEdit.value = false;
|
||||||
|
emit('done', row);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(v) => {
|
||||||
|
content.value = v ?? '';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -444,6 +444,24 @@ export const isImage = (fileName) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 移除 OSS 图片处理参数(非图片文件拼接该参数会导致访问失败)
|
||||||
|
export const stripOssImageProcess = (url?: string) => {
|
||||||
|
if (!url) return url;
|
||||||
|
const hashIndex = url.indexOf('#');
|
||||||
|
const withNoHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
||||||
|
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
||||||
|
const queryIndex = withNoHash.indexOf('?');
|
||||||
|
if (queryIndex < 0) return url;
|
||||||
|
const base = withNoHash.slice(0, queryIndex);
|
||||||
|
const query = withNoHash.slice(queryIndex + 1);
|
||||||
|
const kept = query
|
||||||
|
.split('&')
|
||||||
|
.filter(Boolean)
|
||||||
|
.filter((p) => p !== 'x-oss-process' && !p.startsWith('x-oss-process='));
|
||||||
|
const rebuilt = kept.length ? `${base}?${kept.join('&')}` : base;
|
||||||
|
return `${rebuilt}${hash}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const getWeek = (text) => {
|
export const getWeek = (text) => {
|
||||||
const week = [
|
const week = [
|
||||||
'星期日',
|
'星期日',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<span>导出</span>
|
<span>导出</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
<RefreshCompanyIdButton module="credit-case-filing" @done="reload"/>
|
<RefreshCompanyIdButton :module="props.module" @done="reload" />
|
||||||
<a-button
|
<a-button
|
||||||
danger
|
danger
|
||||||
class="ele-btn-icon"
|
class="ele-btn-icon"
|
||||||
@@ -49,10 +49,12 @@ import {
|
|||||||
CloudDownloadOutlined,
|
CloudDownloadOutlined,
|
||||||
DeleteOutlined
|
DeleteOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import RefreshCompanyIdButton from "@/views/credit/components/RefreshCompanyIdButton.vue";
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
/** 后端模块路径片段,如: credit-breach-of-trust */
|
||||||
|
module: string;
|
||||||
selection?: any[];
|
selection?: any[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
@@ -72,16 +74,16 @@ const emit = defineEmits<{
|
|||||||
const keywords = ref('');
|
const keywords = ref('');
|
||||||
const selection = computed(() => props.selection || []);
|
const selection = computed(() => props.selection || []);
|
||||||
|
|
||||||
// 新增
|
|
||||||
const add = () => {
|
|
||||||
emit('add');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
emit('search', { keywords: keywords.value });
|
emit('search', { keywords: keywords.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 刷新 companyId 后,保持当前条件并触发父级 reload
|
||||||
|
const reload = () => {
|
||||||
|
emit('search', { keywords: keywords.value });
|
||||||
|
};
|
||||||
|
|
||||||
// 导入
|
// 导入
|
||||||
const openImport = () => {
|
const openImport = () => {
|
||||||
emit('importData');
|
emit('importData');
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
CloudDownloadOutlined,
|
CloudDownloadOutlined,
|
||||||
DeleteOutlined
|
DeleteOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
|
import RefreshCompanyIdButton from "@/views/credit/components/RefreshCompanyIdButton.vue";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|||||||
@@ -57,4 +57,3 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
:selection="selection"
|
v-model:selection="selection"
|
||||||
:scroll="{ x: 2400 }"
|
:scroll="{ x: 2400 }"
|
||||||
tool-class="ele-toolbar-form"
|
tool-class="ele-toolbar-form"
|
||||||
class="sys-org-table"
|
class="sys-org-table"
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
:selection="selection"
|
v-model:selection="selection"
|
||||||
tool-class="ele-toolbar-form"
|
tool-class="ele-toolbar-form"
|
||||||
class="sys-org-table"
|
class="sys-org-table"
|
||||||
>
|
>
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'companyName'">
|
<template v-if="column.key === 'companyName'">
|
||||||
@@ -194,7 +193,7 @@
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
:selection="selection"
|
v-model:selection="selection"
|
||||||
tool-class="ele-toolbar-form"
|
tool-class="ele-toolbar-form"
|
||||||
class="sys-org-table"
|
class="sys-org-table"
|
||||||
>
|
>
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditBreachOfTrustHistory(file)
|
importCreditBreachOfTrustHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-breach-of-trust"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史失信被执行人</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -73,15 +68,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditBreachOfTrustImport v-model:visible="showImport" @done="reload" />
|
<CreditBreachOfTrustImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditBreachOfTrustHistoryImport v-model:visible="showImport2" @done="reload" />
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -93,7 +86,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditBreachOfTrustEdit from './components/creditBreachOfTrustEdit.vue';
|
import CreditBreachOfTrustEdit from './components/creditBreachOfTrustEdit.vue';
|
||||||
import CreditBreachOfTrustImport from './components/credit-breach-of-trust-import.vue';
|
import CreditBreachOfTrustImport from './components/credit-breach-of-trust-import.vue';
|
||||||
import CreditBreachOfTrustHistoryImport from './components/credit-breach-of-trust-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditBreachOfTrust,
|
pageCreditBreachOfTrust,
|
||||||
listCreditBreachOfTrust,
|
listCreditBreachOfTrust,
|
||||||
@@ -116,8 +108,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -163,13 +153,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -178,8 +168,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '发生时间',
|
title: '发生时间',
|
||||||
dataIndex: 'occurrenceTime',
|
dataIndex: 'releaseDate',
|
||||||
key: 'occurrenceTime',
|
key: 'releaseDate',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -215,9 +205,10 @@
|
|||||||
key: 'createTime',
|
key: 'createTime',
|
||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -254,11 +245,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditBreachOfTrust>({
|
exportCreditData<CreditBreachOfTrust>({
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<!-- 历史立案信息导入弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="520"
|
||||||
|
:footer="null"
|
||||||
|
title="历史立案信息批量导入"
|
||||||
|
:visible="visible"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-upload-dragger
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="doUpload"
|
||||||
|
style="padding: 24px 0; margin-bottom: 16px"
|
||||||
|
>
|
||||||
|
<p class="ant-upload-drag-icon">
|
||||||
|
<cloud-upload-outlined />
|
||||||
|
</p>
|
||||||
|
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||||
|
</a-upload-dragger>
|
||||||
|
</a-spin>
|
||||||
|
<div class="ele-text-center">
|
||||||
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
|
<a :href="templateUrl" download="历史立案信息导入模板.xlsx">
|
||||||
|
下载导入模板
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { importCreditCaseFilingHistory } from '@/api/credit/creditCaseFiling';
|
||||||
|
import { API_BASE_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 是否打开弹窗
|
||||||
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 导入请求状态
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 模板下载地址,保持与当前接口域名一致
|
||||||
|
const templateUrl = computed(() => {
|
||||||
|
const base = (localStorage.getItem('ApiUrl') || API_BASE_URL || '').replace(
|
||||||
|
/\/$/,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return `${base}/credit/credit-case-filing/import/history/template`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 上传 */
|
||||||
|
const doUpload = ({ file }) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
].includes(file.type)
|
||||||
|
) {
|
||||||
|
message.error('只能选择 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
importCreditCaseFilingHistory(file, props.companyId)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 更新 visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -22,9 +22,7 @@
|
|||||||
</a-spin>
|
</a-spin>
|
||||||
<div class="ele-text-center">
|
<div class="ele-text-center">
|
||||||
<span>只能上传xls、xlsx文件,</span>
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
<a :href="templateUrl" download="立案信息导入模板.xlsx">
|
<a :href="templateUrl" download="立案信息导入模板.xlsx"> 下载导入模板 </a>
|
||||||
下载导入模板
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ele-modal>
|
</ele-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-case-filing"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -153,13 +154,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -215,8 +216,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -178,19 +178,19 @@
|
|||||||
title: '原文件导入名称',
|
title: '原文件导入名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
width: 240
|
width: 280
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '系统匹配企业名称',
|
title: '系统匹配企业名称',
|
||||||
dataIndex: 'matchName',
|
dataIndex: 'matchName',
|
||||||
key: 'matchName',
|
key: 'matchName',
|
||||||
width: 240
|
width: 280
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '登记状态',
|
title: '登记状态',
|
||||||
dataIndex: 'registrationStatus',
|
dataIndex: 'registrationStatus',
|
||||||
key: 'registrationStatus',
|
key: 'registrationStatus',
|
||||||
width: 120
|
width: 180
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '法定代表人',
|
title: '法定代表人',
|
||||||
@@ -272,20 +272,17 @@
|
|||||||
title: '更多邮箱',
|
title: '更多邮箱',
|
||||||
dataIndex: 'moreEmail',
|
dataIndex: 'moreEmail',
|
||||||
key: 'moreEmail',
|
key: 'moreEmail',
|
||||||
width: 120,
|
|
||||||
ellipsis: true
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企业(机构)类型',
|
title: '企业(机构)类型',
|
||||||
dataIndex: 'institutionType',
|
dataIndex: 'institutionType',
|
||||||
key: 'institutionType',
|
key: 'institutionType'
|
||||||
width: 140
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '纳税人识别号',
|
title: '纳税人识别号',
|
||||||
dataIndex: 'taxpayerCode',
|
dataIndex: 'taxpayerCode',
|
||||||
key: 'taxpayerCode',
|
key: 'taxpayerCode'
|
||||||
width: 120
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '注册号',
|
title: '注册号',
|
||||||
@@ -308,18 +305,18 @@
|
|||||||
title: '参保人数所属年报',
|
title: '参保人数所属年报',
|
||||||
dataIndex: 'annualReport',
|
dataIndex: 'annualReport',
|
||||||
key: 'annualReport',
|
key: 'annualReport',
|
||||||
width: 140
|
width: 180
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '营业期限',
|
title: '营业期限',
|
||||||
dataIndex: 'businessTerm',
|
dataIndex: 'businessTerm',
|
||||||
key: 'businessTerm',
|
key: 'businessTerm',
|
||||||
width: 120
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业门类',
|
title: '国标行业门类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories',
|
dataIndex: 'nationalStandardIndustryCategories',
|
||||||
key: 'nationalStandardIndustryCategories',
|
key: 'nationalStandardIndustryCategories'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业大类',
|
title: '国标行业大类',
|
||||||
@@ -364,12 +361,14 @@
|
|||||||
{
|
{
|
||||||
title: '曾用名',
|
title: '曾用名',
|
||||||
dataIndex: 'formerName',
|
dataIndex: 'formerName',
|
||||||
key: 'formerName'
|
key: 'formerName',
|
||||||
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '英文名',
|
title: '英文名',
|
||||||
dataIndex: 'englishName',
|
dataIndex: 'englishName',
|
||||||
key: 'englishName'
|
key: 'englishName',
|
||||||
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '官网',
|
title: '官网',
|
||||||
@@ -455,6 +454,7 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-competitor" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -81,6 +82,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { exportCreditData } from '../utils/export';
|
import { exportCreditData } from '../utils/export';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditCompetitorEdit from './components/creditCompetitorEdit.vue';
|
import CreditCompetitorEdit from './components/creditCompetitorEdit.vue';
|
||||||
@@ -194,8 +196,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- 历史开庭公告导入弹窗 -->
|
<!-- 历史法院公告导入弹窗 -->
|
||||||
<template>
|
<template>
|
||||||
<ele-modal
|
<ele-modal
|
||||||
:width="520"
|
:width="520"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
title="历史开庭公告批量导入"
|
title="历史法院公告批量导入"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
@update:visible="updateVisible"
|
@update:visible="updateVisible"
|
||||||
>
|
>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
</a-spin>
|
</a-spin>
|
||||||
<div class="ele-text-center">
|
<div class="ele-text-center">
|
||||||
<span>只能上传xls、xlsx文件,</span>
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
<a :href="templateUrl" download="历史开庭公告导入模板.xlsx">
|
<a :href="templateUrl" download="历史法院公告导入模板.xlsx">
|
||||||
下载导入模板
|
下载导入模板
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditCourtAnnouncementHistory(file)
|
importCreditCourtAnnouncementHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-court-announcement"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史开庭公告</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -76,18 +71,13 @@
|
|||||||
v-model:visible="showImport"
|
v-model:visible="showImport"
|
||||||
@done="reload"
|
@done="reload"
|
||||||
/>
|
/>
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditCourtAnnouncementHistoryImport
|
|
||||||
v-model:visible="showImport2"
|
|
||||||
@done="reload"
|
|
||||||
/>
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -99,7 +89,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditCourtAnnouncementEdit from './components/creditCourtAnnouncementEdit.vue';
|
import CreditCourtAnnouncementEdit from './components/creditCourtAnnouncementEdit.vue';
|
||||||
import CreditCourtAnnouncementImport from './components/credit-court-announcement-import.vue';
|
import CreditCourtAnnouncementImport from './components/credit-court-announcement-import.vue';
|
||||||
import CreditCourtAnnouncementHistoryImport from './components/credit-court-announcement-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditCourtAnnouncement,
|
pageCreditCourtAnnouncement,
|
||||||
listCreditCourtAnnouncement,
|
listCreditCourtAnnouncement,
|
||||||
@@ -122,8 +111,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -169,13 +156,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -227,8 +214,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -265,11 +253,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditCourtAnnouncement>({
|
exportCreditData<CreditCourtAnnouncement>({
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditCourtSessionHistory(file)
|
importCreditCourtSessionHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-court-session"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史开庭公告</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -65,15 +60,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditCourtSessionImport v-model:visible="showImport" @done="reload" />
|
<CreditCourtSessionImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditCourtSessionHistoryImport v-model:visible="showImport2" @done="reload" />
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -85,7 +78,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditCourtSessionEdit from './components/creditCourtSessionEdit.vue';
|
import CreditCourtSessionEdit from './components/creditCourtSessionEdit.vue';
|
||||||
import CreditCourtSessionImport from './components/credit-court-session-import.vue';
|
import CreditCourtSessionImport from './components/credit-court-session-import.vue';
|
||||||
import CreditCourtSessionHistoryImport from './components/credit-court-session-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditCourtSession,
|
pageCreditCourtSession,
|
||||||
listCreditCourtSession,
|
listCreditCourtSession,
|
||||||
@@ -96,7 +88,7 @@
|
|||||||
CreditCourtSession,
|
CreditCourtSession,
|
||||||
CreditCourtSessionParam
|
CreditCourtSessionParam
|
||||||
} from '@/api/credit/creditCourtSession/model';
|
} from '@/api/credit/creditCourtSession/model';
|
||||||
import type {CreditMediation} from "@/api/credit/creditMediation/model";
|
import type { CreditMediation } from '@/api/credit/creditMediation/model';
|
||||||
|
|
||||||
// 表格实例
|
// 表格实例
|
||||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
@@ -109,8 +101,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -156,13 +146,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -213,8 +203,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -251,11 +242,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditCourtSession>({
|
exportCreditData<CreditCourtSession>({
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-customer" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -81,6 +82,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from './components/search.vue';
|
import Search from './components/search.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditCustomerEdit from './components/creditCustomerEdit.vue';
|
import CreditCustomerEdit from './components/creditCustomerEdit.vue';
|
||||||
import {
|
import {
|
||||||
@@ -155,22 +157,31 @@
|
|||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'statusTxt',
|
dataIndex: 'statusTxt',
|
||||||
key: 'statusTxt'
|
key: 'statusTxt',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '销售金额(万元)',
|
title: '销售金额(万元)',
|
||||||
dataIndex: 'price',
|
dataIndex: 'price',
|
||||||
key: 'price'
|
key: 'price',
|
||||||
|
width: 180,
|
||||||
|
sorter: true,
|
||||||
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '公开日期',
|
title: '公开日期',
|
||||||
dataIndex: 'publicDate',
|
dataIndex: 'publicDate',
|
||||||
key: 'publicDate'
|
key: 'publicDate',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '数据来源',
|
title: '数据来源',
|
||||||
dataIndex: 'dataSource',
|
dataIndex: 'dataSource',
|
||||||
key: 'dataSource'
|
key: 'dataSource',
|
||||||
|
align: 'center',
|
||||||
|
width: 90
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作人',
|
title: '操作人',
|
||||||
@@ -188,7 +199,7 @@
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<!-- 历史送达公告导入弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="520"
|
||||||
|
:footer="null"
|
||||||
|
title="历史送达公告批量导入"
|
||||||
|
:visible="visible"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-upload-dragger
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="doUpload"
|
||||||
|
style="padding: 24px 0; margin-bottom: 16px"
|
||||||
|
>
|
||||||
|
<p class="ant-upload-drag-icon">
|
||||||
|
<cloud-upload-outlined />
|
||||||
|
</p>
|
||||||
|
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||||
|
</a-upload-dragger>
|
||||||
|
</a-spin>
|
||||||
|
<div class="ele-text-center">
|
||||||
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
|
<a :href="templateUrl" download="历史送达公告导入模板.xlsx">
|
||||||
|
下载导入模板
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { importCreditDeliveryNoticeHistory } from '@/api/credit/creditDeliveryNotice';
|
||||||
|
import { API_BASE_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 是否打开弹窗
|
||||||
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 导入请求状态
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 模板下载地址,保持与当前接口域名一致
|
||||||
|
const templateUrl = computed(() => {
|
||||||
|
const base = (localStorage.getItem('ApiUrl') || API_BASE_URL || '').replace(
|
||||||
|
/\/$/,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return `${base}/credit/credit-delivery-notice/import/history/template`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 上传 */
|
||||||
|
const doUpload = ({ file }) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
].includes(file.type)
|
||||||
|
) {
|
||||||
|
message.error('只能选择 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
importCreditDeliveryNoticeHistory(file, props.companyId)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 更新 visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-delivery-notice"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -152,13 +153,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -209,8 +210,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-external" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -82,6 +83,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { exportCreditData } from '../utils/export';
|
import { exportCreditData } from '../utils/export';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditExternalEdit from './components/creditExternalEdit.vue';
|
import CreditExternalEdit from './components/creditExternalEdit.vue';
|
||||||
@@ -225,6 +227,7 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditFinalVersionHistory(file)
|
importCreditFinalVersionHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-final-version"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史终本案件</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -65,15 +60,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditFinalVersionImport v-model:visible="showImport" @done="reload" />
|
<CreditFinalVersionImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditFinalVersionHistoryImport v-model:visible="showImport2" @done="reload" />
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -85,7 +78,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditFinalVersionEdit from './components/creditFinalVersionEdit.vue';
|
import CreditFinalVersionEdit from './components/creditFinalVersionEdit.vue';
|
||||||
import CreditFinalVersionImport from './components/credit-final-version-import.vue';
|
import CreditFinalVersionImport from './components/credit-final-version-import.vue';
|
||||||
import CreditFinalVersionHistoryImport from './components/credit-final-version-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditFinalVersion,
|
pageCreditFinalVersion,
|
||||||
listCreditFinalVersion,
|
listCreditFinalVersion,
|
||||||
@@ -108,8 +100,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -155,23 +145,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'dataType',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'dataType'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'dataType',
|
dataIndex: 'appellee',
|
||||||
key: 'dataType'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
dataIndex: 'dataType',
|
dataIndex: 'otherPartiesThirdParty',
|
||||||
key: 'dataType'
|
key: 'otherPartiesThirdParty'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '发生时间',
|
title: '发生时间',
|
||||||
dataIndex: 'occurrenceTime',
|
dataIndex: 'finalDate',
|
||||||
key: 'occurrenceTime',
|
key: 'finalDate',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -242,8 +232,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -280,11 +271,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditFinalVersion>({
|
exportCreditData<CreditFinalVersion>({
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditGqdjHistory(file)
|
importCreditGqdjHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-gqdj"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -23,12 +24,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史股权冻结</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -38,10 +33,16 @@
|
|||||||
<template v-if="column.key === 'image'">
|
<template v-if="column.key === 'image'">
|
||||||
<a-image :src="record.image" :width="50" />
|
<a-image :src="record.image" :width="50" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'appellee'">
|
||||||
|
{{ record.appellee2 ? record.appellee2 : record.appellee }}
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'dataType'">
|
||||||
|
{{ record.dataType }}
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'action'">
|
<template v-if="column.key === 'action'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a @click="openEdit(record)">修改</a>
|
<a @click="openEdit(record)">修改</a>
|
||||||
@@ -62,15 +63,13 @@
|
|||||||
<CreditGqdjEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
<CreditGqdjEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditGqdjImport v-model:visible="showImport" @done="reload" />
|
<CreditGqdjImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditGqdjHistoryImport v-model:visible="showImport2" @done="reload" />
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -82,7 +81,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditGqdjEdit from './components/creditGqdjEdit.vue';
|
import CreditGqdjEdit from './components/creditGqdjEdit.vue';
|
||||||
import CreditGqdjImport from './components/credit-gqdj-import.vue';
|
import CreditGqdjImport from './components/credit-gqdj-import.vue';
|
||||||
import CreditGqdjHistoryImport from './components/credit-gqdj-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditGqdj,
|
pageCreditGqdj,
|
||||||
listCreditGqdj,
|
listCreditGqdj,
|
||||||
@@ -105,8 +103,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -157,13 +153,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '冻结股权标的企业',
|
title: '冻结股权标的企业',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被执行人',
|
title: '被执行人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '执行法院',
|
title: '执行法院',
|
||||||
@@ -187,18 +183,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '冻结结束日期',
|
title: '冻结结束日期',
|
||||||
dataIndex: 'freezeDateStart',
|
dataIndex: 'freezeDateEnd',
|
||||||
key: 'freezeDateStart'
|
key: 'freezeDateEnd'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'status',
|
dataIndex: 'dataStatus',
|
||||||
key: 'status'
|
key: 'dataStatus'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '数据状态',
|
title: '数据状态',
|
||||||
dataIndex: 'dataStatus',
|
dataIndex: 'dataType',
|
||||||
key: 'dataStatus'
|
key: 'dataType'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作人',
|
title: '操作人',
|
||||||
@@ -214,8 +210,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -252,11 +249,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditGqdj>({
|
exportCreditData<CreditGqdj>({
|
||||||
@@ -266,7 +258,10 @@
|
|||||||
{ title: '执行通知文书号', dataIndex: '执行通知文书号' },
|
{ title: '执行通知文书号', dataIndex: '执行通知文书号' },
|
||||||
{ title: '被执行人', dataIndex: 'appellee' },
|
{ title: '被执行人', dataIndex: 'appellee' },
|
||||||
{ title: '冻结股权标的企业', dataIndex: 'plaintiffAppellant' },
|
{ title: '冻结股权标的企业', dataIndex: 'plaintiffAppellant' },
|
||||||
{ title: '被执行人持有股权、其他投资权益数额', dataIndex: 'involvedAmount' },
|
{
|
||||||
|
title: '被执行人持有股权、其他投资权益数额',
|
||||||
|
dataIndex: 'involvedAmount'
|
||||||
|
},
|
||||||
{ title: '执行法院', dataIndex: 'courtName' },
|
{ title: '执行法院', dataIndex: 'courtName' },
|
||||||
{ title: '类型', dataIndex: 'dataType' },
|
{ title: '类型', dataIndex: 'dataType' },
|
||||||
{ title: '状态', dataIndex: 'dataStatus' },
|
{ title: '状态', dataIndex: 'dataStatus' },
|
||||||
|
|||||||
@@ -188,8 +188,9 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditJudgmentDebtorHistory(file)
|
importCreditJudgmentDebtorHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-judgment-debtor"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史被执行人</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -37,6 +32,12 @@
|
|||||||
<template v-if="column.key === 'image'">
|
<template v-if="column.key === 'image'">
|
||||||
<a-image :src="record.image" :width="50" />
|
<a-image :src="record.image" :width="50" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'appellee'">
|
||||||
|
{{ record.appellee || record.name }}
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'involvedAmount'">
|
||||||
|
{{ record.involvedAmount || record.amount }}
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'caseNumber'">
|
<template v-if="column.key === 'caseNumber'">
|
||||||
<template v-if="record.historyId">
|
<template v-if="record.historyId">
|
||||||
<span class="text-red-500 font-bold">{{
|
<span class="text-red-500 font-bold">{{
|
||||||
@@ -91,21 +92,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditJudgmentDebtorImport v-model:visible="showImport" @done="reload" />
|
<CreditJudgmentDebtorImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史被执行人导入弹窗 -->
|
|
||||||
<CreditJudgmentDebtorHistoryImport
|
|
||||||
v-model:visible="showImport2"
|
|
||||||
@done="reload"
|
|
||||||
/>
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import {
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
CloudUploadOutlined,
|
|
||||||
ExclamationCircleOutlined
|
|
||||||
} from '@ant-design/icons-vue';
|
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -117,7 +110,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditJudgmentDebtorEdit from './components/creditJudgmentDebtorEdit.vue';
|
import CreditJudgmentDebtorEdit from './components/creditJudgmentDebtorEdit.vue';
|
||||||
import CreditJudgmentDebtorImport from './components/credit-judgment-debtor-import.vue';
|
import CreditJudgmentDebtorImport from './components/credit-judgment-debtor-import.vue';
|
||||||
import CreditJudgmentDebtorHistoryImport from './components/credit-judgment-debtor-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditJudgmentDebtor,
|
pageCreditJudgmentDebtor,
|
||||||
listCreditJudgmentDebtor,
|
listCreditJudgmentDebtor,
|
||||||
@@ -141,8 +133,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史被执行人导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -186,25 +176,39 @@
|
|||||||
dataIndex: 'companyName',
|
dataIndex: 'companyName',
|
||||||
key: 'companyName'
|
key: 'companyName'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '原告/上诉人',
|
||||||
|
dataIndex: 'plaintiffAppellant',
|
||||||
|
key: 'plaintiffAppellant',
|
||||||
|
sorter: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '被告/被上诉人',
|
||||||
|
dataIndex: 'appellee',
|
||||||
|
key: 'appellee',
|
||||||
|
sorter: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '其他当事人/第三人',
|
||||||
|
dataIndex: 'otherPartiesThirdParty',
|
||||||
|
key: 'otherPartiesThirdParty',
|
||||||
|
sorter: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '发生时间',
|
||||||
|
dataIndex: 'occurrenceTime',
|
||||||
|
key: 'occurrenceTime',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '案号',
|
title: '案号',
|
||||||
dataIndex: 'caseNumber',
|
dataIndex: 'caseNumber',
|
||||||
key: 'caseNumber'
|
key: 'caseNumber'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被执行人名称',
|
title: '涉案金额',
|
||||||
dataIndex: 'name',
|
dataIndex: 'involvedAmount',
|
||||||
key: 'name'
|
key: 'involvedAmount',
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '证件号/组织机构代码',
|
|
||||||
dataIndex: 'code',
|
|
||||||
key: 'code'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '立案日期',
|
|
||||||
dataIndex: 'occurrenceTime',
|
|
||||||
key: 'occurrenceTime',
|
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -212,12 +216,6 @@
|
|||||||
dataIndex: 'courtName',
|
dataIndex: 'courtName',
|
||||||
key: 'courtName'
|
key: 'courtName'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '执行标的(元)',
|
|
||||||
dataIndex: 'amount',
|
|
||||||
key: 'amount',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '数据状态',
|
title: '数据状态',
|
||||||
dataIndex: 'dataStatus',
|
dataIndex: 'dataStatus',
|
||||||
@@ -239,6 +237,7 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
@@ -277,11 +276,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史被执行人导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditJudgmentDebtor>({
|
exportCreditData<CreditJudgmentDebtor>({
|
||||||
@@ -290,7 +284,6 @@
|
|||||||
{ title: 'ID', dataIndex: 'id' },
|
{ title: 'ID', dataIndex: 'id' },
|
||||||
{ title: '案号', dataIndex: 'caseNumber' },
|
{ title: '案号', dataIndex: 'caseNumber' },
|
||||||
{ title: '被执行人名称', dataIndex: 'name' },
|
{ title: '被执行人名称', dataIndex: 'name' },
|
||||||
{ title: '证件号/组织机构代码', dataIndex: 'code' },
|
|
||||||
{ title: '立案日期', dataIndex: 'occurrenceTime' },
|
{ title: '立案日期', dataIndex: 'occurrenceTime' },
|
||||||
{ title: '执行标的(元)', dataIndex: 'amount' },
|
{ title: '执行标的(元)', dataIndex: 'amount' },
|
||||||
{ title: '法院', dataIndex: 'courtName' },
|
{ title: '法院', dataIndex: 'courtName' },
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditJudicialDocumentHistory(file)
|
importCreditJudicialDocumentHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-judicial-document"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -23,12 +24,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">导入历史裁判文书</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -66,18 +61,13 @@
|
|||||||
/>
|
/>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditJudicialDocumentImport v-model:visible="showImport" @done="reload" />
|
<CreditJudicialDocumentImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditJudicialDocumentHistoryImport
|
|
||||||
v-model:visible="showImport2"
|
|
||||||
@done="reload"
|
|
||||||
/>
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -89,7 +79,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditJudicialDocumentEdit from './components/creditJudicialDocumentEdit.vue';
|
import CreditJudicialDocumentEdit from './components/creditJudicialDocumentEdit.vue';
|
||||||
import CreditJudicialDocumentImport from './components/credit-judicial-document-import.vue';
|
import CreditJudicialDocumentImport from './components/credit-judicial-document-import.vue';
|
||||||
import CreditJudicialDocumentHistoryImport from './components/credit-judicial-document-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditJudicialDocument,
|
pageCreditJudicialDocument,
|
||||||
listCreditJudicialDocument,
|
listCreditJudicialDocument,
|
||||||
@@ -112,8 +101,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -164,8 +151,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文书类型',
|
title: '文书类型',
|
||||||
dataIndex: 'type',
|
dataIndex: 'documentType',
|
||||||
key: 'type'
|
key: 'documentType'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '当事人',
|
title: '当事人',
|
||||||
@@ -229,8 +216,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -267,11 +255,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditJudicialDocument>({
|
exportCreditData<CreditJudicialDocument>({
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
CreditJudiciary,
|
CreditJudiciary,
|
||||||
CreditJudiciaryParam
|
CreditJudiciaryParam
|
||||||
} from '@/api/credit/creditJudiciary/model';
|
} from '@/api/credit/creditJudiciary/model';
|
||||||
import RefreshCompanyIdButton from "@/views/credit/components/RefreshCompanyIdButton.vue";
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from './components/search.vue';
|
import Search from './components/search.vue';
|
||||||
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditJudiciaryEdit from './components/creditJudiciaryEdit.vue';
|
import CreditJudiciaryEdit from './components/creditJudiciaryEdit.vue';
|
||||||
@@ -206,6 +207,16 @@
|
|||||||
key: 'realName',
|
key: 'realName',
|
||||||
width: 90,
|
width: 90,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<!-- 历史诉前调解导入弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="520"
|
||||||
|
:footer="null"
|
||||||
|
title="历史诉前调解批量导入"
|
||||||
|
:visible="visible"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-upload-dragger
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="doUpload"
|
||||||
|
style="padding: 24px 0; margin-bottom: 16px"
|
||||||
|
>
|
||||||
|
<p class="ant-upload-drag-icon">
|
||||||
|
<cloud-upload-outlined />
|
||||||
|
</p>
|
||||||
|
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||||
|
</a-upload-dragger>
|
||||||
|
</a-spin>
|
||||||
|
<div class="ele-text-center">
|
||||||
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
|
<a :href="templateUrl" download="历史诉前调解导入模板.xlsx">
|
||||||
|
下载导入模板
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { importCreditMediationHistory } from '@/api/credit/creditMediation';
|
||||||
|
import { API_BASE_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 是否打开弹窗
|
||||||
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 导入请求状态
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 模板下载地址,保持与当前接口域名一致
|
||||||
|
const templateUrl = computed(() => {
|
||||||
|
const base = (localStorage.getItem('ApiUrl') || API_BASE_URL || '').replace(
|
||||||
|
/\/$/,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return `${base}/credit/credit-mediation/import/history/template`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 上传 */
|
||||||
|
const doUpload = ({ file }) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
].includes(file.type)
|
||||||
|
) {
|
||||||
|
message.error('只能选择 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
importCreditMediationHistory(file, props.companyId)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 更新 visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-mediation"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -144,13 +145,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -201,8 +202,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -0,0 +1,391 @@
|
|||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="800"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:maxable="maxable"
|
||||||
|
:title="isUpdate ? '编辑小程序端客户' : '添加小程序端客户'"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
@ok="save"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||||
|
:wrapper-col="
|
||||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a-form-item label="拖欠方" name="toUser">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入拖欠方"
|
||||||
|
v-model:value="form.toUser"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="拖欠金额" name="price">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入拖欠金额"
|
||||||
|
v-model:value="form.price"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="拖欠年数" name="years">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入拖欠年数"
|
||||||
|
v-model:value="form.years"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="状态" name="statusTxt">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入状态"-->
|
||||||
|
<!-- v-model:value="form.statusTxt"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<!-- <a-form-item label="企业ID" name="companyId">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入企业ID"-->
|
||||||
|
<!-- v-model:value="form.companyId"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<!-- <a-form-item label="所在省份" name="province">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入所在省份"-->
|
||||||
|
<!-- v-model:value="form.province"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="所在城市" name="city">
|
||||||
|
<RegionsSelect
|
||||||
|
v-model:value="regions"
|
||||||
|
type="provinceCity"
|
||||||
|
valueField="label"
|
||||||
|
placeholder="请选择省/市"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="步骤" name="step">
|
||||||
|
<a-select v-model:value="form.step" placeholder="请选择步骤" allow-clear>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stepOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="所在辖区" name="region">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入所在辖区"-->
|
||||||
|
<!-- v-model:value="form.region"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="文件路径" name="files">
|
||||||
|
<SelectFile
|
||||||
|
:data="fileList"
|
||||||
|
:limit="9"
|
||||||
|
placeholder="请选择附件"
|
||||||
|
@done="onFileChoose"
|
||||||
|
@del="onFileDelete"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="是否有数据" name="hasData">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入是否有数据"-->
|
||||||
|
<!-- v-model:value="form.hasData"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入描述"
|
||||||
|
v-model:value="form.comments"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="是否推荐" name="recommend">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入是否推荐"-->
|
||||||
|
<!-- v-model:value="form.recommend"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="排序" name="sortNumber">
|
||||||
|
<a-input-number
|
||||||
|
:min="0"
|
||||||
|
:max="9999"
|
||||||
|
class="ele-fluid"
|
||||||
|
placeholder="请输入排序号"
|
||||||
|
v-model:value="form.sortNumber"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="状态, 0正常, 1冻结" name="status">-->
|
||||||
|
<!-- <a-radio-group v-model:value="form.status">-->
|
||||||
|
<!-- <a-radio :value="0">显示</a-radio>-->
|
||||||
|
<!-- <a-radio :value="1">隐藏</a-radio>-->
|
||||||
|
<!-- </a-radio-group>-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
</a-form>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { assignObject, uuid } from 'ele-admin-pro';
|
||||||
|
import { addCreditMpCustomer, updateCreditMpCustomer } from '@/api/credit/creditMpCustomer';
|
||||||
|
import { CreditMpCustomer } from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { FormInstance } from 'ant-design-vue/es/form';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
import RegionsSelect from '@/components/RegionsSelect/index.vue';
|
||||||
|
import SelectFile from '@/components/SelectFile/index.vue';
|
||||||
|
import { isImage, stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
// 是否是修改
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
// 是否开启响应式布局
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const { styleResponsive } = storeToRefs(themeStore);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 弹窗是否打开
|
||||||
|
visible: boolean;
|
||||||
|
// 修改回显的数据
|
||||||
|
data?: CreditMpCustomer | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const loading = ref(false);
|
||||||
|
// 是否显示最大化切换按钮
|
||||||
|
const maxable = ref(true);
|
||||||
|
// 表格选中数据
|
||||||
|
const formRef = ref<FormInstance | null>(null);
|
||||||
|
const regions = ref<string[]>();
|
||||||
|
const fileList = ref<any[]>([]);
|
||||||
|
|
||||||
|
const stepOptions = [
|
||||||
|
{ value: 0, text: '未受理' },
|
||||||
|
{ value: 1, text: '已受理' },
|
||||||
|
{ value: 2, text: '材料提交' },
|
||||||
|
{ value: 3, text: '合同签订' },
|
||||||
|
{ value: 4, text: '执行回款' },
|
||||||
|
{ value: 5, text: '完结' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 用户信息
|
||||||
|
const form = reactive<CreditMpCustomer>({
|
||||||
|
id: undefined,
|
||||||
|
toUser: undefined,
|
||||||
|
price: undefined,
|
||||||
|
years: undefined,
|
||||||
|
url: undefined,
|
||||||
|
statusTxt: undefined,
|
||||||
|
companyId: undefined,
|
||||||
|
province: undefined,
|
||||||
|
city: undefined,
|
||||||
|
region: undefined,
|
||||||
|
files: undefined,
|
||||||
|
step: 0,
|
||||||
|
hasData: undefined,
|
||||||
|
recommend: undefined,
|
||||||
|
status: undefined,
|
||||||
|
deleted: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
tenantId: undefined,
|
||||||
|
createTime: undefined,
|
||||||
|
updateTime: undefined,
|
||||||
|
comments: '',
|
||||||
|
sortNumber: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
creditMpCustomerName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请填写小程序端客户名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
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 normalizeFiles = (raw: unknown) => {
|
||||||
|
if (!raw) return [];
|
||||||
|
if (Array.isArray(raw)) {
|
||||||
|
return raw
|
||||||
|
.map((item: any) => {
|
||||||
|
if (!item) return null;
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
const url = isImage(item) ? item : stripOssImageProcess(item);
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
thumbnail: url,
|
||||||
|
isImage: isImage(url)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url =
|
||||||
|
rawUrl && typeof rawUrl === 'string'
|
||||||
|
? isImage(rawUrl)
|
||||||
|
? rawUrl
|
||||||
|
: stripOssImageProcess(rawUrl)
|
||||||
|
: undefined;
|
||||||
|
if (!url) return null;
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
name: typeof item.name === 'string' ? item.name : guessNameFromUrl(url),
|
||||||
|
thumbnail: typeof item.thumbnail === 'string' ? item.thumbnail : undefined,
|
||||||
|
isImage: typeof item.isImage === 'boolean' ? item.isImage : isImage(url)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
if (typeof raw === 'string') {
|
||||||
|
const text = raw.trim();
|
||||||
|
if (!text) return [];
|
||||||
|
try {
|
||||||
|
let parsed: any = JSON.parse(text);
|
||||||
|
if (typeof parsed === 'string') parsed = JSON.parse(parsed);
|
||||||
|
if (Array.isArray(parsed)) return normalizeFiles(parsed);
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return normalizeFiles(text.includes(',') ? text.split(',') : [text]);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncFilesToForm = () => {
|
||||||
|
const payload = (fileList.value ?? [])
|
||||||
|
.map((f: any) => {
|
||||||
|
const url = f?.url;
|
||||||
|
if (!url) return null;
|
||||||
|
return {
|
||||||
|
name: f?.name || guessNameFromUrl(url),
|
||||||
|
url,
|
||||||
|
thumbnail: f?.thumbnail,
|
||||||
|
isImage: typeof f?.isImage === 'boolean' ? f.isImage : isImage(url)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
form.files = payload.length ? JSON.stringify(payload) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFileChoose = (data: FileRecord) => {
|
||||||
|
const rawUrl = data.url || data.downloadUrl || data.path;
|
||||||
|
const url = rawUrl ? (isImage(rawUrl) ? rawUrl : stripOssImageProcess(rawUrl)) : undefined;
|
||||||
|
if (!url) return;
|
||||||
|
const exists = fileList.value.some((d: any) => d?.url === url);
|
||||||
|
if (exists) return;
|
||||||
|
fileList.value.push({
|
||||||
|
url,
|
||||||
|
name: data.name || guessNameFromUrl(url),
|
||||||
|
thumbnail: data.thumbnail,
|
||||||
|
isImage: isImage(url)
|
||||||
|
});
|
||||||
|
syncFilesToForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFileDelete = (index: number) => {
|
||||||
|
fileList.value.splice(index, 1);
|
||||||
|
syncFilesToForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
|
||||||
|
// 级联选择回填到表单字段
|
||||||
|
watch(
|
||||||
|
regions,
|
||||||
|
(val) => {
|
||||||
|
form.province = val?.[0];
|
||||||
|
form.city = val?.[1];
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
/* 保存编辑 */
|
||||||
|
const save = () => {
|
||||||
|
if (!formRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
const formData = {
|
||||||
|
...form
|
||||||
|
};
|
||||||
|
const saveOrUpdate = isUpdate.value ? updateCreditMpCustomer : addCreditMpCustomer;
|
||||||
|
saveOrUpdate(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
regions.value = undefined;
|
||||||
|
fileList.value = [];
|
||||||
|
if (props.data) {
|
||||||
|
assignObject(form, props.data);
|
||||||
|
regions.value = form.province && form.city ? [form.province, form.city] : undefined;
|
||||||
|
fileList.value = normalizeFiles(props.data.files);
|
||||||
|
syncFilesToForm();
|
||||||
|
isUpdate.value = true;
|
||||||
|
} else {
|
||||||
|
isUpdate.value = false;
|
||||||
|
form.step = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetFields();
|
||||||
|
regions.value = undefined;
|
||||||
|
fileList.value = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
120
src/views/credit/creditMpCustomer/components/search.vue
Normal file
120
src/views/credit/creditMpCustomer/components/search.vue
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<!-- 搜索表单 -->
|
||||||
|
<template>
|
||||||
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
|
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
||||||
|
<!-- <template #icon>-->
|
||||||
|
<!-- <PlusOutlined />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <span>添加</span>-->
|
||||||
|
<!-- </a-button>-->
|
||||||
|
<a-button class="ele-btn-icon" @click="exportData">
|
||||||
|
<template #icon>
|
||||||
|
<CloudDownloadOutlined />
|
||||||
|
</template>
|
||||||
|
<span>导出</span>
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
danger
|
||||||
|
class="ele-btn-icon"
|
||||||
|
:disabled="!selection?.length"
|
||||||
|
@click="remove"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</template>
|
||||||
|
<span>批量删除</span>
|
||||||
|
</a-button>
|
||||||
|
<a-select
|
||||||
|
v-model:value="step"
|
||||||
|
allow-clear
|
||||||
|
placeholder="步骤"
|
||||||
|
style="width: 140px"
|
||||||
|
@change="handleSearch"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="item in stepOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input-search
|
||||||
|
allow-clear
|
||||||
|
v-model:value="keywords"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
style="width: 220px"
|
||||||
|
@search="handleSearch"
|
||||||
|
@pressEnter="handleSearch"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import {
|
||||||
|
PlusOutlined,
|
||||||
|
CloudDownloadOutlined,
|
||||||
|
DeleteOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import type {
|
||||||
|
CreditMpCustomer,
|
||||||
|
CreditMpCustomerParam
|
||||||
|
} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
// 选中的角色
|
||||||
|
selection?: CreditMpCustomer[];
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
selection: () => []
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'search', where?: CreditMpCustomerParam): void;
|
||||||
|
(e: 'add'): void;
|
||||||
|
(e: 'remove'): void;
|
||||||
|
(e: 'batchMove'): void;
|
||||||
|
(e: 'exportData'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const keywords = ref('');
|
||||||
|
const step = ref<number | undefined>(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');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
emit('search', { keywords: keywords.value || undefined, step: step.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const exportData = () => {
|
||||||
|
emit('exportData');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
const remove = () => {
|
||||||
|
emit('remove');
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.selection,
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
589
src/views/credit/creditMpCustomer/index.vue
Normal file
589
src/views/credit/creditMpCustomer/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step1/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step1/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step2/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step2/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step3/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step3/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step4/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step4/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step5/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step5/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
589
src/views/credit/creditMpCustomer/step6/index.vue
Normal file
589
src/views/credit/creditMpCustomer/step6/index.vue
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="id"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
v-model:selection="selection"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
@exportData="exportData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'userInfo'">
|
||||||
|
<div class="user-info">
|
||||||
|
<a-avatar :size="42" :src="record.avatar">
|
||||||
|
<template v-if="!record.avatar" #icon>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
<div class="user-details">
|
||||||
|
<h4 class="username">{{ record.nickname }}</h4>
|
||||||
|
<p class="user-phone">{{ record.phone }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50"/>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'files'">
|
||||||
|
<a-space :size="8" style="flex-wrap: wrap">
|
||||||
|
<template v-for="(file, index) in normalizeFiles(record.files)" :key="`${file.url}-${index}`">
|
||||||
|
<a-image
|
||||||
|
v-if="file.isImage"
|
||||||
|
:src="file.thumbnail || file.url"
|
||||||
|
:width="50"
|
||||||
|
:preview="{ src: file.url }"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
|
:href="sanitizeFileUrl(file.url, file.isImage)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ file.name || `附件${index + 1}` }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<span v-if="!normalizeFiles(record.files).length">-</span>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'step'">
|
||||||
|
<a-tag :color="getStepColor(record.step)">
|
||||||
|
{{ getStepText(record.step) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical"/>
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<CreditMpCustomerEdit v-model:visible="showEdit" :data="current" @done="reload"/>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {createVNode, ref, computed} from 'vue';
|
||||||
|
import {message, Modal} from 'ant-design-vue';
|
||||||
|
import {ExclamationCircleOutlined, UserOutlined} from '@ant-design/icons-vue';
|
||||||
|
import type {EleProTable} from 'ele-admin-pro';
|
||||||
|
import {toDateString} from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './../components/search.vue';
|
||||||
|
import {getPageTitle} from '@/utils/common';
|
||||||
|
import CreditMpCustomerEdit from './../components/creditMpCustomerEdit.vue';
|
||||||
|
import {
|
||||||
|
pageCreditMpCustomer,
|
||||||
|
listCreditMpCustomer,
|
||||||
|
removeCreditMpCustomer,
|
||||||
|
removeBatchCreditMpCustomer
|
||||||
|
} from '@/api/credit/creditMpCustomer';
|
||||||
|
import type {CreditMpCustomer, CreditMpCustomerParam} from '@/api/credit/creditMpCustomer/model';
|
||||||
|
import {exportCreditData} from '../../utils/export';
|
||||||
|
import { stripOssImageProcess } from '@/utils/common';
|
||||||
|
|
||||||
|
type NormalizedFile = {
|
||||||
|
name?: string;
|
||||||
|
url: string;
|
||||||
|
thumbnail?: string;
|
||||||
|
isImage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<CreditMpCustomer[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<CreditMpCustomer | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
// 搜索关键词
|
||||||
|
const searchText = ref('');
|
||||||
|
const searchStep = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where = {},
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
const params: CreditMpCustomerParam = {...(where as CreditMpCustomerParam)};
|
||||||
|
if (filters) {
|
||||||
|
const filterStatus = (filters as any).status;
|
||||||
|
if (Array.isArray(filterStatus)) {
|
||||||
|
if (filterStatus.length) {
|
||||||
|
(params as any).status = filterStatus[0];
|
||||||
|
}
|
||||||
|
} else if (filterStatus !== undefined && filterStatus !== null) {
|
||||||
|
(params as any).status = filterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stepFilter = (filters as any).step;
|
||||||
|
if (Array.isArray(stepFilter)) {
|
||||||
|
if (stepFilter.length) {
|
||||||
|
(params as any).step = stepFilter[0];
|
||||||
|
}
|
||||||
|
} else if (stepFilter !== undefined && stepFilter !== null) {
|
||||||
|
(params as any).step = stepFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageCreditMpCustomer({
|
||||||
|
...params,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sanitizeFileUrl = (url: string, isImage: boolean) => {
|
||||||
|
return isImage ? url : (stripOssImageProcess(url) as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filesCache = new Map<string, NormalizedFile[]>();
|
||||||
|
|
||||||
|
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') {
|
||||||
|
const url = sanitizeFileUrl(item, isImageUrl(item));
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
thumbnail: url,
|
||||||
|
name: guessNameFromUrl(url),
|
||||||
|
isImage: isImageUrl(url)
|
||||||
|
} satisfies NormalizedFile;
|
||||||
|
}
|
||||||
|
const rawUrl = item.url || item.path || item.href;
|
||||||
|
const url = typeof rawUrl === 'string' ? rawUrl : undefined;
|
||||||
|
if (!url) 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: sanitizeFileUrl(url, isImage), 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<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userInfo',
|
||||||
|
key: 'userInfo',
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠方',
|
||||||
|
dataIndex: 'toUser',
|
||||||
|
key: 'toUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
key: 'price',
|
||||||
|
width: 120,
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ text }) => '¥' + text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '拖欠年数',
|
||||||
|
dataIndex: 'years',
|
||||||
|
key: 'years',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '链接',
|
||||||
|
// dataIndex: 'url',
|
||||||
|
// key: 'url',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '状态',
|
||||||
|
// dataIndex: 'statusTxt',
|
||||||
|
// key: 'statusTxt'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '所在省份',
|
||||||
|
// dataIndex: 'province',
|
||||||
|
// key: 'province',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '所在城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
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',
|
||||||
|
// key: 'region',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '附件',
|
||||||
|
dataIndex: 'files',
|
||||||
|
key: 'files',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '是否有数据',
|
||||||
|
// dataIndex: 'hasData',
|
||||||
|
// key: 'hasData',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '备注',
|
||||||
|
// dataIndex: 'comments',
|
||||||
|
// key: 'comments',
|
||||||
|
// ellipsis: true
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '是否推荐',
|
||||||
|
// dataIndex: 'recommend',
|
||||||
|
// key: 'recommend',
|
||||||
|
// width: 120
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortNumber',
|
||||||
|
key: 'sortNumber',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
key: 'createTime',
|
||||||
|
width: 200,
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '跟进人',
|
||||||
|
dataIndex: 'realName',
|
||||||
|
key: 'realName',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 默认显示的核心列(最多5个主要字段)
|
||||||
|
const defaultVisibleColumns = [
|
||||||
|
'id',
|
||||||
|
'userInfo',
|
||||||
|
'toUser',
|
||||||
|
'price',
|
||||||
|
'years',
|
||||||
|
'city',
|
||||||
|
'realName',
|
||||||
|
'step',
|
||||||
|
'files',
|
||||||
|
// 'status',
|
||||||
|
'createTime',
|
||||||
|
'action'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据默认可见列过滤显示的列
|
||||||
|
const columns = computed(() => {
|
||||||
|
return allColumns.value.filter(col =>
|
||||||
|
defaultVisibleColumns.includes(col.dataIndex) || col.key === 'action'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: CreditMpCustomerParam) => {
|
||||||
|
if (where && Object.prototype.hasOwnProperty.call(where, 'keywords')) {
|
||||||
|
searchText.value = where.keywords ?? '';
|
||||||
|
}
|
||||||
|
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});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: CreditMpCustomer) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 导出 */
|
||||||
|
const exportData = () => {
|
||||||
|
exportCreditData<CreditMpCustomer>({
|
||||||
|
filename: '小程序端客户列表',
|
||||||
|
includeCompanyName: false,
|
||||||
|
columns: [
|
||||||
|
{title: 'ID', dataIndex: 'id'},
|
||||||
|
{title: '拖欠方', dataIndex: 'toUser'},
|
||||||
|
{title: '拖欠金额', dataIndex: 'price'},
|
||||||
|
{title: '拖欠年数', dataIndex: 'years'},
|
||||||
|
{title: '链接', dataIndex: 'url'},
|
||||||
|
{title: '状态', dataIndex: 'statusTxt'},
|
||||||
|
{title: '所在省份', dataIndex: 'province'},
|
||||||
|
{title: '所在城市', dataIndex: 'city'},
|
||||||
|
{title: '所在辖区', dataIndex: 'region'},
|
||||||
|
{title: '步骤', dataIndex: 'step'},
|
||||||
|
{title: '文件路径', dataIndex: 'files'},
|
||||||
|
{title: '是否有数据', dataIndex: 'hasData'},
|
||||||
|
{title: '备注', dataIndex: 'comments'},
|
||||||
|
{title: '是否推荐', dataIndex: 'recommend'},
|
||||||
|
{title: '排序(数字越小越靠前)', dataIndex: 'sortNumber'},
|
||||||
|
{title: '状态, 0正常, 1冻结', dataIndex: 'status'},
|
||||||
|
{title: '是否删除, 0否, 1是', dataIndex: 'deleted'},
|
||||||
|
{title: '用户ID', dataIndex: 'userId'},
|
||||||
|
{title: '创建时间', dataIndex: 'createTime'},
|
||||||
|
{title: '修改时间', dataIndex: 'updateTime'}
|
||||||
|
],
|
||||||
|
fetchData: () =>
|
||||||
|
listCreditMpCustomer({
|
||||||
|
keywords: searchText.value || undefined,
|
||||||
|
step: searchStep.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: CreditMpCustomer) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeCreditMpCustomer(row.id)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchCreditMpCustomer(selection.value.map((d) => d.id))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: CreditMpCustomer) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CreditMpCustomer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
margin-left: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -8,12 +8,18 @@
|
|||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
:scroll="{ x: 9000 }"
|
:scroll="{ x: 9000 }"
|
||||||
:selection="selection"
|
v-model:selection="selection"
|
||||||
tool-class="ele-toolbar-form"
|
tool-class="ele-toolbar-form"
|
||||||
class="sys-org-table"
|
class="sys-org-table"
|
||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<a-button class="ele-btn-icon" @click="openImport">
|
||||||
|
<template #icon>
|
||||||
|
<CloudUploadOutlined />
|
||||||
|
</template>
|
||||||
|
<span>导入(多)</span>
|
||||||
|
</a-button>
|
||||||
<RefreshCompanyIdButton
|
<RefreshCompanyIdButton
|
||||||
module="credit-nearby-company"
|
module="credit-nearby-company"
|
||||||
@done="reload"
|
@done="reload"
|
||||||
@@ -90,6 +96,7 @@
|
|||||||
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { exportCreditData } from '../utils/export';
|
import { exportCreditData } from '../utils/export';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
import CreditNearbyCompanyEdit from './components/creditNearbyCompanyEdit.vue';
|
import CreditNearbyCompanyEdit from './components/creditNearbyCompanyEdit.vue';
|
||||||
import CreditNearbyCompanyImport from './components/credit-nearby-company-import.vue';
|
import CreditNearbyCompanyImport from './components/credit-nearby-company-import.vue';
|
||||||
import {
|
import {
|
||||||
@@ -213,12 +220,6 @@
|
|||||||
key: 'email',
|
key: 'email',
|
||||||
ellipsis: true
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '邮箱',
|
|
||||||
dataIndex: 'moreEmail',
|
|
||||||
key: 'moreEmail',
|
|
||||||
ellipsis: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '所在国家',
|
title: '所在国家',
|
||||||
dataIndex: 'country',
|
dataIndex: 'country',
|
||||||
@@ -249,98 +250,82 @@
|
|||||||
{
|
{
|
||||||
title: '注册号',
|
title: '注册号',
|
||||||
dataIndex: 'registrationNumber',
|
dataIndex: 'registrationNumber',
|
||||||
key: 'registrationNumber',
|
key: 'registrationNumber'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '组织机构代码',
|
title: '组织机构代码',
|
||||||
dataIndex: 'organizationalCode',
|
dataIndex: 'organizationalCode',
|
||||||
key: 'organizationalCode',
|
key: 'organizationalCode'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '参保人数',
|
title: '参保人数',
|
||||||
dataIndex: 'numberOfInsuredPersons',
|
dataIndex: 'numberOfInsuredPersons',
|
||||||
key: 'numberOfInsuredPersons',
|
key: 'numberOfInsuredPersons'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '参保人数所属年报',
|
title: '参保人数所属年报',
|
||||||
dataIndex: 'annualReport',
|
dataIndex: 'annualReport',
|
||||||
key: 'annualReport',
|
key: 'annualReport'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企业(机构)类型',
|
title: '企业(机构)类型',
|
||||||
dataIndex: 'institutionType',
|
dataIndex: 'institutionType',
|
||||||
key: 'institutionType',
|
key: 'institutionType'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企业规模',
|
title: '企业规模',
|
||||||
dataIndex: 'companySize',
|
dataIndex: 'companySize',
|
||||||
key: 'companySize',
|
key: 'companySize'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '营业期限',
|
title: '营业期限',
|
||||||
dataIndex: 'businessTerm',
|
dataIndex: 'businessTerm',
|
||||||
key: 'businessTerm',
|
key: 'businessTerm'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业门类',
|
title: '国标行业门类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories',
|
dataIndex: 'nationalStandardIndustryCategories',
|
||||||
key: 'nationalStandardIndustryCategories',
|
key: 'nationalStandardIndustryCategories'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业大类',
|
title: '国标行业大类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories2',
|
dataIndex: 'nationalStandardIndustryCategories2',
|
||||||
key: 'nationalStandardIndustryCategories2',
|
key: 'nationalStandardIndustryCategories2'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业中类',
|
title: '国标行业中类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories3',
|
dataIndex: 'nationalStandardIndustryCategories3',
|
||||||
key: 'nationalStandardIndustryCategories3',
|
key: 'nationalStandardIndustryCategories3'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '国标行业小类',
|
title: '国标行业小类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories4',
|
dataIndex: 'nationalStandardIndustryCategories4',
|
||||||
key: 'nationalStandardIndustryCategories4',
|
key: 'nationalStandardIndustryCategories4'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '曾用名',
|
title: '曾用名',
|
||||||
dataIndex: 'formerName',
|
dataIndex: 'formerName',
|
||||||
key: 'formerName',
|
key: 'formerName'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '英文名',
|
title: '英文名',
|
||||||
dataIndex: 'englishName',
|
dataIndex: 'englishName',
|
||||||
key: 'englishName',
|
key: 'englishName'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '官网网址',
|
title: '官网网址',
|
||||||
dataIndex: 'domain',
|
dataIndex: 'domain',
|
||||||
key: 'domain',
|
key: 'domain'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '通信地址',
|
title: '通信地址',
|
||||||
dataIndex: 'mailingAddress',
|
dataIndex: 'mailingAddress',
|
||||||
key: 'mailingAddress',
|
key: 'mailingAddress'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '通信地址邮箱',
|
title: '通信地址邮编',
|
||||||
dataIndex: 'mailingEmail',
|
dataIndex: 'mailingEmail',
|
||||||
key: 'mailingEmail',
|
key: 'mailingEmail'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企业简介',
|
title: '企业简介',
|
||||||
@@ -354,102 +339,53 @@
|
|||||||
key: 'natureOfBusiness',
|
key: 'natureOfBusiness',
|
||||||
ellipsis: true
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '电话',
|
|
||||||
dataIndex: 'tel',
|
|
||||||
key: 'tel',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '企查查行业门类',
|
title: '企查查行业门类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories5',
|
dataIndex: 'nationalStandardIndustryCategories5',
|
||||||
key: 'nationalStandardIndustryCategories5',
|
key: 'nationalStandardIndustryCategories5'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企查查行业大类',
|
title: '企查查行业大类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories6',
|
dataIndex: 'nationalStandardIndustryCategories6',
|
||||||
key: 'nationalStandardIndustryCategories6',
|
key: 'nationalStandardIndustryCategories6'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企查查行业中类',
|
title: '企查查行业中类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories7',
|
dataIndex: 'nationalStandardIndustryCategories7',
|
||||||
key: 'nationalStandardIndustryCategories7',
|
key: 'nationalStandardIndustryCategories7'
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '企查查行业小类',
|
title: '企查查行业小类',
|
||||||
dataIndex: 'nationalStandardIndustryCategories8',
|
dataIndex: 'nationalStandardIndustryCategories8',
|
||||||
key: 'nationalStandardIndustryCategories8',
|
key: 'nationalStandardIndustryCategories8'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '实缴资本',
|
||||||
|
// dataIndex: 'paidinCapital',
|
||||||
|
// key: 'paidinCapital'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '登记机关',
|
||||||
|
// dataIndex: 'registrationAuthority',
|
||||||
|
// key: 'registrationAuthority'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '纳税人资质',
|
||||||
|
// dataIndex: 'taxpayerQualification',
|
||||||
|
// key: 'taxpayerQualification'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '最新年报年份',
|
||||||
|
// dataIndex: 'latestAnnualReportYear',
|
||||||
|
// key: 'latestAnnualReportYear'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '最新年报营业收入',
|
||||||
|
// dataIndex: 'latestAnnualReportOnOperatingRevenue',
|
||||||
|
// key: 'latestAnnualReportOnOperatingRevenue'
|
||||||
|
// },
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '类型',
|
|
||||||
dataIndex: 'type',
|
|
||||||
key: 'type',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '实缴资本',
|
|
||||||
dataIndex: 'paidinCapital',
|
|
||||||
key: 'paidinCapital',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '登记机关',
|
|
||||||
dataIndex: 'registrationAuthority',
|
|
||||||
key: 'registrationAuthority',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '纳税人资质',
|
|
||||||
dataIndex: 'taxpayerQualification',
|
|
||||||
key: 'taxpayerQualification',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '最新年报年份',
|
|
||||||
dataIndex: 'latestAnnualReportYear',
|
|
||||||
key: 'latestAnnualReportYear',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '最新年报营业收入',
|
|
||||||
dataIndex: 'latestAnnualReportOnOperatingRevenue',
|
|
||||||
key: 'latestAnnualReportOnOperatingRevenue',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '企查分',
|
|
||||||
dataIndex: 'enterpriseScoreCheck',
|
|
||||||
key: 'enterpriseScoreCheck',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '信用等级',
|
|
||||||
dataIndex: 'creditRating',
|
|
||||||
key: 'creditRating',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '科创分',
|
|
||||||
dataIndex: 'cechnologyScore',
|
|
||||||
key: 'cechnologyScore',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '科创等级',
|
|
||||||
dataIndex: 'cechnologyLevel',
|
|
||||||
key: 'cechnologyLevel',
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '是否小微企业',
|
|
||||||
dataIndex: 'smallEnterprise',
|
|
||||||
key: 'smallEnterprise',
|
|
||||||
|
|
||||||
},
|
|
||||||
// {
|
// {
|
||||||
// title: '备注',
|
// title: '备注',
|
||||||
// dataIndex: 'comments',
|
// dataIndex: 'comments',
|
||||||
@@ -489,6 +425,7 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -559,10 +496,22 @@
|
|||||||
{ title: '企业(机构)类型', dataIndex: 'institutionType' },
|
{ title: '企业(机构)类型', dataIndex: 'institutionType' },
|
||||||
{ title: '企业规模', dataIndex: 'companySize' },
|
{ title: '企业规模', dataIndex: 'companySize' },
|
||||||
{ title: '营业期限', dataIndex: 'businessTerm' },
|
{ title: '营业期限', dataIndex: 'businessTerm' },
|
||||||
{ title: '国标行业门类', dataIndex: 'nationalStandardIndustryCategories' },
|
{
|
||||||
{ title: '国标行业大类', dataIndex: 'nationalStandardIndustryCategories2' },
|
title: '国标行业门类',
|
||||||
{ title: '国标行业中类', dataIndex: 'nationalStandardIndustryCategories3' },
|
dataIndex: 'nationalStandardIndustryCategories'
|
||||||
{ title: '国标行业小类', dataIndex: 'nationalStandardIndustryCategories4' },
|
},
|
||||||
|
{
|
||||||
|
title: '国标行业大类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '国标行业中类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '国标行业小类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories4'
|
||||||
|
},
|
||||||
{ title: '曾用名', dataIndex: 'formerName' },
|
{ title: '曾用名', dataIndex: 'formerName' },
|
||||||
{ title: '英文名', dataIndex: 'englishName' },
|
{ title: '英文名', dataIndex: 'englishName' },
|
||||||
{ title: '官网网址', dataIndex: 'domain' },
|
{ title: '官网网址', dataIndex: 'domain' },
|
||||||
@@ -570,11 +519,22 @@
|
|||||||
{ title: '通信地址邮箱', dataIndex: 'mailingEmail' },
|
{ title: '通信地址邮箱', dataIndex: 'mailingEmail' },
|
||||||
{ title: '企业简介', dataIndex: 'companyProfile' },
|
{ title: '企业简介', dataIndex: 'companyProfile' },
|
||||||
{ title: '经营范围', dataIndex: 'natureOfBusiness' },
|
{ title: '经营范围', dataIndex: 'natureOfBusiness' },
|
||||||
{ title: '电话', dataIndex: 'tel' },
|
{
|
||||||
{ title: '企查查行业门类', dataIndex: 'nationalStandardIndustryCategories5' },
|
title: '企查查行业门类',
|
||||||
{ title: '企查查行业大类', dataIndex: 'nationalStandardIndustryCategories6' },
|
dataIndex: 'nationalStandardIndustryCategories5'
|
||||||
{ title: '企查查行业中类', dataIndex: 'nationalStandardIndustryCategories7' },
|
},
|
||||||
{ title: '企查查行业小类', dataIndex: 'nationalStandardIndustryCategories8' },
|
{
|
||||||
|
title: '企查查行业大类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '企查查行业中类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories7'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '企查查行业小类',
|
||||||
|
dataIndex: 'nationalStandardIndustryCategories8'
|
||||||
|
},
|
||||||
{ title: '链接', dataIndex: 'url' },
|
{ title: '链接', dataIndex: 'url' },
|
||||||
{ title: '类型', dataIndex: 'type' },
|
{ title: '类型', dataIndex: 'type' },
|
||||||
{ title: '上级ID', dataIndex: 'parentId' },
|
{ title: '上级ID', dataIndex: 'parentId' },
|
||||||
@@ -582,7 +542,10 @@
|
|||||||
{ title: '登记机关', dataIndex: 'registrationAuthority' },
|
{ title: '登记机关', dataIndex: 'registrationAuthority' },
|
||||||
{ title: '纳税人资质', dataIndex: 'taxpayerQualification' },
|
{ title: '纳税人资质', dataIndex: 'taxpayerQualification' },
|
||||||
{ title: '最新年报年份', dataIndex: 'latestAnnualReportYear' },
|
{ title: '最新年报年份', dataIndex: 'latestAnnualReportYear' },
|
||||||
{ title: '最新年报营业收入', dataIndex: 'latestAnnualReportOnOperatingRevenue' },
|
{
|
||||||
|
title: '最新年报营业收入',
|
||||||
|
dataIndex: 'latestAnnualReportOnOperatingRevenue'
|
||||||
|
},
|
||||||
{ title: '企查分', dataIndex: 'enterpriseScoreCheck' },
|
{ title: '企查分', dataIndex: 'enterpriseScoreCheck' },
|
||||||
{ title: '信用等级', dataIndex: 'creditRating' },
|
{ title: '信用等级', dataIndex: 'creditRating' },
|
||||||
{ title: '科创分', dataIndex: 'cechnologyScore' },
|
{ title: '科创分', dataIndex: 'cechnologyScore' },
|
||||||
|
|||||||
@@ -212,8 +212,9 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-project"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -206,6 +207,7 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-risk-relation" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { exportCreditData } from '../utils/export';
|
import { exportCreditData } from '../utils/export';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditRiskRelationEdit from './components/creditRiskRelationEdit.vue';
|
import CreditRiskRelationEdit from './components/creditRiskRelationEdit.vue';
|
||||||
@@ -186,6 +188,7 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-supplier" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
import Search from '@/views/credit/components/CreditSearchToolbar2.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { exportCreditData } from '../utils/export';
|
import { exportCreditData } from '../utils/export';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditSupplierEdit from './components/creditSupplierEdit.vue';
|
import CreditSupplierEdit from './components/creditSupplierEdit.vue';
|
||||||
@@ -155,7 +157,8 @@
|
|||||||
{
|
{
|
||||||
title: '采购金额(万元)',
|
title: '采购金额(万元)',
|
||||||
dataIndex: 'purchaseAmount',
|
dataIndex: 'purchaseAmount',
|
||||||
key: 'purchaseAmount'
|
key: 'purchaseAmount',
|
||||||
|
sorter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '公开日期',
|
title: '公开日期',
|
||||||
@@ -181,8 +184,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -214,7 +214,7 @@
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
>
|
>
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
|
<RefreshCompanyIdButton module="credit-user" @done="reload" />
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@@ -76,7 +77,9 @@
|
|||||||
DatasourceFunction,
|
DatasourceFunction,
|
||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import Search from './components/search.vue';
|
import Search from './components/search.vue';
|
||||||
|
import RefreshCompanyIdButton from '@/views/credit/components/RefreshCompanyIdButton.vue';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditUserEdit from './components/creditUserEdit.vue';
|
import CreditUserEdit from './components/creditUserEdit.vue';
|
||||||
import CreditUserImport from './components/credit-user-import.vue';
|
import CreditUserImport from './components/credit-user-import.vue';
|
||||||
@@ -210,6 +213,11 @@
|
|||||||
dataIndex: 'winningName',
|
dataIndex: 'winningName',
|
||||||
key: 'winningName'
|
key: 'winningName'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '中标金额',
|
||||||
|
dataIndex: 'winningPrice',
|
||||||
|
key: 'winningPrice'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作人',
|
title: '操作人',
|
||||||
dataIndex: 'realName',
|
dataIndex: 'realName',
|
||||||
@@ -217,11 +225,6 @@
|
|||||||
width: 90,
|
width: 90,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '中标金额',
|
|
||||||
dataIndex: 'winningPrice',
|
|
||||||
key: 'winningPrice'
|
|
||||||
},
|
|
||||||
// {
|
// {
|
||||||
// title: '排序',
|
// title: '排序',
|
||||||
// dataIndex: 'sortNumber',
|
// dataIndex: 'sortNumber',
|
||||||
@@ -236,16 +239,16 @@
|
|||||||
// width: 120,
|
// width: 120,
|
||||||
// align: 'center'
|
// align: 'center'
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// title: '创建时间',
|
title: '创建时间',
|
||||||
// dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
// key: 'createTime',
|
key: 'createTime',
|
||||||
// width: 200,
|
width: 200,
|
||||||
// align: 'center',
|
align: 'center',
|
||||||
// sorter: true,
|
sorter: true,
|
||||||
// ellipsis: true,
|
ellipsis: true,
|
||||||
// customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
// },
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
// 是否打开弹窗
|
// 是否打开弹窗
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
// 关联企业ID(企业详情下导入时需要)
|
||||||
|
companyId?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 导入请求状态
|
// 导入请求状态
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
importCreditXgxfHistory(file)
|
importCreditXgxfHistory(file, props.companyId)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -93,4 +95,3 @@
|
|||||||
emit('update:visible', value);
|
emit('update:visible', value);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<a-space class="flex">
|
<a-space class="flex">
|
||||||
<search
|
<search
|
||||||
@search="reload"
|
@search="reload"
|
||||||
|
module="credit-xgxf"
|
||||||
:selection="selection"
|
:selection="selection"
|
||||||
@add="openEdit"
|
@add="openEdit"
|
||||||
@remove="removeBatch"
|
@remove="removeBatch"
|
||||||
@@ -22,12 +23,6 @@
|
|||||||
@importData="openImport"
|
@importData="openImport"
|
||||||
@exportData="exportData"
|
@exportData="exportData"
|
||||||
/>
|
/>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport2">
|
|
||||||
<template #icon>
|
|
||||||
<CloudUploadOutlined />
|
|
||||||
</template>
|
|
||||||
<span class="text-red-500">历史限制高消费</span>
|
|
||||||
</a-button>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
@@ -37,6 +32,9 @@
|
|||||||
<template v-if="column.key === 'image'">
|
<template v-if="column.key === 'image'">
|
||||||
<a-image :src="record.image" :width="50" />
|
<a-image :src="record.image" :width="50" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'plaintiffAppellant'">
|
||||||
|
{{ record.plaintiffAppellant || record.dataType }}
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||||
@@ -61,15 +59,13 @@
|
|||||||
<CreditXgxfEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
<CreditXgxfEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<CreditXgxfImport v-model:visible="showImport" @done="reload" />
|
<CreditXgxfImport v-model:visible="showImport" @done="reload" />
|
||||||
<!-- 历史导入弹窗 -->
|
|
||||||
<CreditXgxfHistoryImport v-model:visible="showImport2" @done="reload" />
|
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { createVNode, ref } from 'vue';
|
import { createVNode, ref } from 'vue';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { ExclamationCircleOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import type { EleProTable } from 'ele-admin-pro';
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
import { toDateString } from 'ele-admin-pro';
|
import { toDateString } from 'ele-admin-pro';
|
||||||
import type {
|
import type {
|
||||||
@@ -81,7 +77,6 @@
|
|||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import CreditXgxfEdit from './components/creditXgxfEdit.vue';
|
import CreditXgxfEdit from './components/creditXgxfEdit.vue';
|
||||||
import CreditXgxfImport from './components/credit-xgxf-import.vue';
|
import CreditXgxfImport from './components/credit-xgxf-import.vue';
|
||||||
import CreditXgxfHistoryImport from './components/credit-xgxf-history-import.vue';
|
|
||||||
import {
|
import {
|
||||||
pageCreditXgxf,
|
pageCreditXgxf,
|
||||||
listCreditXgxf,
|
listCreditXgxf,
|
||||||
@@ -104,8 +99,6 @@
|
|||||||
const showEdit = ref(false);
|
const showEdit = ref(false);
|
||||||
// 是否显示导入弹窗
|
// 是否显示导入弹窗
|
||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示历史导入弹窗
|
|
||||||
const showImport2 = ref(false);
|
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -151,13 +144,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '原告/上诉人',
|
title: '原告/上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'plaintiffAppellant',
|
||||||
key: 'plaintiffUser'
|
key: 'plaintiffAppellant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '被告/被上诉人',
|
title: '被告/被上诉人',
|
||||||
dataIndex: 'plaintiffUser',
|
dataIndex: 'appellee',
|
||||||
key: 'plaintiffUser'
|
key: 'appellee'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '其他当事人/第三人',
|
title: '其他当事人/第三人',
|
||||||
@@ -166,8 +159,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '发生时间',
|
title: '发生时间',
|
||||||
dataIndex: 'occurrenceTime',
|
dataIndex: 'releaseDate',
|
||||||
key: 'occurrenceTime'
|
key: 'releaseDate'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '案号',
|
title: '案号',
|
||||||
@@ -175,12 +168,12 @@
|
|||||||
key: 'caseNumber'
|
key: 'caseNumber'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '涉案金额(元)',
|
title: '涉案金额',
|
||||||
dataIndex: 'involvedAmount',
|
dataIndex: 'involvedAmount',
|
||||||
key: 'involvedAmount'
|
key: 'involvedAmount'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '执行法院',
|
title: '法院',
|
||||||
dataIndex: 'courtName',
|
dataIndex: 'courtName',
|
||||||
key: 'courtName'
|
key: 'courtName'
|
||||||
},
|
},
|
||||||
@@ -230,8 +223,9 @@
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: true,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// title: '操作',
|
// title: '操作',
|
||||||
// key: 'action',
|
// key: 'action',
|
||||||
@@ -268,11 +262,6 @@
|
|||||||
showImport.value = true;
|
showImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 打开历史导入弹窗 */
|
|
||||||
const openImport2 = () => {
|
|
||||||
showImport2.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 导出 */
|
/* 导出 */
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
exportCreditData<CreditXgxf>({
|
exportCreditData<CreditXgxf>({
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<!-- 企业导入弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="520"
|
||||||
|
:footer="null"
|
||||||
|
title="企业批量导入"
|
||||||
|
:visible="visible"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-upload-dragger
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="doUpload"
|
||||||
|
style="padding: 24px 0; margin-bottom: 16px"
|
||||||
|
>
|
||||||
|
<p class="ant-upload-drag-icon">
|
||||||
|
<cloud-upload-outlined />
|
||||||
|
</p>
|
||||||
|
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||||
|
</a-upload-dragger>
|
||||||
|
</a-spin>
|
||||||
|
<div class="ele-text-center">
|
||||||
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
|
<a :href="templateUrl" download="企业导入模板.xlsx"> 下载导入模板 </a>
|
||||||
|
</div>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import {importCustomer} from '@/api/credit/creditCompany';
|
||||||
|
import { API_BASE_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
// 是否打开弹窗
|
||||||
|
visible: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 导入请求状态
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 模板下载地址,保持与当前接口域名一致
|
||||||
|
const templateUrl = computed(() => {
|
||||||
|
const base = (localStorage.getItem('ApiUrl') || API_BASE_URL || '').replace(
|
||||||
|
/\/$/,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return `${base}/credit/credit-company/import/template`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 上传 */
|
||||||
|
const doUpload = ({ file }) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
].includes(file.type)
|
||||||
|
) {
|
||||||
|
message.error('只能选择 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
importCustomer(file)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 更新 visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<!-- 企业详情子表导入弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="520"
|
||||||
|
:footer="null"
|
||||||
|
:title="title"
|
||||||
|
:visible="visible"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-upload-dragger
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="doUpload"
|
||||||
|
style="padding: 24px 0; margin-bottom: 16px"
|
||||||
|
>
|
||||||
|
<p class="ant-upload-drag-icon">
|
||||||
|
<cloud-upload-outlined />
|
||||||
|
</p>
|
||||||
|
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||||
|
</a-upload-dragger>
|
||||||
|
</a-spin>
|
||||||
|
<div class="ele-text-center">
|
||||||
|
<span>只能上传xls、xlsx文件,</span>
|
||||||
|
<a :href="templateUrl" :download="`${title}.xlsx`">下载导入模板</a>
|
||||||
|
</div>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { API_BASE_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 是否打开弹窗
|
||||||
|
visible: boolean;
|
||||||
|
// 弹窗标题
|
||||||
|
title: string;
|
||||||
|
// 模板下载相对路径(保持与当前接口域名一致)
|
||||||
|
templatePath: string;
|
||||||
|
// 当前企业ID(用于导入关联)
|
||||||
|
companyId?: number;
|
||||||
|
// 导入方法:必须支持传 companyId
|
||||||
|
importFn: (file: File, companyId?: number) => Promise<string>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 导入请求状态
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const templateUrl = computed(() => {
|
||||||
|
const base = (localStorage.getItem('ApiUrl') || API_BASE_URL || '').replace(
|
||||||
|
/\/$/,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
const path = (props.templatePath || '').startsWith('/')
|
||||||
|
? props.templatePath
|
||||||
|
: `/${props.templatePath}`;
|
||||||
|
return `${base}${path}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 上传 */
|
||||||
|
const doUpload = ({ file }) => {
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
].includes(file.type)
|
||||||
|
) {
|
||||||
|
message.error('只能选择 excel 文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 10) {
|
||||||
|
message.error('大小不能超过 10MB');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!props.companyId) {
|
||||||
|
message.error('缺少企业ID,无法导入');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
props
|
||||||
|
.importFn(file, props.companyId)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 更新 visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
612
src/views/credit/customer/components/creditCompanyEdit.vue
Normal file
612
src/views/credit/customer/components/creditCompanyEdit.vue
Normal file
@@ -0,0 +1,612 @@
|
|||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
width="80%"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:maxable="maxable"
|
||||||
|
:title="isUpdate ? '主体企业信息' : '添加企业'"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
@ok="save"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||||
|
:wrapper-col="
|
||||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a-form-item label="原文件导入名称" name="name">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入原文件导入名称"
|
||||||
|
v-model:value="form.name"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="系统匹配企业名称" name="matchName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入系统匹配企业名称"
|
||||||
|
v-model:value="form.matchName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="统一社会信用代码" name="code">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入统一社会信用代码"
|
||||||
|
v-model:value="form.code"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- <a-form-item label="类型" name="type">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入类型"-->
|
||||||
|
<!-- v-model:value="form.type"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<!-- <a-form-item label="上级id, 0是顶级" name="parentId">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- allow-clear-->
|
||||||
|
<!-- placeholder="请输入上级id, 0是顶级"-->
|
||||||
|
<!-- v-model:value="form.parentId"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="登记状态" name="registrationStatus">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入登记状态"
|
||||||
|
v-model:value="form.registrationStatus"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="法定代表人" name="legalPerson">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入法定代表人"
|
||||||
|
v-model:value="form.legalPerson"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="注册资本" name="registeredCapital">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入注册资本"
|
||||||
|
v-model:value="form.registeredCapital"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="实缴资本" name="paidinCapital">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入实缴资本"
|
||||||
|
v-model:value="form.paidinCapital"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="成立日期" name="establishDate">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入成立日期"
|
||||||
|
v-model:value="form.establishDate"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="企业地址" name="address">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企业地址"
|
||||||
|
v-model:value="form.address"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="电话" name="tel">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入电话"
|
||||||
|
v-model:value="form.tel"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="更多电话" name="moreTel">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入更多电话"
|
||||||
|
v-model:value="form.moreTel"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="邮箱" name="email">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
v-model:value="form.email"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="更多邮箱" name="moreEmail">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入更多邮箱"
|
||||||
|
v-model:value="form.moreEmail"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所在国家" name="country">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入所在国家"
|
||||||
|
v-model:value="form.country"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所属省份" name="province">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入所属省份"
|
||||||
|
v-model:value="form.province"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所属城市" name="city">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入所属城市"
|
||||||
|
v-model:value="form.city"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所属区县" name="region">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入所属区县"
|
||||||
|
v-model:value="form.region"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="企业(机构)类型" name="institutionType">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企业(机构)类型"
|
||||||
|
v-model:value="form.institutionType"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="纳税人识别号" name="taxpayerCode">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入纳税人识别号"
|
||||||
|
v-model:value="form.taxpayerCode"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="注册号" name="registrationNumber">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入注册号"
|
||||||
|
v-model:value="form.registrationNumber"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="组织机构代码" name="organizationalCode">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入组织机构代码"
|
||||||
|
v-model:value="form.organizationalCode"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="参保人数" name="numberOfInsuredPersons">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入参保人数"
|
||||||
|
v-model:value="form.numberOfInsuredPersons"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="参保人数所属年报" name="annualReport">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入参保人数所属年报"
|
||||||
|
v-model:value="form.annualReport"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="营业期限" name="businessTerm">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入营业期限"
|
||||||
|
v-model:value="form.businessTerm"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="国标行业门类"
|
||||||
|
name="nationalStandardIndustryCategories"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入国标行业门类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="国标行业大类"
|
||||||
|
name="nationalStandardIndustryCategories2"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入国标行业大类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories2"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="国标行业中类"
|
||||||
|
name="nationalStandardIndustryCategories3"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入国标行业中类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories3"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="国标行业小类"
|
||||||
|
name="nationalStandardIndustryCategories4"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入国标行业小类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories4"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="企查查行业门类"
|
||||||
|
name="nationalStandardIndustryCategories5"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企查查行业门类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories5"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="企查查行业大类"
|
||||||
|
name="nationalStandardIndustryCategories6"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企查查行业大类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories6"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="企查查行业中类"
|
||||||
|
name="nationalStandardIndustryCategories7"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企查查行业中类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories7"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="企查查行业小类"
|
||||||
|
name="nationalStandardIndustryCategories8"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企查查行业小类"
|
||||||
|
v-model:value="form.nationalStandardIndustryCategories8"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="企业规模" name="companySize">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企业规模"
|
||||||
|
v-model:value="form.companySize"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="曾用名" name="formerName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入曾用名"
|
||||||
|
v-model:value="form.formerName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="英文名" name="englishName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入英文名"
|
||||||
|
v-model:value="form.englishName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="官网" name="domain">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入官网"
|
||||||
|
v-model:value="form.domain"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="通信地址" name="mailingAddress">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入通信地址"
|
||||||
|
v-model:value="form.mailingAddress"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="企业简介" name="companyProfile">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企业简介"
|
||||||
|
v-model:value="form.companyProfile"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="经营范围" name="natureOfBusiness">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入经营范围"
|
||||||
|
v-model:value="form.natureOfBusiness"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="登记机关" name="registrationAuthority">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入登记机关"
|
||||||
|
v-model:value="form.registrationAuthority"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="纳税人资质" name="taxpayerQualification">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入纳税人资质"
|
||||||
|
v-model:value="form.taxpayerQualification"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="最新年报年份" name="latestAnnualReportYear">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入最新年报年份"
|
||||||
|
v-model:value="form.latestAnnualReportYear"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="最新年报营业收入"
|
||||||
|
name="latestAnnualReportOnOperatingRevenue"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入最新年报营业收入"
|
||||||
|
v-model:value="form.latestAnnualReportOnOperatingRevenue"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="企查分" name="enterpriseScoreCheck">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入企查分"
|
||||||
|
v-model:value="form.enterpriseScoreCheck"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="信用等级" name="creditRating">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入信用等级"
|
||||||
|
v-model:value="form.creditRating"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="科创分" name="cechnologyScore">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入科创分"
|
||||||
|
v-model:value="form.cechnologyScore"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="科创等级" name="cechnologyLevel">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入科创等级"
|
||||||
|
v-model:value="form.cechnologyLevel"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="是否小微企业" name="smallEnterprise">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入是否小微企业"
|
||||||
|
v-model:value="form.smallEnterprise"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入描述"
|
||||||
|
v-model:value="form.comments"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="排序" name="sortNumber">
|
||||||
|
<a-input-number
|
||||||
|
:min="0"
|
||||||
|
:max="9999"
|
||||||
|
class="ele-fluid"
|
||||||
|
placeholder="请输入排序号"
|
||||||
|
v-model:value="form.sortNumber"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="状态" name="status">
|
||||||
|
<a-radio-group v-model:value="form.status">
|
||||||
|
<a-radio :value="0">显示</a-radio>
|
||||||
|
<a-radio :value="1">隐藏</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { assignObject, uuid } from 'ele-admin-pro';
|
||||||
|
import {
|
||||||
|
addCreditCompany,
|
||||||
|
updateCreditCompany
|
||||||
|
} from '@/api/credit/creditCompany';
|
||||||
|
import { CreditCompany } from '@/api/credit/creditCompany/model';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
|
import { FormInstance } from 'ant-design-vue/es/form';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
|
||||||
|
// 是否是修改
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
// 是否开启响应式布局
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const { styleResponsive } = storeToRefs(themeStore);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 弹窗是否打开
|
||||||
|
visible: boolean;
|
||||||
|
// 修改回显的数据
|
||||||
|
data?: CreditCompany | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const loading = ref(false);
|
||||||
|
// 是否显示最大化切换按钮
|
||||||
|
const maxable = ref(true);
|
||||||
|
// 表格选中数据
|
||||||
|
const formRef = ref<FormInstance | null>(null);
|
||||||
|
const images = ref<ItemType[]>([]);
|
||||||
|
|
||||||
|
// 用户信息
|
||||||
|
const form = reactive<CreditCompany>({
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
matchName: undefined,
|
||||||
|
code: undefined,
|
||||||
|
type: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
registrationStatus: undefined,
|
||||||
|
legalPerson: undefined,
|
||||||
|
registeredCapital: undefined,
|
||||||
|
paidinCapital: undefined,
|
||||||
|
establishDate: undefined,
|
||||||
|
address: undefined,
|
||||||
|
tel: undefined,
|
||||||
|
moreTel: undefined,
|
||||||
|
email: undefined,
|
||||||
|
moreEmail: undefined,
|
||||||
|
country: undefined,
|
||||||
|
province: undefined,
|
||||||
|
city: undefined,
|
||||||
|
region: undefined,
|
||||||
|
institutionType: undefined,
|
||||||
|
taxpayerCode: undefined,
|
||||||
|
registrationNumber: undefined,
|
||||||
|
organizationalCode: undefined,
|
||||||
|
numberOfInsuredPersons: undefined,
|
||||||
|
annualReport: undefined,
|
||||||
|
businessTerm: undefined,
|
||||||
|
nationalStandardIndustryCategories: undefined,
|
||||||
|
nationalStandardIndustryCategories2: undefined,
|
||||||
|
nationalStandardIndustryCategories3: undefined,
|
||||||
|
nationalStandardIndustryCategories4: undefined,
|
||||||
|
nationalStandardIndustryCategories5: undefined,
|
||||||
|
nationalStandardIndustryCategories6: undefined,
|
||||||
|
nationalStandardIndustryCategories7: undefined,
|
||||||
|
nationalStandardIndustryCategories8: undefined,
|
||||||
|
companySize: undefined,
|
||||||
|
formerName: undefined,
|
||||||
|
englishName: undefined,
|
||||||
|
domain: undefined,
|
||||||
|
mailingAddress: undefined,
|
||||||
|
companyProfile: undefined,
|
||||||
|
natureOfBusiness: undefined,
|
||||||
|
registrationAuthority: undefined,
|
||||||
|
taxpayerQualification: undefined,
|
||||||
|
latestAnnualReportYear: undefined,
|
||||||
|
latestAnnualReportOnOperatingRevenue: undefined,
|
||||||
|
enterpriseScoreCheck: undefined,
|
||||||
|
creditRating: undefined,
|
||||||
|
cechnologyScore: undefined,
|
||||||
|
cechnologyLevel: undefined,
|
||||||
|
smallEnterprise: undefined,
|
||||||
|
recommend: undefined,
|
||||||
|
sortNumber: undefined,
|
||||||
|
deleted: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
tenantId: undefined,
|
||||||
|
createTime: undefined,
|
||||||
|
updateTime: undefined,
|
||||||
|
status: 0,
|
||||||
|
comments: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
creditCompanyName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请填写企业名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const chooseImage = (data: FileRecord) => {
|
||||||
|
images.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
form.image = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteItem = (index: number) => {
|
||||||
|
images.value.splice(index, 1);
|
||||||
|
form.image = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
|
||||||
|
/* 保存编辑 */
|
||||||
|
const save = () => {
|
||||||
|
if (!formRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
const formData = {
|
||||||
|
...form
|
||||||
|
};
|
||||||
|
const saveOrUpdate = isUpdate.value
|
||||||
|
? updateCreditCompany
|
||||||
|
: addCreditCompany;
|
||||||
|
saveOrUpdate(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
images.value = [];
|
||||||
|
if (props.data) {
|
||||||
|
assignObject(form, props.data);
|
||||||
|
isUpdate.value = true;
|
||||||
|
} else {
|
||||||
|
isUpdate.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetFields();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
2139
src/views/credit/customer/components/creditCompanyInfo.vue
Normal file
2139
src/views/credit/customer/components/creditCompanyInfo.vue
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user