Prechádzať zdrojové kódy

修改商户模块,增加支付方式,货币单位,商户费率等

test 10 mesiacov pred
rodič
commit
f86a44b363

+ 396 - 79
build/cool/temp/eps.d.ts

@@ -368,6 +368,10 @@ declare namespace Eps {
 		 * 类型 1-代收 2-下发 3 冲正 4 内充
 		 */
 		type?: number;
+		/**
+		 * 货币单位
+		 */
+		currency?: string;
 		/**
 		 * 金额
 		 */
@@ -488,6 +492,37 @@ declare namespace Eps {
 		[key: string]: any;
 	}
 
+	interface CurrencyEntity {
+		/**
+		 * ID
+		 */
+		id?: number;
+		/**
+		 * 货币
+		 */
+		currency?: string;
+		/**
+		 * 描述
+		 */
+		desc?: string;
+		/**
+		 * icon
+		 */
+		icon?: string;
+		/**
+		 * 创建时间
+		 */
+		createTime?: Date;
+		/**
+		 * 更新时间
+		 */
+		updateTime?: Date;
+		/**
+		 * 任意键值
+		 */
+		[key: string]: any;
+	}
+
 	interface KycEntity {
 		/**
 		 * ID
@@ -539,33 +574,6 @@ declare namespace Eps {
 		[key: string]: any;
 	}
 
-	interface MchBalanceEntity {
-		/**
-		 * ID
-		 */
-		id?: number;
-		/**
-		 * 商户号
-		 */
-		mchId?: string;
-		/**
-		 * 余额
-		 */
-		balance?: number;
-		/**
-		 * 创建时间
-		 */
-		createTime?: Date;
-		/**
-		 * 更新时间
-		 */
-		updateTime?: Date;
-		/**
-		 * 任意键值
-		 */
-		[key: string]: any;
-	}
-
 	interface MerchantEntity {
 		/**
 		 * ID
@@ -584,33 +592,33 @@ declare namespace Eps {
 		 */
 		mchId?: string;
 		/**
-		 * 手续费
+		 * 邮箱
 		 */
-		rate?: number;
+		email?: string;
 		/**
-		 * 代付手续费
+		 * 状态 0-禁用 1-启用
 		 */
-		withdrawRate?: number;
+		status?: number;
 		/**
-		 * 代付单笔固定费用
+		 * 资金密码
 		 */
-		withdrawBasicFee?: number;
+		fundPwd?: string;
 		/**
-		 * 代付单笔最低费用
+		 * MD5Key
 		 */
-		withdrawFeeMin?: number;
+		key?: string;
 		/**
-		 * 状态 0-禁用 1-启用
+		 * secret
 		 */
-		status?: number;
+		secret?: string;
 		/**
-		 * 代付状态 0-禁用 1-启用
+		 * 可用币种
 		 */
-		withdrawStatus?: number;
+		currency?: string;
 		/**
-		 * MD5Key
+		 * IP白名单
 		 */
-		key?: string;
+		whiteIp?: string;
 		/**
 		 * 备注
 		 */
@@ -720,6 +728,123 @@ declare namespace Eps {
 		[key: string]: any;
 	}
 
+	interface PayTypeEntity {
+		/**
+		 * ID
+		 */
+		id?: number;
+		/**
+		 * 支付方式
+		 */
+		payType?: string;
+		/**
+		 * 类型 1-代收 2-代付
+		 */
+		type?: number;
+		/**
+		 * 货币
+		 */
+		currencies?: string;
+		/**
+		 * 描述
+		 */
+		remark?: string;
+		/**
+		 * 创建时间
+		 */
+		createTime?: Date;
+		/**
+		 * 更新时间
+		 */
+		updateTime?: Date;
+		/**
+		 * 任意键值
+		 */
+		[key: string]: any;
+	}
+
+	interface RateEntity {
+		/**
+		 * ID
+		 */
+		id?: number;
+		/**
+		 * 商户号
+		 */
+		mchId?: string;
+		/**
+		 * 货币单位
+		 */
+		currency?: string;
+		/**
+		 * 类型 1-代收 2-代付
+		 */
+		type?: number;
+		/**
+		 * 支付方式
+		 */
+		payType?: string;
+		/**
+		 * 费率
+		 */
+		rate?: number;
+		/**
+		 * 单笔固定费用
+		 */
+		basicFee?: number;
+		/**
+		 * 单笔最低费用
+		 */
+		feeMin?: number;
+		/**
+		 * 创建时间
+		 */
+		createTime?: Date;
+		/**
+		 * 更新时间
+		 */
+		updateTime?: Date;
+		/**
+		 * 任意键值
+		 */
+		[key: string]: any;
+	}
+
+	interface WalletEntity {
+		/**
+		 * ID
+		 */
+		id?: number;
+		/**
+		 * 商户号
+		 */
+		mchId?: string;
+		/**
+		 * 货币单位
+		 */
+		currency?: string;
+		/**
+		 * 余额
+		 */
+		balance?: number;
+		/**
+		 * 冻结中余额
+		 */
+		freeze?: number;
+		/**
+		 * 创建时间
+		 */
+		createTime?: Date;
+		/**
+		 * 更新时间
+		 */
+		updateTime?: Date;
+		/**
+		 * 任意键值
+		 */
+		[key: string]: any;
+	}
+
 	interface WithdrawEntity {
 		/**
 		 * ID
@@ -2006,10 +2131,6 @@ declare namespace Eps {
 	}
 
 	interface DjBalance {
-		/**
-		 * 统计
-		 */
-		summary(data?: any): Promise<any>;
 		/**
 		 * 分页查询
 		 */
@@ -2042,7 +2163,6 @@ declare namespace Eps {
 		 * 权限标识
 		 */
 		permission: {
-			summary: string;
 			page: string;
 			add: string;
 			list: string;
@@ -2054,7 +2174,6 @@ declare namespace Eps {
 		 * 权限状态
 		 */
 		_permission: {
-			summary: boolean;
 			page: boolean;
 			add: boolean;
 			list: boolean;
@@ -2184,9 +2303,17 @@ declare namespace Eps {
 
 	interface DjComm {
 		/**
-		 * 统计
+		 * 商户列表
+		 */
+		getMerchants(data?: any): Promise<any>;
+		/**
+		 * 货币列表
+		 */
+		getCurrency(data?: any): Promise<any>;
+		/**
+		 * 支付类型列表
 		 */
-		queryBalance(data?: any): Promise<any>;
+		getPayTypes(data?: any): Promise<any>;
 		/**
 		 * 统计
 		 */
@@ -2227,7 +2354,9 @@ declare namespace Eps {
 		 * 权限标识
 		 */
 		permission: {
-			queryBalance: string;
+			getMerchants: string;
+			getCurrency: string;
+			getPayTypes: string;
 			dashboard: string;
 			chartData: string;
 			list: string;
@@ -2241,7 +2370,9 @@ declare namespace Eps {
 		 * 权限状态
 		 */
 		_permission: {
-			queryBalance: boolean;
+			getMerchants: boolean;
+			getCurrency: boolean;
+			getPayTypes: boolean;
 			dashboard: boolean;
 			chartData: boolean;
 			list: boolean;
@@ -2257,7 +2388,7 @@ declare namespace Eps {
 		request: Service["request"];
 	}
 
-	interface DjKyc {
+	interface DjCurrency {
 		/**
 		 * 删除
 		 */
@@ -2266,22 +2397,22 @@ declare namespace Eps {
 		 * 修改
 		 */
 		update(data?: any): Promise<any>;
-		/**
-		 * 列表查询
-		 */
-		list(data?: any): Promise<KycEntity[]>;
 		/**
 		 * 单个信息
 		 */
-		info(data?: any): Promise<KycEntity>;
+		info(data?: any): Promise<CurrencyEntity>;
 		/**
 		 * 分页查询
 		 */
 		page(data?: any): Promise<{
 			pagination: { size: number; page: number; total: number };
-			list: KycEntity[];
+			list: CurrencyEntity[];
 			[key: string]: any;
 		}>;
+		/**
+		 * 列表查询
+		 */
+		list(data?: any): Promise<CurrencyEntity[]>;
 		/**
 		 * 新增
 		 */
@@ -2292,9 +2423,9 @@ declare namespace Eps {
 		permission: {
 			delete: string;
 			update: string;
-			list: string;
 			info: string;
 			page: string;
+			list: string;
 			add: string;
 		};
 		/**
@@ -2303,9 +2434,9 @@ declare namespace Eps {
 		_permission: {
 			delete: boolean;
 			update: boolean;
-			list: boolean;
 			info: boolean;
 			page: boolean;
+			list: boolean;
 			add: boolean;
 		};
 		/**
@@ -2314,55 +2445,55 @@ declare namespace Eps {
 		request: Service["request"];
 	}
 
-	interface DjMchBalance {
+	interface DjKyc {
+		/**
+		 * 删除
+		 */
+		delete(data?: any): Promise<any>;
+		/**
+		 * 修改
+		 */
+		update(data?: any): Promise<any>;
 		/**
 		 * 列表查询
 		 */
-		list(data?: any): Promise<MchBalanceEntity[]>;
+		list(data?: any): Promise<KycEntity[]>;
 		/**
 		 * 单个信息
 		 */
-		info(data?: any): Promise<MchBalanceEntity>;
+		info(data?: any): Promise<KycEntity>;
 		/**
-		 * page
+		 * 分页查询
 		 */
 		page(data?: any): Promise<{
 			pagination: { size: number; page: number; total: number };
-			list: MchBalanceEntity[];
+			list: KycEntity[];
 			[key: string]: any;
 		}>;
 		/**
-		 * update
-		 */
-		update(data?: any): Promise<any>;
-		/**
-		 * delete
-		 */
-		delete(data?: any): Promise<any>;
-		/**
-		 * add
+		 * 新增
 		 */
 		add(data?: any): Promise<any>;
 		/**
 		 * 权限标识
 		 */
 		permission: {
+			delete: string;
+			update: string;
 			list: string;
 			info: string;
 			page: string;
-			update: string;
-			delete: string;
 			add: string;
 		};
 		/**
 		 * 权限状态
 		 */
 		_permission: {
+			delete: boolean;
+			update: boolean;
 			list: boolean;
 			info: boolean;
 			page: boolean;
-			update: boolean;
-			delete: boolean;
 			add: boolean;
 		};
 		/**
@@ -2372,6 +2503,14 @@ declare namespace Eps {
 	}
 
 	interface DjMerchant {
+		/**
+		 * 生成谷歌验证码
+		 */
+		createSecret(data?: any): Promise<any>;
+		/**
+		 * 校验谷歌验证码
+		 */
+		validSecret(data?: any): Promise<any>;
 		/**
 		 * 删除
 		 */
@@ -2404,6 +2543,8 @@ declare namespace Eps {
 		 * 权限标识
 		 */
 		permission: {
+			createSecret: string;
+			validSecret: string;
 			delete: string;
 			update: string;
 			info: string;
@@ -2415,6 +2556,8 @@ declare namespace Eps {
 		 * 权限状态
 		 */
 		_permission: {
+			createSecret: boolean;
+			validSecret: boolean;
 			delete: boolean;
 			update: boolean;
 			info: boolean;
@@ -2644,6 +2787,177 @@ declare namespace Eps {
 		request: Service["request"];
 	}
 
+	interface DjPayType {
+		/**
+		 * 删除
+		 */
+		delete(data?: any): Promise<any>;
+		/**
+		 * 修改
+		 */
+		update(data?: any): Promise<any>;
+		/**
+		 * 单个信息
+		 */
+		info(data?: any): Promise<PayTypeEntity>;
+		/**
+		 * 分页查询
+		 */
+		page(data?: any): Promise<{
+			pagination: { size: number; page: number; total: number };
+			list: PayTypeEntity[];
+			[key: string]: any;
+		}>;
+		/**
+		 * 列表查询
+		 */
+		list(data?: any): Promise<PayTypeEntity[]>;
+		/**
+		 * 新增
+		 */
+		add(data?: any): Promise<any>;
+		/**
+		 * 权限标识
+		 */
+		permission: {
+			delete: string;
+			update: string;
+			info: string;
+			page: string;
+			list: string;
+			add: string;
+		};
+		/**
+		 * 权限状态
+		 */
+		_permission: {
+			delete: boolean;
+			update: boolean;
+			info: boolean;
+			page: boolean;
+			list: boolean;
+			add: boolean;
+		};
+		/**
+		 * 请求
+		 */
+		request: Service["request"];
+	}
+
+	interface DjRate {
+		/**
+		 * 删除
+		 */
+		delete(data?: any): Promise<any>;
+		/**
+		 * 修改
+		 */
+		update(data?: any): Promise<any>;
+		/**
+		 * 单个信息
+		 */
+		info(data?: any): Promise<RateEntity>;
+		/**
+		 * 分页查询
+		 */
+		page(data?: any): Promise<{
+			pagination: { size: number; page: number; total: number };
+			list: RateEntity[];
+			[key: string]: any;
+		}>;
+		/**
+		 * 列表查询
+		 */
+		list(data?: any): Promise<RateEntity[]>;
+		/**
+		 * 新增
+		 */
+		add(data?: any): Promise<any>;
+		/**
+		 * 权限标识
+		 */
+		permission: {
+			delete: string;
+			update: string;
+			info: string;
+			page: string;
+			list: string;
+			add: string;
+		};
+		/**
+		 * 权限状态
+		 */
+		_permission: {
+			delete: boolean;
+			update: boolean;
+			info: boolean;
+			page: boolean;
+			list: boolean;
+			add: boolean;
+		};
+		/**
+		 * 请求
+		 */
+		request: Service["request"];
+	}
+
+	interface DjWallet {
+		/**
+		 * 删除
+		 */
+		delete(data?: any): Promise<any>;
+		/**
+		 * 修改
+		 */
+		update(data?: any): Promise<any>;
+		/**
+		 * 单个信息
+		 */
+		info(data?: any): Promise<WalletEntity>;
+		/**
+		 * 分页查询
+		 */
+		page(data?: any): Promise<{
+			pagination: { size: number; page: number; total: number };
+			list: WalletEntity[];
+			[key: string]: any;
+		}>;
+		/**
+		 * 列表查询
+		 */
+		list(data?: any): Promise<WalletEntity[]>;
+		/**
+		 * add
+		 */
+		add(data?: any): Promise<any>;
+		/**
+		 * 权限标识
+		 */
+		permission: {
+			delete: string;
+			update: string;
+			info: string;
+			page: string;
+			list: string;
+			add: string;
+		};
+		/**
+		 * 权限状态
+		 */
+		_permission: {
+			delete: boolean;
+			update: boolean;
+			info: boolean;
+			page: boolean;
+			list: boolean;
+			add: boolean;
+		};
+		/**
+		 * 请求
+		 */
+		request: Service["request"];
+	}
+
 	interface DjWithdraw {
 		/**
 		 * 发起代付
@@ -3126,11 +3440,14 @@ declare namespace Eps {
 			bill: DjBill;
 			channel: DjChannel;
 			comm: DjComm;
+			currency: DjCurrency;
 			kyc: DjKyc;
-			mchBalance: DjMchBalance;
 			merchant: DjMerchant;
 			open: DjOpen;
 			order: DjOrder;
+			payType: DjPayType;
+			rate: DjRate;
+			wallet: DjWallet;
 			withdraw: DjWithdraw;
 			withdrawChannel: DjWithdrawChannel;
 		};

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
build/cool/temp/eps.json


+ 37 - 66
src/modules/dj/views/balance.vue

@@ -1,44 +1,14 @@
 <template>
 	<cl-crud ref="Crud">
-		<el-row class="statistic" :gutter="15" v-permission="{
-			or: [service.dj.balance.permission.summary]
-		}">
-			<el-col :lg="6" :md="12" :xs="24">
-				<el-card shadow="never">
-					<el-statistic title="代收" :value="summary.num1" />
-				</el-card>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<el-card shadow="never">
-					<el-statistic title="下发" :value="summary.num2" />
-				</el-card>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<el-card shadow="never">
-					<el-statistic title="冲正" :value="summary.num3" />
-				</el-card>
-			</el-col>
-			<el-col :lg="6" :md="12" :xs="24">
-				<el-card shadow="never">
-					<el-statistic title="内冲" :value="summary.num4" />
-				</el-card>
-			</el-col>
-		</el-row>
-
 		<cl-row>
-			<cl-filter-group :items="items" :reset-btn="true" />
+			<cl-filter-group :data="filterParam" :items="items" :reset-btn="true" />
 			<cl-export-btn :columns="Table?.columns" />
 		</cl-row>
 
-		<cl-row v-permission="{
-			or: [service.dj.balance.permission.summary]
-		}">
-			<el-tag class="ml-2" effect="light" size="large">商户总余额: {{ summary.num5 }}</el-tag>
-		</cl-row>
-
 		<cl-row>
 			<!-- 数据表格 -->
-			<cl-table ref="Table" :contextMenu="[]" />
+			<cl-table ref="Table">
+			</cl-table>
 		</cl-row>
 
 		<cl-row>
@@ -52,30 +22,32 @@
 <script lang="ts" name="pay-balance" setup>
 import { useCrud, useTable } from "@cool-vue/crud";
 import { useCool } from "/@/cool";
-import { ref } from "vue";
-import { checkPerm } from "/$/base";
+import { ref, onBeforeMount } from "vue";
+const { service, route } = useCool();
 
-const { service } = useCool();
-
-const summary = ref({
-	num1: 0,
-	num2: 0,
-	num3: 0,
-	num4: 0,
-	num5: 0
+const filterParam = ref({
+	mchId: '',
+	currency: ''
 });
 
 const items = ref<ClForm.Item[]>([
 	{
-		label: "订单号",
-		prop: "orderNo",
+		label: "商户号",
+		prop: "mchId",
 		component: {
 			name: "el-input"
 		}
 	},
 	{
-		label: "商户号",
-		prop: "mchId",
+		label: "货币",
+		prop: "currency",
+		component: {
+			name: "el-input"
+		}
+	},
+	{
+		label: "订单号",
+		prop: "orderNo",
 		component: {
 			name: "el-input"
 		}
@@ -128,7 +100,7 @@ const items = ref<ClForm.Item[]>([
 const Table = useTable({
 	autoHeight: false,
 	columns: [
-		{ prop: "orderNo", label: "订单号" },
+		{ prop: "orderNo", label: "订单号", showOverflowTooltip: true },
 		{ prop: "mchId", label: "商户号" },
 		{
 			prop: "type",
@@ -141,6 +113,7 @@ const Table = useTable({
 			]
 		},
 		{ prop: "amount", label: "金额" },
+		{ prop: "currency", label: "货币" },
 		{ prop: "remark", label: "备注", showOverflowTooltip: true },
 		{ prop: "createTime", label: "日期", width: 160 }
 	]
@@ -149,28 +122,19 @@ const Table = useTable({
 // cl-crud
 const Crud = useCrud(
 	{
-		service: service.dj.balance,
-		async onRefresh(params, { next, render }) {
-			const { list, pagination } = await next({
-				order: "createTime",
-				sort: "desc",
-				...params
-			});
-			if (checkPerm(service.dj.balance.permission.summary)) {
-				const { num1, num2, num3, num4, num5 } = await service.dj.balance.summary(params);
-				summary.value.num1 = +num1;
-				summary.value.num2 = +num2;
-				summary.value.num3 = +num3;
-				summary.value.num4 = +num4;
-				summary.value.num5 = +num5;
-				render(list, pagination);
-			}
-		}
+		service: service.dj.balance
 	},
 	(app) => {
-		app.refresh();
+		app.refresh(filterParam.value);
 	}
 );
+
+onBeforeMount(() => {
+	const mchId = route.query.mchId || '';
+	const currency = route.query.currency || '';
+	filterParam.value.mchId = mchId.toString();
+	filterParam.value.currency = currency.toString();
+})
 </script>
 
 <style lang="scss">
@@ -186,4 +150,11 @@ const Crud = useCrud(
 		--el-statistic-content-font-size: 28px;
 	}
 }
+
+.tooltip {
+	max-width: 180px !important;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
 </style>

+ 70 - 0
src/modules/dj/views/currency.vue

@@ -0,0 +1,70 @@
+<template>
+	<cl-crud ref="Crud">
+		<cl-row>
+			<!-- 刷新按钮 -->
+			<cl-refresh-btn />
+			<!-- 新增按钮 -->
+			<cl-add-btn />
+			<!-- 删除按钮 -->
+			<cl-multi-delete-btn />
+			<cl-flex1 />
+			<!-- 关键字搜索 -->
+			<cl-search-key />
+		</cl-row>
+
+		<cl-row>
+			<!-- 数据表格 -->
+			<cl-table ref="Table" />
+		</cl-row>
+
+		<cl-row>
+			<cl-flex1 />
+			<!-- 分页控件 -->
+			<cl-pagination />
+		</cl-row>
+
+		<!-- 新增、编辑 -->
+		<cl-upsert ref="Upsert" />
+	</cl-crud>
+</template>
+
+<script lang="ts" name="dj-currency" setup>
+import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
+import { useCool } from "/@/cool";
+
+const { service } = useCool();
+
+// cl-upsert
+const Upsert = useUpsert({
+	items: [
+		{ prop: "currency", label: "货币", required: true, component: { name: "el-input" } },
+		{
+			prop: "desc",
+			label: "描述",
+			component: { name: "el-input", props: { type: "textarea", rows: 4 } }
+		},
+		{ prop: "icon", label: "icon", component: { name: "cl-upload" } }
+	]
+});
+
+// cl-table
+const Table = useTable({
+	columns: [
+		{ type: "selection" },
+		{ prop: "currency", label: "货币" },
+		{ prop: "desc", label: "描述", showOverflowTooltip: true },
+		{ prop: "icon", label: "icon", component: { name: "cl-image", props: { size: 60 } } },
+		{ type: "op", buttons: ["edit", "delete"] }
+	]
+});
+
+// cl-crud
+const Crud = useCrud(
+	{
+		service: service.dj.currency
+	},
+	(app) => {
+		app.refresh();
+	}
+);
+</script>

+ 45 - 171
src/modules/dj/views/merchant.vue

@@ -14,13 +14,10 @@
 
 		<cl-row>
 			<!-- 数据表格 -->
-			<cl-table ref="Table">
+			<cl-table ref="Table" :contextMenu="[]">
 				<template #slot-info="{ scope }">
 					<el-button text bg type="success" @click="openInfo(scope.row)">商户信息</el-button>
 				</template>
-				<template #slot-balance="{ scope }">
-					<el-button text bg type="warning" @click="toBalance(scope.row)">余额变动</el-button>
-				</template>
 			</cl-table>
 		</cl-row>
 
@@ -38,19 +35,16 @@
 					<el-button type="primary" @click="makeKey()">自动生成</el-button>
 				</div>
 			</template>
+			<template #slot-secret="{ scope }">
+				<div>
+					<el-input v-model="scope.secret" style="width: 84%"></el-input>
+					<el-button type="primary" @click="makeSecret()">自动生成</el-button>
+				</div>
+			</template>
 		</cl-upsert>
 		<cl-dialog title="商户信息" width="600" v-model="visible">
 			<el-input v-model="mchInfo" :rows="15" type="textarea" placeholder="Please input" />
 		</cl-dialog>
-		<cl-form class="form" ref="form">
-			<template #slot-type="{ scope }">
-				<el-radio-group v-model="scope.type" class="ml-4" @change="typeChange">
-					<el-radio label="2" size="large">下发</el-radio>
-					<el-radio label="3" size="large">冲正</el-radio>
-					<el-radio label="4" size="large">内充</el-radio>
-				</el-radio-group>
-			</template>
-		</cl-form>
 	</cl-crud>
 </template>
 
@@ -59,102 +53,8 @@ import { useCrud, useTable, useUpsert, useForm } from "@cool-vue/crud";
 import { useCool } from "/@/cool";
 import md5 from "md5";
 import { ref } from "vue";
-import { ElMessage } from "element-plus";
-
 const { service } = useCool();
 
-const form = useForm();
-
-function typeChange(value: any) {
-	form.value?.setProps("amount", {
-		min: +value === 3 ? -Infinity : 0
-	});
-}
-
-function toBalance(row: any) {
-	form.value?.open({
-		title: "余额变动",
-		width: "700",
-		props: {
-			labelWidth: "120px"
-		},
-		items: [
-			{
-				label: "商户号",
-				prop: "mchId",
-				required: true,
-				component: {
-					name: "el-input",
-					props: {
-						readonly: true
-					}
-				}
-			},
-			{
-				label: "类型",
-				prop: "type",
-				required: true,
-				component: {
-					name: "slot-type"
-				}
-			},
-			{
-				label: "金额",
-				prop: "amount",
-				required: true,
-				component: {
-					name: "el-input-number",
-					props: {
-						style: { width: "200px" },
-						precision: 2,
-						min: 0
-					}
-				}
-			},
-			{
-				label: "备注",
-				prop: "remark",
-				component: {
-					name: "el-input",
-					props: {
-						type: "textarea",
-						rows: 3
-					}
-				}
-			}
-		],
-		form: {
-			mchId: row.mchId,
-			type: "",
-			amount: 0,
-			remark: ""
-		},
-		on: {
-			submit(data, { close, done }) {
-				const payload = {
-					...data
-				};
-				if (+data.type === 2) {
-					payload.amount = -Math.abs(data.amount);
-				} else if (+data.type === 4) {
-					payload.amount = +Math.abs(data.amount);
-				}
-				service.dj.balance
-					.add(payload)
-					.then(() => {
-						ElMessage.success("操作成功,如余额未变化,请稍后刷新");
-						close();
-						Crud.value?.refresh();
-					})
-					.catch((err: any) => {
-						ElMessage.error(err.message);
-						done();
-					});
-			}
-		}
-	});
-}
-
 const visible = ref(false);
 
 const mchInfo = ref("");
@@ -164,7 +64,9 @@ function openInfo(row: any) {
 	mchInfo.value = `
   商户号:  ${row.mchId}
   商户密码:
+  商户资金密码:
   商户密钥: ${row.key}
+  商户谷歌验证码: ${row.secret}
   商户后台: http://157.175.73.225
 
   开发文档地址:https://doc.apipost.net/docs/detail/33d38ea154ee000?target_id=3d3371cff09002
@@ -179,6 +81,11 @@ function makeKey() {
 	Upsert.value?.setForm("key", md5(+new Date()));
 }
 
+async function makeSecret() {
+	const secret = await service.dj.merchant.createSecret();
+	Upsert.value?.setForm("secret", secret);
+}
+
 // cl-upsert
 const Upsert = useUpsert({
 	dialog: {
@@ -204,21 +111,18 @@ const Upsert = useUpsert({
 				span: 12,
 			};
 		},
-		{ prop: "key", label: "密钥", required: true, component: { name: "slot-key" } },
 		{
-			prop: "rate",
-			label: "手续费(%)",
-			component: {
-				name: "el-input-number",
-				props: { style: { width: "200px" }, precision: 2, min: 0 }
-			},
+			prop: "email",
+			label: "邮箱",
 			required: true,
+			component: { name: "el-input" },
 			span: 12,
 		},
+		{ prop: "key", label: "密钥", required: true, component: { name: "slot-key" } },
 		() => {
 			return {
 				prop: "password",
-				label: "密码",
+				label: "登录密码",
 				span: 12,
 				required: Upsert.value?.mode == "add",
 				component: {
@@ -236,28 +140,31 @@ const Upsert = useUpsert({
 				]
 			};
 		},
-		{
-			prop: "status",
-			label: "状态",
-			value: 1,
-			component: {
-				name: "el-radio-group",
-				options: [
-					{
-						label: "开启",
-						value: 1
-					},
+		{ prop: "secret", label: "谷歌验证码", required: true, component: { name: "slot-secret" } },
+		() => {
+			return {
+				prop: "fundPwd",
+				label: "资金密码",
+				span: 12,
+				required: Upsert.value?.mode == "add",
+				component: {
+					name: "el-input",
+					props: {
+						type: "password"
+					}
+				},
+				rules: [
 					{
-						label: "关闭",
-						value: 0
+						min: 6,
+						max: 16,
+						message: "密码长度在 6 到 16 个字符"
 					}
 				]
-			},
-
+			};
 		},
 		{
 			prop: "status",
-			label: "代付状态",
+			label: "状态",
 			value: 1,
 			component: {
 				name: "el-radio-group",
@@ -272,44 +179,18 @@ const Upsert = useUpsert({
 					}
 				]
 			},
-
-		},
-		{
-			prop: "withdrawRate",
-			label: "代付手续费(%)",
-			component: {
-				name: "el-input-number",
-				props: { style: { width: "200px" }, precision: 2, min: 0 }
-			},
-			required: true,
-			span: 12,
-		},
-		{
-			prop: "withdrawBasicFee",
-			label: "单笔固定费用",
-			component: {
-				name: "el-input-number",
-				props: { style: { width: "200px" }, precision: 2, min: 0 }
-			},
-			required: true,
-			span: 12,
 		},
 		{
-			prop: "withdrawFeeMin",
-			label: "单笔最低费用",
-			component: {
-				name: "el-input-number",
-				props: { style: { width: "200px" }, precision: 2, min: 0 }
-			},
-			required: true,
-			span: 12,
+			prop: "whiteIp",
+			label: "IP白名单",
+			component: { name: "el-input", props: { type: "textarea", rows: 4, placeholder: '请输入IP白名单,以英文逗号隔开' } }
 		},
 		{
 			prop: "remark",
 			label: "备注",
 			component: { name: "el-input", props: { type: "textarea", rows: 4 } }
 		}
-	]
+	],
 });
 
 // cl-table
@@ -319,15 +200,7 @@ const Table = useTable({
 		{ type: "selection" },
 		{ prop: "name", label: "商户名" },
 		{ prop: "mchId", label: "商户号" },
-		{ prop: "balance", label: "余额" },
-		{
-			prop: "rate",
-			label: "手续费",
-			formatter(row) {
-				return row.rate + "%";
-			}
-		},
-
+		{ prop: "email", label: "邮箱" },
 		{
 			prop: "status",
 			label: "状态",
@@ -336,9 +209,10 @@ const Table = useTable({
 				name: "cl-switch"
 			}
 		},
+		{ prop: "whiteIp", label: "IP白名单", showOverflowTooltip: true },
 		{ prop: "remark", label: "备注", showOverflowTooltip: true },
 		{ prop: "createTime", label: "创建时间", sortable: "desc", width: 160 },
-		{ type: "op", width: 220, buttons: ["slot-info", "slot-balance", "edit", "delete"] }
+		{ type: "op", width: 300, buttons: ["slot-info", "edit", "delete"] }
 	]
 });
 

+ 3 - 18
src/modules/dj/views/order.vue

@@ -18,21 +18,6 @@
 		<cl-row>
 			<!-- 数据表格 -->
 			<cl-table ref="Table" :contextMenu="[]">
-				<template #column-orderNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.orderNo" placement="top">
-						<div class="tooltip">{{ scope.row.orderNo }}</div>
-					</el-tooltip>
-				</template>
-				<template #column-traceNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.traceNo" placement="top">
-						<div class="tooltip">{{ scope.row.traceNo }}</div>
-					</el-tooltip>
-				</template>
-				<template #column-outOrderNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.outOrderNo" placement="top">
-						<div class="tooltip">{{ scope.row.outOrderNo }}</div>
-					</el-tooltip>
-				</template>
 				<template #column-detail="{ scope }">
 					<div style="padding: 10px;">
 						<el-descriptions border :column="4" class="desc">
@@ -319,9 +304,9 @@ const Table = useTable({
 				prop: "detail"
 			};
 		},
-		{ prop: "orderNo", label: "订单号" },
-		{ prop: "outOrderNo", label: "商户订单号" },
-		{ prop: "traceNo", label: "交易号" },
+		{ prop: "orderNo", label: "订单号", showOverflowTooltip: true },
+		{ prop: "outOrderNo", label: "商户订单号", showOverflowTooltip: true },
+		{ prop: "traceNo", label: "交易号", showOverflowTooltip: true },
 		{ prop: "mchId", label: "商户号" },
 		{ prop: "code", label: "通道编码" },
 		{

+ 125 - 0
src/modules/dj/views/payType.vue

@@ -0,0 +1,125 @@
+<template>
+	<cl-crud ref="Crud">
+		<cl-row>
+			<!-- 刷新按钮 -->
+			<cl-refresh-btn />
+			<!-- 新增按钮 -->
+			<cl-add-btn />
+			<!-- 删除按钮 -->
+			<cl-multi-delete-btn />
+			<cl-flex1 />
+			<!-- 关键字搜索 -->
+			<cl-search-key />
+		</cl-row>
+
+		<cl-row>
+			<!-- 数据表格 -->
+			<cl-table ref="Table" />
+		</cl-row>
+
+		<cl-row>
+			<cl-flex1 />
+			<!-- 分页控件 -->
+			<cl-pagination />
+		</cl-row>
+
+		<!-- 新增、编辑 -->
+		<cl-upsert ref="Upsert" />
+	</cl-crud>
+</template>
+
+<script lang="ts" name="dj-payType" setup>
+import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
+import { useCool } from "/@/cool";
+
+const { service } = useCool();
+
+// cl-upsert
+const Upsert = useUpsert({
+	items: [
+		{
+			prop: "payType",
+			label: "支付方式",
+			component: { name: "el-input" },
+			required: true
+		},
+		{
+			prop: "type",
+			label: "类型",
+			component: {
+				name: "el-radio-group",
+				options: [
+					{ label: "代收", value: 1 },
+					{ label: "代付", value: 2 }
+				]
+			},
+			value: 1,
+			required: true
+		},
+		{
+			prop: "currencies",
+			label: "货币",
+			value: [],
+			component: {
+				name: "el-select",
+				options: [],
+				props: {
+					multiple: true,
+				}
+			}
+		},
+		{
+			prop: "remark",
+			label: "描述",
+			component: { name: "el-input", props: { type: "textarea", rows: 4 } }
+		}
+	],
+	async onOpen(data) {
+		const currencyList = await service.dj.comm.getCurrency();
+		Upsert.value?.setOptions(
+			'currencies',
+			currencyList.map((item: string) => {
+				return {
+					label: item,
+					value: item
+				}
+			})
+		);
+		Upsert.value?.setForm('currencies', data && data.length > 0 ? data.currencies.split(',') : [])
+	},
+	async onSubmit(data, { done, close, next }) {
+		data.currencies = data.currencies.join(',');
+		next(data);
+	},
+});
+
+// cl-table
+const Table = useTable({
+	columns: [
+		{ type: "selection" },
+		{ prop: "payType", label: "支付方式" },
+		{
+			prop: "type",
+			label: "类型",
+			dict: [
+				{ label: "代收", value: 1, color: "#67C23A" },
+				{ label: "代付", value: 2, color: "#4165d7" }
+			]
+		},
+		{ prop: "currencies", label: "货币" },
+		{ prop: "remark", label: "描述", showOverflowTooltip: true },
+		{ prop: "createTime", label: "创建时间", sortable: "desc", width: 160 },
+		{ type: "op", buttons: ["edit", "delete"] }
+	]
+});
+
+// cl-crud
+const Crud = useCrud(
+	{
+		service: service.dj.payType
+	},
+	(app) => {
+		app.refresh();
+	}
+);
+</script>

+ 242 - 0
src/modules/dj/views/rate.vue

@@ -0,0 +1,242 @@
+<template>
+	<cl-crud ref="Crud">
+		<cl-row>
+			<cl-filter-group :items="items" :reset-btn="true" />
+			<cl-add-btn />
+		</cl-row>
+		<cl-row>
+			<!-- 数据表格 -->
+			<cl-table ref="Table" />
+		</cl-row>
+
+		<cl-row>
+			<cl-flex1 />
+			<!-- 分页控件 -->
+			<cl-pagination />
+		</cl-row>
+
+		<!-- 新增、编辑 -->
+		<cl-upsert ref="Upsert" />
+	</cl-crud>
+</template>
+
+<script lang="ts" name="dj-rate" setup>
+import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
+import { useCool } from "/@/cool";
+import { ref } from "vue";
+import { checkPerm } from "/$/base";
+
+const { service } = useCool();
+
+const payTypes = ref([]);
+
+const items = ref<ClForm.Item[]>([
+	{
+		label: "商户号",
+		prop: "mchId",
+		component: {
+			name: "el-input"
+		}
+	},
+	{
+		label: "货币",
+		prop: "currency",
+		component: {
+			name: "el-input"
+		}
+	},
+	{
+		label: "类型",
+		prop: "type",
+		component: {
+			name: "el-select",
+			props: {
+				clearable: true
+			},
+			options: [
+				{
+					label: "代收",
+					value: 1
+				},
+				{
+					label: "代付",
+					value: 2
+				}
+			]
+		}
+	},
+]);
+
+// cl-upsert
+const Upsert = useUpsert({
+	props: {
+		labelWidth: 120
+	},
+	items: [
+		() => {
+			return {
+				prop: "mchId",
+				label: "商户号",
+				required: true,
+				component: {
+					name: "el-select",
+					options: [],
+					props: { disabled: Upsert.value?.mode !== "add" }
+				}
+			}
+		},
+		() => {
+			return {
+				prop: "currency",
+				label: "货币",
+				required: true,
+				component: {
+					name: "el-select",
+					options: [],
+					props: { disabled: Upsert.value?.mode !== "add" }
+				}
+			}
+		},
+		() => {
+			return {
+				prop: "type",
+				label: "类型",
+				component: {
+					name: "el-radio-group",
+					options: [
+						{ label: "代收", value: 1 },
+						{ label: "代付", value: 2 }
+					],
+					props: {
+						disabled: Upsert.value?.mode !== "add",
+						onChange(data) {
+							Upsert.value?.setOptions(
+								'payType',
+								payTypes.value.filter((item: any) => {
+									return +item.type === +data
+								}).map((item: any) => {
+									return {
+										label: item.payType + ' ( ' + item.currencies + ' ) ',
+										value: item.payType
+									}
+								})
+							);
+						}
+					}
+				},
+				value: 1,
+				required: true
+			}
+		},
+		{
+			prop: "payType",
+			label: "支付方式",
+			component: {
+				name: "el-select",
+				options: [],
+			},
+			required: true
+		},
+		{
+			prop: "rate",
+			label: "费率(%)",
+			component: {
+				name: "el-input-number",
+				props: { style: { width: "200px" }, precision: 2, min: 0 },
+			},
+			required: true
+		},
+		{
+			prop: "basicFee",
+			label: "单笔固定费用",
+			required: true,
+			component: {
+				name: "el-input-number",
+				props: { style: { width: "200px" }, precision: 2, min: 0 }
+			}
+		},
+		{
+			prop: "feeMin",
+			label: "单笔最低费用",
+			required: true,
+			component: {
+				name: "el-input-number",
+				props: { style: { width: "200px" }, precision: 2, min: 0 }
+			}
+		},
+	],
+	async onOpen(data) {
+		const currencyList = await service.dj.comm.getCurrency();
+		Upsert.value?.setOptions(
+			'currency',
+			currencyList.map((item: string) => {
+				return {
+					label: item,
+					value: item
+				}
+			})
+		);
+		const merchantList = await service.dj.comm.getMerchants();
+		Upsert.value?.setOptions(
+			'mchId',
+			merchantList.map((item: any) => {
+				return {
+					label: item.name + '(' + item.mchId + ')',
+					value: item.mchId
+				}
+			})
+		);
+		payTypes.value = await service.dj.comm.getPayTypes();
+		Upsert.value?.setOptions(
+			'payType',
+			payTypes.value.filter((item: any) => {
+				return +item.type === +data.type
+			}).map((item: any) => {
+				return {
+					label: item.payType + ' ( ' + item.currencies + ' ) ',
+					value: item.payType
+				}
+			})
+		);
+	}
+});
+
+// cl-table
+const Table = useTable({
+	columns: [
+		{ prop: "mchId", label: "商户号" },
+		{ prop: "currency", label: "货币" },
+		{
+			prop: "type",
+			label: "类型",
+			dict: [
+				{ label: "代收", value: 1, color: "#67C23A" },
+				{ label: "代付", value: 2, color: "#4165d7" }
+			]
+		},
+		{ prop: "payType", label: "支付方式" },
+		{
+			prop: "rate", label: "费率", formatter(row) {
+				return row.rate + "%";
+			}
+		},
+		{ prop: "basicFee", label: "单笔固定费用" },
+		{ prop: "feeMin", label: "单笔最低费用" },
+		{
+			type: "op",
+			buttons: ["edit", "delete"],
+			hidden: !(checkPerm(service.dj.rate.permission.update) || checkPerm(service.dj.rate.permission.delete))
+		}
+	]
+});
+
+// cl-crud
+const Crud = useCrud(
+	{
+		service: service.dj.rate
+	},
+	(app) => {
+		app.refresh();
+	}
+);
+</script>

+ 2 - 2
src/modules/dj/views/test.vue

@@ -82,10 +82,10 @@ function toFormPay() {
   document.write(formText.value);
 }
 
-const key = ref("7bde11c1e5be0fca046f099c4264076e");
+const key = ref("32394ae8b550485c53326f10764f8492");
 
 const defaultForm = {
-  mchId: "test",
+  mchId: "TEST",
   outOrderNo: "",
   notifyUrl: "http://157.175.73.225/api/admin/dj/open/notifyTest",
   returnUrl: "https://www.baidu.com",

+ 2 - 2
src/modules/dj/views/toWithdraw.vue

@@ -75,10 +75,10 @@ function makeKey() {
   form.value.outOrderNo = "TEST" + dayjs().format("YYYYMMDDHHmmss");
 }
 
-const key = ref("7bde11c1e5be0fca046f099c4264076e");
+const key = ref("32394ae8b550485c53326f10764f8492");
 
 const defaultForm = {
-  mchId: "test",
+  mchId: "TEST",
   outOrderNo: "",
   notifyUrl: "http://157.175.73.225/api/admin/dj/open/notifyTest",
   returnUrl: "https://www.baidu.com",

+ 160 - 0
src/modules/dj/views/wallet.vue

@@ -0,0 +1,160 @@
+<template>
+	<cl-crud ref="Crud">
+		<cl-row>
+			<cl-filter-group :items="items" :reset-btn="true" />
+		</cl-row>
+
+
+		<cl-row>
+			<!-- 数据表格 -->
+			<cl-table ref="Table" :contextMenu="[]">
+				<template #slot-info="{ scope }">
+					<el-button type="success" text @click="toInfo(scope.row.mchId, scope.row.currency)">明细</el-button>
+				</template>
+			</cl-table>
+		</cl-row>
+
+		<cl-row>
+			<cl-flex1 />
+			<!-- 分页控件 -->
+			<cl-pagination />
+		</cl-row>
+
+		<!-- 新增、编辑 -->
+		<cl-upsert ref="Upsert">
+			<template #slot-type="{ scope }">
+				<el-radio-group v-model="scope.type" class="ml-4" @change="typeChange">
+					<el-radio label="4" size="large">内充</el-radio>
+					<el-radio label="3" size="large">冲正</el-radio>
+				</el-radio-group>
+			</template>
+		</cl-upsert>
+	</cl-crud>
+</template>
+
+<script lang="ts" name="dj-wallet" setup>
+import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
+import { useCool } from "/@/cool";
+import { ref } from "vue";
+const { router } = useCool();
+
+function toInfo(mchId: any, currency: any) {
+	router.push({ path: '/dj/balance', query: { mchId, currency } });
+}
+
+function typeChange(value: any) {
+	Upsert.value?.setProps("amount", {
+		min: +value === 3 ? -Infinity : 0
+	});
+	if (+value === 4) {
+		Upsert.value?.setForm("amount", Math.abs(Upsert.value?.getForm('amount')));
+	}
+}
+
+const { service } = useCool();
+
+const items = ref<ClForm.Item[]>([
+	{
+		label: "商户号",
+		prop: "mchId",
+		component: {
+			name: "el-input"
+		}
+	},
+	{
+		label: "货币",
+		prop: "currency",
+		component: {
+			name: "el-input"
+		}
+	}
+]);
+
+// cl-upsert
+const Upsert = useUpsert({
+	dialog: {
+		title: "余额变动"
+	},
+	props: {
+		labelWidth: "120px"
+	},
+	items: [
+		{
+			label: "商户号",
+			prop: "mchId",
+			required: true,
+			component: {
+				name: "el-input",
+				props: {
+					readonly: true
+				}
+			}
+		},
+		{
+			prop: "currency",
+			label: "货币",
+			required: true,
+			component: {
+				name: "el-input",
+				props: {
+				}
+			}
+		},
+		{
+			label: "类型",
+			prop: "type",
+			required: true,
+			component: {
+				name: "slot-type"
+			}
+		},
+		{
+			label: "金额",
+			prop: "amount",
+			required: true,
+			component: {
+				name: "el-input-number",
+				props: {
+					style: { width: "200px" },
+					precision: 2,
+					min: 0
+				}
+			}
+		},
+		{
+			label: "备注",
+			prop: "remark",
+			component: {
+				name: "el-input",
+				props: {
+					type: "textarea",
+					rows: 3
+				}
+			}
+		}
+	]
+});
+
+// cl-table
+const Table = useTable({
+	columns: [
+		{ prop: "mchId", label: "商户号", sortable: "custom", },
+		{ prop: "currency", label: "货币", sortable: "custom", },
+		{ prop: "balance", label: "余额", sortable: "custom", },
+		{ prop: "freeze", label: "冻结中余额", sortable: "custom", },
+		{ prop: "updateTime", label: "更新时间", sortable: "custom", width: 160 },
+		{ type: "op", buttons: ["slot-info", "edit", "delete"] }
+
+	]
+});
+
+// cl-crud
+const Crud = useCrud(
+	{
+		service: service.dj.wallet
+	},
+	(app) => {
+		app.refresh();
+	}
+);
+</script>

+ 3 - 18
src/modules/dj/views/withdraw.vue

@@ -18,21 +18,6 @@
 		<cl-row>
 			<!-- 数据表格 -->
 			<cl-table ref="Table" :contextMenu="[]">
-				<template #column-orderNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.orderNo" placement="top">
-						<div class="tooltip">{{ scope.row.orderNo }}</div>
-					</el-tooltip>
-				</template>
-				<template #column-traceNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.traceNo" placement="top">
-						<div class="tooltip">{{ scope.row.traceNo }}</div>
-					</el-tooltip>
-				</template>
-				<template #column-outOrderNo="{ scope }">
-					<el-tooltip class="box-item" effect="dark" :content="scope.row.outOrderNo" placement="top">
-						<div class="tooltip">{{ scope.row.outOrderNo }}</div>
-					</el-tooltip>
-				</template>
 				<template #column-detail="{ scope }">
 					<div style="padding: 10px;">
 						<el-descriptions border :column="4" class="desc">
@@ -328,9 +313,9 @@ const Table = useTable({
 				prop: "detail"
 			};
 		},
-		{ prop: "orderNo", label: "订单号" },
-		{ prop: "outOrderNo", label: "商户订单号" },
-		{ prop: "traceNo", label: "交易号" },
+		{ prop: "orderNo", label: "订单号", showOverflowTooltip: true },
+		{ prop: "outOrderNo", label: "商户订单号", showOverflowTooltip: true },
+		{ prop: "traceNo", label: "交易号", showOverflowTooltip: true },
 		{ prop: "mchId", label: "商户号" },
 		{ prop: "code", label: "通道码" },
 		{

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov