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 = [
|
||||||
'星期日',
|
'星期日',
|
||||||
|
|||||||
@@ -9,17 +9,17 @@
|
|||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<a-button class="ele-btn-icon" @click="openImport">
|
<a-button class="ele-btn-icon" @click="openImport">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudUploadOutlined/>
|
<CloudUploadOutlined />
|
||||||
</template>
|
</template>
|
||||||
<span>导入(多)</span>
|
<span>导入(多)</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button class="ele-btn-icon" @click="exportData">
|
<a-button class="ele-btn-icon" @click="exportData">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudDownloadOutlined/>
|
<CloudDownloadOutlined />
|
||||||
</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"
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
@click="remove"
|
@click="remove"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DeleteOutlined/>
|
<DeleteOutlined />
|
||||||
</template>
|
</template>
|
||||||
<span>批量删除</span>
|
<span>批量删除</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -43,57 +43,59 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, ref} from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import {
|
import {
|
||||||
CloudUploadOutlined,
|
CloudUploadOutlined,
|
||||||
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[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
selection: () => []
|
selection: () => []
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'search', where?: { keywords?: string }): void;
|
(e: 'search', where?: { keywords?: string }): void;
|
||||||
(e: 'add'): void;
|
(e: 'add'): void;
|
||||||
(e: 'remove'): void;
|
(e: 'remove'): void;
|
||||||
(e: 'batchMove'): void;
|
(e: 'batchMove'): void;
|
||||||
(e: 'importData'): void;
|
(e: 'importData'): void;
|
||||||
(e: 'exportData'): void;
|
(e: 'exportData'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const keywords = ref('');
|
const keywords = ref('');
|
||||||
const selection = computed(() => props.selection || []);
|
const selection = computed(() => props.selection || []);
|
||||||
|
|
||||||
// 新增
|
// 搜索
|
||||||
const add = () => {
|
const handleSearch = () => {
|
||||||
emit('add');
|
emit('search', { keywords: keywords.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 搜索
|
// 刷新 companyId 后,保持当前条件并触发父级 reload
|
||||||
const handleSearch = () => {
|
const reload = () => {
|
||||||
emit('search', {keywords: keywords.value});
|
emit('search', { keywords: keywords.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导入
|
// 导入
|
||||||
const openImport = () => {
|
const openImport = () => {
|
||||||
emit('importData');
|
emit('importData');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
const exportData = () => {
|
const exportData = () => {
|
||||||
emit('exportData');
|
emit('exportData');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 批量删除
|
// 批量删除
|
||||||
const remove = () => {
|
const remove = () => {
|
||||||
emit('remove');
|
emit('remove');
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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
@@ -1,12 +1,12 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="10" style="flex-wrap: wrap">
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <PlusOutlined />-->
|
<!-- <PlusOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>添加</span>-->
|
<!-- <span>添加</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<a-button type="primary" class="ele-btn-icon" @click="openImport">
|
<a-button type="primary" class="ele-btn-icon" @click="openImport">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudUploadOutlined />
|
<CloudUploadOutlined />
|
||||||
|
|||||||
@@ -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>({
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="10" style="flex-wrap: wrap">
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <PlusOutlined />-->
|
<!-- <PlusOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>添加</span>-->
|
<!-- <span>添加</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <CloudUploadOutlined />-->
|
<!-- <CloudUploadOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>导入(多)</span>-->
|
<!-- <span>导入(多)</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<a-button class="ele-btn-icon" @click="exportData">
|
<a-button class="ele-btn-icon" @click="exportData">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudDownloadOutlined />
|
<CloudDownloadOutlined />
|
||||||
|
|||||||
@@ -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>({
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="10" style="flex-wrap: wrap">
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <PlusOutlined />-->
|
<!-- <PlusOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>添加</span>-->
|
<!-- <span>添加</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <CloudUploadOutlined />-->
|
<!-- <CloudUploadOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>导入(多)</span>-->
|
<!-- <span>导入(多)</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<a-button class="ele-btn-icon" @click="exportData">
|
<a-button class="ele-btn-icon" @click="exportData">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudDownloadOutlined />
|
<CloudDownloadOutlined />
|
||||||
@@ -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"
|
||||||
@@ -51,14 +57,14 @@
|
|||||||
<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>
|
||||||
<!-- <a @click="openEdit(record)">修改</a>-->
|
<!-- <a @click="openEdit(record)">修改</a>-->
|
||||||
<!-- <a-divider type="vertical" />-->
|
<!-- <a-divider type="vertical" />-->
|
||||||
<!-- <a-popconfirm-->
|
<!-- <a-popconfirm-->
|
||||||
<!-- title="确定要删除此记录吗?"-->
|
<!-- title="确定要删除此记录吗?"-->
|
||||||
<!-- @confirm="remove(record)"-->
|
<!-- @confirm="remove(record)"-->
|
||||||
<!-- >-->
|
<!-- >-->
|
||||||
<!-- <a class="ele-text-danger">删除</a>-->
|
<!-- <a class="ele-text-danger">删除</a>-->
|
||||||
<!-- </a-popconfirm>-->
|
<!-- </a-popconfirm>-->
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@@ -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',
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="10" style="flex-wrap: wrap">
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <PlusOutlined />-->
|
<!-- <PlusOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>添加</span>-->
|
<!-- <span>添加</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
<!-- <a-button class="ele-btn-icon" @click="openImport">-->
|
||||||
<!-- <template #icon>-->
|
<!-- <template #icon>-->
|
||||||
<!-- <CloudUploadOutlined />-->
|
<!-- <CloudUploadOutlined />-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- <span>导入(多)</span>-->
|
<!-- <span>导入(多)</span>-->
|
||||||
<!-- </a-button>-->
|
<!-- </a-button>-->
|
||||||
<a-button class="ele-btn-icon" @click="exportData">
|
<a-button class="ele-btn-icon" @click="exportData">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CloudDownloadOutlined />
|
<CloudDownloadOutlined />
|
||||||
|
|||||||
@@ -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>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user