فهرست منبع

feat:新增配置

叶静 1 هفته پیش
والد
کامیت
03bc75c0a0

+ 286 - 0
doc/dls.json

@@ -0,0 +1,286 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "默认模块",
+    "description": "",
+    "version": "1.0.0"
+  },
+  "tags": [],
+  "paths": {
+    "/agentPaymentType/list": {
+      "get": {
+        "summary": "列表-代收或代付 agent_payment_type_query",
+        "deprecated": false,
+        "description": "",
+        "tags": [],
+        "parameters": [
+          {
+            "name": "paymentType",
+            "in": "query",
+            "description": "通道类型\nPAY :代付\nHARVEST :代收",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "enum": [
+                "PAY",
+                "HARVEST"
+              ]
+            }
+          },
+          {
+            "name": "agentUserId",
+            "in": "query",
+            "description": "代理商id",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int64"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/RListAgentPaymentTypeListVO"
+                },
+                "example": {
+                  "code": 0,
+                  "msg": "",
+                  "data": [
+                    {
+                      "agentPaymentTypeId": 0,
+                      "paymentTypeId": 0,
+                      "channelName": "",
+                      "channelCode": "",
+                      "paymentName": "",
+                      "paymentCode": "",
+                      "status": false,
+                      "feeType": "",
+                      "feeRate": 0,
+                      "feeEvery": 0
+                    }
+                  ]
+                }
+              }
+            },
+            "headers": {}
+          }
+        },
+        "security": [
+          {
+            "bearer": []
+          }
+        ]
+      }
+    },
+    "/agentPaymentType/edit": {
+      "post": {
+        "summary": "编辑配置 agent_payment_type_edit",
+        "deprecated": false,
+        "description": "",
+        "tags": [],
+        "parameters": [],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/EditAgentPaymentROEdit",
+                "description": ""
+              }
+            }
+          }
+        },
+        "responses": {
+          "200": {
+            "description": "",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/R",
+                  "description": "响应信息主体"
+                },
+                "example": {
+                  "ok": false,
+                  "code": null,
+                  "msg": "",
+                  "data": {}
+                }
+              }
+            },
+            "headers": {}
+          }
+        },
+        "security": [
+          {
+            "bearer": []
+          }
+        ]
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "AgentPaymentTypeListVO": {
+        "type": "object",
+        "properties": {
+          "agentPaymentTypeId": {
+            "type": "integer",
+            "description": "配置id",
+            "format": "int64"
+          },
+          "paymentTypeId": {
+            "type": "integer",
+            "description": "支付类型id",
+            "format": "int64"
+          },
+          "channelName": {
+            "type": "string",
+            "description": "通道名称"
+          },
+          "channelCode": {
+            "type": "string",
+            "description": "通道编码"
+          },
+          "paymentName": {
+            "type": "string",
+            "description": "支付类型名称"
+          },
+          "paymentCode": {
+            "type": "string",
+            "description": "支付类型代码"
+          },
+          "status": {
+            "type": "boolean",
+            "description": "启用状态"
+          },
+          "feeType": {
+            "type": "string",
+            "description": "手续费类型",
+            "enum": [
+              "PERCENTAGE",
+              "FIXED",
+              "MIXED"
+            ]
+          },
+          "feeRate": {
+            "type": "number",
+            "description": "手续费比例(百分比)"
+          },
+          "feeEvery": {
+            "type": "number",
+            "description": "手续费固定金额"
+          }
+        }
+      },
+      "RListAgentPaymentTypeListVO": {
+        "type": "object",
+        "properties": {
+          "code": {
+            "type": "integer",
+            "description": "返回标记:成功标记=0,失败标记=1"
+          },
+          "msg": {
+            "type": "string",
+            "description": "返回信息"
+          },
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/AgentPaymentTypeListVO",
+              "description": ""
+            },
+            "description": "数据"
+          }
+        }
+      },
+      "EditAgentPaymentROEdit": {
+        "type": "object",
+        "properties": {
+          "agentPaymentTypeId": {
+            "type": "integer",
+            "description": "配置id",
+            "format": "int64"
+          },
+          "paymentType": {
+            "type": "string",
+            "description": "通道类型",
+            "enum": [
+              "PAY",
+              "HARVEST"
+            ]
+          },
+          "paymentTypeId": {
+            "type": "integer",
+            "description": "支付类型id",
+            "format": "int64"
+          },
+          "agentUserId": {
+            "type": "integer",
+            "description": "代理商id",
+            "format": "int64"
+          },
+          "feeType": {
+            "type": "string",
+            "description": "手续费类型",
+            "enum": [
+              "PERCENTAGE",
+              "FIXED",
+              "MIXED"
+            ]
+          },
+          "feeRate": {
+            "type": "number",
+            "description": "手续费比例(百分比)"
+          },
+          "feeEvery": {
+            "type": "number",
+            "description": "手续费固定金额"
+          },
+          "status": {
+            "type": "boolean",
+            "description": "启用状态"
+          }
+        },
+        "required": [
+          "paymentType",
+          "paymentTypeId",
+          "agentUserId",
+          "feeType",
+          "status"
+        ]
+      },
+      "R": {
+        "type": "object",
+        "properties": {
+          "ok": {
+            "type": "boolean"
+          },
+          "code": {
+            "description": "返回标记:成功标记=0,失败标记=1",
+            "type": "null"
+          },
+          "msg": {
+            "type": "string",
+            "description": "返回信息"
+          },
+          "data": {
+            "type": "object",
+            "properties": {},
+            "description": "数据"
+          }
+        }
+      }
+    },
+    "securitySchemes": {
+      "bearer": {
+        "type": "http",
+        "scheme": "bearer"
+      }
+    }
+  },
+  "servers": [],
+  "security": []
+}

+ 294 - 0
doc/shtd.json

@@ -0,0 +1,294 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "默认模块",
+    "description": "",
+    "version": "1.0.0"
+  },
+  "tags": [],
+  "paths": {
+    "/merchantPaymentType/list": {
+      "get": {
+        "summary": "列表-代收或代付 merchant_payment_type_query",
+        "deprecated": false,
+        "description": "",
+        "tags": [],
+        "parameters": [
+          {
+            "name": "paymentType",
+            "in": "query",
+            "description": "通道类型\nPAY :代付\nHARVEST :代收",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "enum": [
+                "PAY",
+                "HARVEST"
+              ]
+            }
+          },
+          {
+            "name": "merchantUserId",
+            "in": "query",
+            "description": "商户id",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int64"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/RListMerchantPaymentTypeListVO"
+                },
+                "example": {
+                  "code": 0,
+                  "msg": "",
+                  "data": [
+                    {
+                      "merchantPaymentTypeId": 0,
+                      "paymentTypeId": 0,
+                      "channelName": "",
+                      "channelCode": "",
+                      "paymentName": "",
+                      "paymentCode": "",
+                      "status": false,
+                      "agentUserRate": 0,
+                      "merchantUserRate": 0,
+                      "singleMaxAmount": 0,
+                      "singleMinAmount": 0,
+                      "baseSingleMaxAmount": 0,
+                      "baseSingleMinAmount": 0
+                    }
+                  ]
+                }
+              }
+            },
+            "headers": {}
+          }
+        },
+        "security": [
+          {
+            "bearer": []
+          }
+        ]
+      }
+    },
+    "/merchantPaymentType/edit": {
+      "post": {
+        "summary": "编辑配置 merchant_payment_type_edit",
+        "deprecated": false,
+        "description": "",
+        "tags": [],
+        "parameters": [],
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "$ref": "#/components/schemas/EditMerchantPaymentROEdit",
+                "description": ""
+              }
+            }
+          }
+        },
+        "responses": {
+          "200": {
+            "description": "",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/R",
+                  "description": "响应信息主体"
+                },
+                "example": {
+                  "ok": false,
+                  "code": null,
+                  "msg": "",
+                  "data": {}
+                }
+              }
+            },
+            "headers": {}
+          }
+        },
+        "security": [
+          {
+            "bearer": []
+          }
+        ]
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "MerchantPaymentTypeListVO": {
+        "type": "object",
+        "properties": {
+          "merchantPaymentTypeId": {
+            "type": "integer",
+            "description": "配置id",
+            "format": "int64"
+          },
+          "paymentTypeId": {
+            "type": "integer",
+            "description": "支付类型id",
+            "format": "int64"
+          },
+          "channelName": {
+            "type": "string",
+            "description": "通道名称"
+          },
+          "channelCode": {
+            "type": "string",
+            "description": "通道编码"
+          },
+          "paymentName": {
+            "type": "string",
+            "description": "支付类型名称"
+          },
+          "paymentCode": {
+            "type": "string",
+            "description": "支付类型代码"
+          },
+          "status": {
+            "type": "boolean",
+            "description": "启用状态"
+          },
+          "agentUserRate": {
+            "type": "number",
+            "description": "代理商费率"
+          },
+          "merchantUserRate": {
+            "type": "number",
+            "description": "商户费率"
+          },
+          "singleMaxAmount": {
+            "type": "number",
+            "description": "单比最大金额"
+          },
+          "singleMinAmount": {
+            "type": "number",
+            "description": "单比最小金额"
+          },
+          "baseSingleMaxAmount": {
+            "type": "number",
+            "description": "通道单比最大金额"
+          },
+          "baseSingleMinAmount": {
+            "type": "number",
+            "description": "通道单比最小金额"
+          }
+        }
+      },
+      "RListMerchantPaymentTypeListVO": {
+        "type": "object",
+        "properties": {
+          "code": {
+            "type": "integer",
+            "description": "返回标记:成功标记=0,失败标记=1"
+          },
+          "msg": {
+            "type": "string",
+            "description": "返回信息"
+          },
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MerchantPaymentTypeListVO",
+              "description": ""
+            },
+            "description": "数据"
+          }
+        }
+      },
+      "EditMerchantPaymentROEdit": {
+        "type": "object",
+        "properties": {
+          "merchantPaymentTypeId": {
+            "type": "integer",
+            "description": "配置id",
+            "format": "int64"
+          },
+          "paymentType": {
+            "type": "string",
+            "description": "通道类型",
+            "enum": [
+              "PAY",
+              "HARVEST"
+            ]
+          },
+          "paymentTypeId": {
+            "type": "integer",
+            "description": "支付类型id",
+            "format": "int64"
+          },
+          "merchantUserId": {
+            "type": "integer",
+            "description": "商户id",
+            "format": "int64"
+          },
+          "agentUserRate": {
+            "type": "number",
+            "description": "代理商费率"
+          },
+          "merchantUserRate": {
+            "type": "number",
+            "description": "商户费率"
+          },
+          "status": {
+            "type": "boolean",
+            "description": "启用状态"
+          },
+          "singleMaxAmount": {
+            "type": "number",
+            "description": "单比最大金额"
+          },
+          "singleMinAmount": {
+            "type": "number",
+            "description": "单比最小金额"
+          }
+        },
+        "required": [
+          "paymentType",
+          "paymentTypeId",
+          "merchantUserId",
+          "status"
+        ]
+      },
+      "R": {
+        "type": "object",
+        "properties": {
+          "ok": {
+            "type": "boolean"
+          },
+          "code": {
+            "description": "返回标记:成功标记=0,失败标记=1",
+            "type": "null"
+          },
+          "msg": {
+            "type": "string",
+            "description": "返回信息"
+          },
+          "data": {
+            "type": "object",
+            "properties": {},
+            "description": "数据"
+          }
+        }
+      }
+    },
+    "securitySchemes": {
+      "bearer": {
+        "type": "http",
+        "scheme": "bearer"
+      }
+    }
+  },
+  "servers": [],
+  "security": []
+}

+ 23 - 0
src/api/agent/agentUser.ts → src/api/agent/index.ts

@@ -1,5 +1,7 @@
 import request from '/@/utils/request';
 
+// ==================== 代理商用户相关 API ====================
+
 export function fetchList(query?: Object) {
 	return request({
 		url: 'admin/agentUser/page',
@@ -45,3 +47,24 @@ export function changePwd(id: string, data?: Object) {
 		data: data,
 	});
 }
+
+// ==================== 代理商支付通道相关 API ====================
+
+export function fetchAgentPaymentTypeList(agentUserId: string, paymentType: 'PAY' | 'HARVEST') {
+	return request({
+		url: 'admin/agentPaymentType/list',
+		method: 'get',
+		params: {
+			agentUserId,
+			paymentType,
+		},
+	});
+}
+
+export function editAgentPaymentType(obj?: Object) {
+	return request({
+		url: 'admin/agentPaymentType/edit',
+		method: 'post',
+		data: obj,
+	});
+}

+ 23 - 0
src/api/merchant/merchantUser.ts → src/api/merchant/index.ts

@@ -1,5 +1,7 @@
 import request from '/@/utils/request';
 
+// ==================== 商户用户相关 API ====================
+
 export function fetchList(query?: Object) {
 	return request({
 		url: 'admin/merchantUser/page',
@@ -59,3 +61,24 @@ export function resetMd5Key(id: string) {
 		method: 'patch',
 	});
 }
+
+// ==================== 商户支付通道相关 API ====================
+
+export function fetchMerchantPaymentTypeList(merchantUserId: string, paymentType: 'PAY' | 'HARVEST') {
+	return request({
+		url: 'admin/merchantPaymentType/list',
+		method: 'get',
+		params: {
+			merchantUserId,
+			paymentType,
+		},
+	});
+}
+
+export function editMerchantPaymentType(obj?: Object) {
+	return request({
+		url: 'admin/merchantPaymentType/edit',
+		method: 'post',
+		data: obj,
+	});
+}

+ 210 - 0
src/views/agent/list/agentPaymentConfigDialog.vue

@@ -0,0 +1,210 @@
+<template>
+	<el-dialog :close-on-click-modal="false" title="配置代理商支付通道" draggable v-model="visible" width="700px">
+		<el-form :model="formData" :rules="formRules" label-width="140px" ref="formRef" v-loading="formLoading">
+			<!-- 基本信息(只读) -->
+			<el-divider content-position="left">基本信息</el-divider>
+			<el-row :gutter="24">
+				<el-col :span="24" class="mb20">
+					<el-form-item label="通道名称">
+						<el-input v-model="formData.channelName" disabled />
+					</el-form-item>
+				</el-col>
+
+				<el-col :span="24" class="mb20">
+					<el-form-item label="支付类型名称">
+						<el-input v-model="formData.paymentName" disabled />
+					</el-form-item>
+				</el-col>
+			</el-row>
+
+			<!-- 配置信息 -->
+			<el-divider content-position="left">配置信息</el-divider>
+			<el-row :gutter="24">
+				<el-col :span="24" class="mb20">
+					<el-form-item label="启用状态" prop="status">
+						<el-radio-group v-model="formData.status">
+							<el-radio :label="true">启用</el-radio>
+							<el-radio :label="false">禁用</el-radio>
+						</el-radio-group>
+					</el-form-item>
+				</el-col>
+
+				<!-- 代收:只显示费率,固定百分比类型 -->
+				<el-col :span="24" class="mb20" v-if="formData.paymentType === 'HARVEST'">
+					<el-form-item label="费率(%)" prop="feeRate">
+						<el-input-number placeholder="请输入费率" v-model="formData.feeRate" :min="0" :max="100" :precision="2" style="width: 100%" />
+					</el-form-item>
+				</el-col>
+
+				<!-- 代付:显示手续费类型选择 -->
+				<template v-if="formData.paymentType === 'PAY'">
+					<el-col :span="24" class="mb20">
+						<el-form-item label="手续费类型" prop="feeType">
+							<el-radio-group v-model="formData.feeType">
+								<el-radio label="PERCENTAGE">百分比</el-radio>
+								<el-radio label="FIXED">固定</el-radio>
+								<el-radio label="MIXED">百分比+固定</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+
+					<!-- 代付:百分比、百分比+固定 显示手续费比例 -->
+					<el-col :span="24" class="mb20" v-if="formData.feeType === 'PERCENTAGE' || formData.feeType === 'MIXED'">
+						<el-form-item label="手续费比例(%)" prop="feeRate">
+							<el-input-number placeholder="请输入手续费比例" v-model="formData.feeRate" :min="0" :max="100" :precision="2" style="width: 100%" />
+						</el-form-item>
+					</el-col>
+
+					<!-- 代付:固定、百分比+固定 显示手续费固定金额 -->
+					<el-col :span="24" class="mb20" v-if="formData.feeType === 'FIXED' || formData.feeType === 'MIXED'">
+						<el-form-item label="手续费固定金额" prop="feeEvery">
+							<el-input-number placeholder="请输入手续费固定金额" v-model="formData.feeEvery" :min="0" :precision="2" style="width: 100%" />
+						</el-form-item>
+					</el-col>
+				</template>
+			</el-row>
+		</el-form>
+
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">取消</el-button>
+				<el-button @click="handleSubmit" type="primary" :disabled="formLoading">确定</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script lang="ts" name="AgentPaymentConfigDialog" setup>
+import { editAgentPaymentType } from '/@/api/agent';
+import { useMessage } from '/@/hooks/message';
+
+const emit = defineEmits(['refresh']);
+
+// 定义变量
+const visible = ref(false);
+const formLoading = ref(false);
+const formRef = ref();
+
+// 表单数据
+const formData = reactive({
+	agentPaymentTypeId: '',
+	paymentTypeId: '',
+	agentUserId: '',
+	paymentType: '',
+	channelName: '',
+	paymentName: '',
+	status: true,
+	feeType: '',
+	feeRate: 0,
+	feeEvery: 0,
+});
+
+// 表单验证规则
+const formRules = ref({
+	status: [{ required: true, message: '请选择启用状态', trigger: 'change' }],
+	feeType: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 只有代付需要选择手续费类型
+				if (formData.paymentType === 'PAY' && !value) {
+					callback(new Error('请选择手续费类型'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'change',
+		},
+	],
+	feeRate: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 代收:必填费率
+				// 代付:百分比、百分比+固定 需要手续费比例
+				const needFeeRate =
+					formData.paymentType === 'HARVEST' ||
+					(formData.paymentType === 'PAY' && (formData.feeType === 'PERCENTAGE' || formData.feeType === 'MIXED'));
+
+				if (needFeeRate && !value && value !== 0) {
+					callback(new Error(formData.paymentType === 'HARVEST' ? '请输入费率' : '请输入手续费比例'));
+				} else if (value !== undefined && value !== null && (value < 0 || value > 100)) {
+					callback(new Error('费率范围为0-100'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+	feeEvery: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 代付:固定、百分比+固定 需要手续费固定金额
+				const needFeeEvery = formData.paymentType === 'PAY' && (formData.feeType === 'FIXED' || formData.feeType === 'MIXED');
+
+				if (needFeeEvery && !value && value !== 0) {
+					callback(new Error('请输入手续费固定金额'));
+				} else if (value !== undefined && value !== null && value < 0) {
+					callback(new Error('手续费固定金额不能小于0'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+});
+
+// 打开弹窗
+const openDialog = (row: any, agentUserId: string, paymentType: 'PAY' | 'HARVEST') => {
+	visible.value = true;
+
+	// 填充数据
+	formData.agentPaymentTypeId = row.agentPaymentTypeId;
+	formData.paymentTypeId = row.paymentTypeId;
+	formData.agentUserId = agentUserId;
+	formData.paymentType = paymentType;
+	formData.channelName = row.channelName;
+	formData.paymentName = row.paymentName;
+	formData.status = row.status ?? true;
+	formData.feeType = row.feeType || 'PERCENTAGE';
+	formData.feeRate = row.feeRate || 0;
+	formData.feeEvery = row.feeEvery || 0;
+
+	nextTick(() => {
+		formRef.value?.clearValidate();
+	});
+};
+
+// 提交表单
+const handleSubmit = async () => {
+	const valid = await formRef.value.validate().catch(() => {});
+	if (!valid) return false;
+
+	try {
+		formLoading.value = true;
+		const submitData = {
+			agentPaymentTypeId: formData.agentPaymentTypeId,
+			paymentTypeId: formData.paymentTypeId,
+			agentUserId: formData.agentUserId,
+			paymentType: formData.paymentType,
+			status: formData.status,
+			feeType: formData.feeType,
+			feeRate: formData.feeRate,
+			feeEvery: formData.feeEvery,
+		};
+		await editAgentPaymentType(submitData);
+		useMessage().success('配置成功');
+		visible.value = false;
+		emit('refresh');
+	} catch (err: any) {
+		useMessage().error(err.msg);
+	} finally {
+		formLoading.value = false;
+	}
+};
+
+// 暴露方法
+defineExpose({
+	openDialog,
+});
+</script>

+ 129 - 0
src/views/agent/list/agentPaymentDialog.vue

@@ -0,0 +1,129 @@
+<template>
+	<el-dialog :close-on-click-modal="false" :title="dialogTitle" draggable v-model="visible" width="1400px" @close="handleClose">
+		<!-- 表格 -->
+		<el-table
+			:data="paymentList"
+			v-loading="loading"
+			border
+			:cell-style="tableStyle.cellStyle"
+			:header-cell-style="tableStyle.headerCellStyle"
+			style="width: 100%"
+			max-height="500"
+		>
+			<el-table-column label="通道名称" prop="channelName" show-overflow-tooltip />
+			<el-table-column label="通道编码" prop="channelCode" show-overflow-tooltip />
+			<el-table-column label="支付类型名称" prop="paymentName" show-overflow-tooltip />
+			<el-table-column label="支付类型代码" prop="paymentCode" show-overflow-tooltip />
+			<el-table-column label="启用状态" prop="status" show-overflow-tooltip>
+				<template #default="scope">
+					<el-tag :type="scope.row.status ? 'success' : 'info'">
+						{{ scope.row.status ? '启用' : '禁用' }}
+					</el-tag>
+				</template>
+			</el-table-column>
+			<!-- 代收:只显示费率 -->
+			<el-table-column v-if="paymentType === 'HARVEST'" label="费率(%)" prop="feeRate" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.feeRate ? scope.row.feeRate.toFixed(2) : '0.00' }}
+				</template>
+			</el-table-column>
+			<!-- 代付:显示手续费类型、手续费比例、手续费固定金额 -->
+			<template v-if="paymentType === 'PAY'">
+				<el-table-column label="手续费类型" prop="feeType" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag v-if="scope.row.feeType === 'PERCENTAGE'" type="primary">百分比</el-tag>
+						<el-tag v-else-if="scope.row.feeType === 'FIXED'" type="success">固定</el-tag>
+						<el-tag v-else-if="scope.row.feeType === 'MIXED'" type="warning">百分比+固定</el-tag>
+						<el-tag v-else type="info">-</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column label="手续费比例(%)" prop="feeRate" show-overflow-tooltip>
+					<template #default="scope">
+						{{ scope.row.feeRate ? scope.row.feeRate.toFixed(2) : '0.00' }}
+					</template>
+				</el-table-column>
+				<el-table-column label="手续费固定金额" prop="feeEvery" show-overflow-tooltip>
+					<template #default="scope">
+						{{ scope.row.feeEvery || 0 }}
+					</template>
+				</el-table-column>
+			</template>
+			<el-table-column label="操作" width="100">
+				<template #default="scope">
+					<el-button icon="Setting" @click="handleConfig(scope.row)" text type="primary" v-auth="'agent_payment_type_edit'">配置 </el-button>
+				</template>
+			</el-table-column>
+		</el-table>
+
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">关闭</el-button>
+			</span>
+		</template>
+	</el-dialog>
+
+	<!-- 配置弹窗 -->
+	<config-dialog ref="configDialogRef" @refresh="loadPaymentList" />
+</template>
+
+<script lang="ts" name="AgentPaymentDialog" setup>
+import { fetchAgentPaymentTypeList } from '/@/api/agent';
+import { useMessage } from '/@/hooks/message';
+
+// 引入配置弹窗组件
+const ConfigDialog = defineAsyncComponent(() => import('./agentPaymentConfigDialog.vue'));
+
+// 定义表格样式
+const tableStyle = {
+	cellStyle: { textAlign: 'center' },
+	headerCellStyle: { textAlign: 'center', background: '#f5f7fa' },
+};
+
+// 定义变量
+const visible = ref(false);
+const loading = ref(false);
+const configDialogRef = ref();
+const agentUserId = ref('');
+const paymentType = ref<'PAY' | 'HARVEST'>('HARVEST');
+const dialogTitle = ref('');
+const paymentList = ref<any[]>([]);
+
+// 打开弹窗
+const openDialog = (userId: string, type: 'PAY' | 'HARVEST') => {
+	visible.value = true;
+	agentUserId.value = userId;
+	paymentType.value = type;
+	dialogTitle.value = type === 'HARVEST' ? '代理商代收配置' : '代理商代付配置';
+
+	// 加载数据
+	loadPaymentList();
+};
+
+// 加载支付通道列表
+const loadPaymentList = async () => {
+	try {
+		loading.value = true;
+		const res = await fetchAgentPaymentTypeList(agentUserId.value, paymentType.value);
+		paymentList.value = res.data || [];
+	} catch (err: any) {
+		useMessage().error(err.msg);
+	} finally {
+		loading.value = false;
+	}
+};
+
+// 配置
+const handleConfig = (row: any) => {
+	configDialogRef.value.openDialog(row, agentUserId.value, paymentType.value);
+};
+
+// 关闭弹窗
+const handleClose = () => {
+	paymentList.value = [];
+};
+
+// 暴露方法
+defineExpose({
+	openDialog,
+});
+</script>

+ 1 - 1
src/views/agent/list/changePwd.vue

@@ -20,7 +20,7 @@
 
 <script lang="ts" name="ChangePwdDialog" setup>
 import { useMessage } from '/@/hooks/message';
-import { changePwd } from '/@/api/agent/agentUser';
+import { changePwd } from '/@/api/agent';
 import { useI18n } from 'vue-i18n';
 
 const emit = defineEmits(['refresh']);

+ 1 - 1
src/views/agent/list/form.vue

@@ -129,7 +129,7 @@
 <script lang="ts" name="AgentUserDialog" setup>
 // 定义子组件向父组件传值/事件
 import { useMessage } from '/@/hooks/message';
-import { addObj, getObj, putObj } from '/@/api/agent/agentUser';
+import { addObj, getObj, putObj } from '/@/api/agent';
 import { useI18n } from 'vue-i18n';
 import { rule } from '/@/utils/validate';
 

+ 18 - 2
src/views/agent/list/index.vue

@@ -51,7 +51,7 @@
 						/>
 					</template>
 				</el-table-column>
-				<el-table-column :label="$t('agentUser.operation')" width="200">
+				<el-table-column :label="$t('agentUser.operation')" width="360">
 					<template #default="scope">
 						<el-button icon="View" @click="handleView(scope.row)" text type="primary" v-auth="'agent_admin'">{{ $t('agentUser.viewBtn') }}</el-button>
 						<el-button icon="edit-pen" @click="formDialogRef.openDialog(scope.row.userId)" text type="primary" v-auth="'agent_admin'"
@@ -60,6 +60,12 @@
 						<el-button icon="Key" @click="handleChangePwd(scope.row)" text type="warning" v-auth="'agent_admin'">{{
 							$t('agentUser.changePwdBtn')
 						}}</el-button>
+						<el-button icon="Setting" @click="handleAgentPayment(scope.row, 'HARVEST')" text type="success" v-auth="'agent_payment_type_query'"
+							>代收
+						</el-button>
+						<el-button icon="Setting" @click="handleAgentPayment(scope.row, 'PAY')" text type="warning" v-auth="'agent_payment_type_query'"
+							>代付
+						</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -71,12 +77,15 @@
 
 		<!-- 修改密码 -->
 		<change-pwd-dialog @refresh="getDataList(false)" ref="changePwdDialogRef" />
+
+		<!-- 代理商支付通道配置 -->
+		<agent-payment-dialog ref="agentPaymentDialogRef" />
 	</div>
 </template>
 
 <script lang="ts" name="systemAgentUser" setup>
 import { BasicTableProps, useTable } from '/@/hooks/table';
-import { fetchList, changeStatus } from '/@/api/agent/agentUser';
+import { fetchList, changeStatus } from '/@/api/agent';
 import { useMessage, useMessageBox } from '/@/hooks/message';
 import { useI18n } from 'vue-i18n';
 
@@ -85,10 +94,12 @@ const { t } = useI18n();
 // 引入组件
 const FormDialog = defineAsyncComponent(() => import('./form.vue'));
 const ChangePwdDialog = defineAsyncComponent(() => import('./changePwd.vue'));
+const AgentPaymentDialog = defineAsyncComponent(() => import('./agentPaymentDialog.vue'));
 
 // 定义变量内容
 const formDialogRef = ref();
 const changePwdDialogRef = ref();
+const agentPaymentDialogRef = ref();
 // 搜索变量
 const queryRef = ref();
 const showSearch = ref(true);
@@ -163,4 +174,9 @@ const handleView = (row: any) => {
 const handleChangePwd = (row: any) => {
 	changePwdDialogRef.value.openDialog(row.userId);
 };
+
+// 打开代理商支付通道配置
+const handleAgentPayment = (row: any, type: 'PAY' | 'HARVEST') => {
+	agentPaymentDialogRef.value.openDialog(row.userId, type);
+};
 </script>

+ 1 - 1
src/views/merchant/list/changePwd.vue

@@ -20,7 +20,7 @@
 
 <script lang="ts" name="ChangePwdDialog" setup>
 import { useMessage } from '/@/hooks/message';
-import { changePwd } from '/@/api/merchant/merchantUser';
+import { changePwd } from '/@/api/merchant';
 import { useI18n } from 'vue-i18n';
 
 const emit = defineEmits(['refresh']);

+ 2 - 2
src/views/merchant/list/form.vue

@@ -67,7 +67,7 @@
 
 				<el-col :span="12" class="mb20">
 					<el-form-item :label="$t('merchantUser.agentId')" prop="agentId">
-						<el-select v-model="form.agentId" :placeholder="$t('merchantUser.selectAgentTip')" :disabled="readonly" style="width: 100%">
+						<el-select v-model="form.agentId" :placeholder="$t('merchantUser.selectAgentTip')" :disabled="readonly" style="width: 100%" clearable>
 							<el-option v-for="item in agentList" :key="item.userId" :label="item.agentName" :value="item.userId" />
 						</el-select>
 					</el-form-item>
@@ -128,7 +128,7 @@
 <script lang="ts" name="MerchantUserDialog" setup>
 // 定义子组件向父组件传值/事件
 import { useMessage } from '/@/hooks/message';
-import { addObj, getObj, putObj, getAgentList } from '/@/api/merchant/merchantUser';
+import { addObj, getObj, putObj, getAgentList } from '/@/api/merchant';
 import { useI18n } from 'vue-i18n';
 import { rule } from '/@/utils/validate';
 import { useClipboard } from '@vueuse/core';

+ 18 - 2
src/views/merchant/list/index.vue

@@ -52,7 +52,7 @@
 						/>
 					</template>
 				</el-table-column>
-				<el-table-column :label="$t('merchantUser.operation')" width="320">
+				<el-table-column :label="$t('merchantUser.operation')" width="480">
 					<template #default="scope">
 						<el-button icon="View" @click="handleView(scope.row)" text type="primary" v-auth="'merchant_admin'">{{
 							$t('merchantUser.viewBtn')
@@ -66,6 +66,12 @@
 						<el-button icon="RefreshRight" @click="handleResetKey(scope.row)" text type="danger" v-auth="'merchant_admin'">{{
 							$t('merchantUser.resetKeyBtn')
 						}}</el-button>
+						<el-button icon="Setting" @click="handleMerchantPayment(scope.row, 'HARVEST')" text type="success" v-auth="'merchant_payment_type_query'"
+							>代收
+						</el-button>
+						<el-button icon="Setting" @click="handleMerchantPayment(scope.row, 'PAY')" text type="warning" v-auth="'merchant_payment_type_query'"
+							>代付
+						</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -80,12 +86,15 @@
 
 		<!-- 密钥显示 -->
 		<key-dialog ref="keyDialogRef" />
+
+		<!-- 商户支付通道配置 -->
+		<merchant-payment-dialog ref="merchantPaymentDialogRef" />
 	</div>
 </template>
 
 <script lang="ts" name="systemMerchantUser" setup>
 import { BasicTableProps, useTable } from '/@/hooks/table';
-import { fetchList, changeStatus, resetMd5Key } from '/@/api/merchant/merchantUser';
+import { fetchList, changeStatus, resetMd5Key } from '/@/api/merchant';
 import { useMessage, useMessageBox } from '/@/hooks/message';
 import { useI18n } from 'vue-i18n';
 
@@ -95,11 +104,13 @@ const { t } = useI18n();
 const FormDialog = defineAsyncComponent(() => import('./form.vue'));
 const ChangePwdDialog = defineAsyncComponent(() => import('./changePwd.vue'));
 const KeyDialog = defineAsyncComponent(() => import('./keyDialog.vue'));
+const MerchantPaymentDialog = defineAsyncComponent(() => import('./merchantPaymentDialog.vue'));
 
 // 定义变量内容
 const formDialogRef = ref();
 const changePwdDialogRef = ref();
 const keyDialogRef = ref();
+const merchantPaymentDialogRef = ref();
 const queryRef = ref();
 const showSearch = ref(true);
 const selectObjs = ref([]);
@@ -163,4 +174,9 @@ const handleResetKey = async (row: any) => {
 		}
 	}
 };
+
+// 打开商户支付通道配置
+const handleMerchantPayment = (row: any, type: 'PAY' | 'HARVEST') => {
+	merchantPaymentDialogRef.value.openDialog(row.userId, type);
+};
 </script>

+ 352 - 0
src/views/merchant/list/merchantPaymentConfigDialog.vue

@@ -0,0 +1,352 @@
+<template>
+	<el-dialog :close-on-click-modal="false" title="配置商户支付通道" draggable v-model="visible" width="700px">
+		<el-form :model="formData" :rules="formRules" label-width="140px" ref="formRef" v-loading="formLoading">
+			<!-- 基本信息(只读) -->
+			<el-divider content-position="left">基本信息</el-divider>
+			<el-row :gutter="24">
+				<el-col :span="24" class="mb20">
+					<el-form-item label="通道名称">
+						<el-input v-model="formData.channelName" disabled />
+					</el-form-item>
+				</el-col>
+
+				<el-col :span="24" class="mb20">
+					<el-form-item label="支付类型名称">
+						<el-input v-model="formData.paymentName" disabled />
+					</el-form-item>
+				</el-col>
+			</el-row>
+
+			<!-- 代理商手续费信息(只读) -->
+			<el-divider content-position="left">代理商手续费信息</el-divider>
+			<el-row :gutter="24">
+				<el-col :span="24" class="mb20">
+					<el-form-item label="手续费类型">
+						<el-input :value="getAgentFeeTypeLabel()" disabled />
+					</el-form-item>
+				</el-col>
+
+				<el-col :span="24" class="mb20" v-if="formData.agentFeeType === 'PERCENTAGE' || formData.agentFeeType === 'MIXED'">
+					<el-form-item label="手续费比例(%)">
+						<el-input :value="formData.agentFeeRate !== undefined && formData.agentFeeRate !== null ? formData.agentFeeRate : '未设置'" disabled />
+					</el-form-item>
+				</el-col>
+
+				<el-col :span="24" class="mb20" v-if="formData.agentFeeType === 'FIXED' || formData.agentFeeType === 'MIXED'">
+					<el-form-item label="手续费固定金额">
+						<el-input :value="formData.agentFeeEvery !== undefined && formData.agentFeeEvery !== null ? formData.agentFeeEvery : '未设置'" disabled />
+					</el-form-item>
+				</el-col>
+			</el-row>
+
+			<!-- 配置信息 -->
+			<el-divider content-position="left">配置信息</el-divider>
+			<el-row :gutter="24">
+				<el-col :span="24" class="mb20">
+					<el-form-item label="启用状态" prop="status">
+						<el-radio-group v-model="formData.status">
+							<el-radio :label="true">启用</el-radio>
+							<el-radio :label="false">禁用</el-radio>
+						</el-radio-group>
+					</el-form-item>
+				</el-col>
+
+				<!-- 代收:只显示商户费率 -->
+				<el-col :span="24" class="mb20" v-if="formData.paymentType === 'HARVEST'">
+					<el-form-item label="商户费率(%)" prop="merchantUserRate">
+						<el-input-number
+							placeholder="请输入商户费率"
+							v-model="formData.merchantUserRate"
+							:min="0"
+							:max="100"
+							:precision="2"
+							style="width: 100%"
+						/>
+					</el-form-item>
+				</el-col>
+
+				<!-- 代付:显示手续费类型选择 -->
+				<template v-if="formData.paymentType === 'PAY'">
+					<el-col :span="24" class="mb20">
+						<el-form-item label="手续费类型" prop="merchantUserFeeType">
+							<el-radio-group v-model="formData.merchantUserFeeType">
+								<el-radio label="PERCENTAGE">百分比</el-radio>
+								<el-radio label="FIXED">固定</el-radio>
+								<el-radio label="MIXED">百分比+固定</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+
+					<!-- 代付:百分比、百分比+固定 显示手续费比例 -->
+					<el-col :span="24" class="mb20" v-if="formData.merchantUserFeeType === 'PERCENTAGE' || formData.merchantUserFeeType === 'MIXED'">
+						<el-form-item label="手续费比例(%)" prop="merchantUserRate">
+							<el-input-number
+								placeholder="请输入手续费比例"
+								v-model="formData.merchantUserRate"
+								:min="0"
+								:max="100"
+								:precision="2"
+								style="width: 100%"
+							/>
+						</el-form-item>
+					</el-col>
+
+					<!-- 代付:固定、百分比+固定 显示手续费固定金额 -->
+					<el-col :span="24" class="mb20" v-if="formData.merchantUserFeeType === 'FIXED' || formData.merchantUserFeeType === 'MIXED'">
+						<el-form-item label="手续费固定金额" prop="merchantUserFeeEvery">
+							<el-input-number
+								placeholder="请输入手续费固定金额"
+								v-model="formData.merchantUserFeeEvery"
+								:min="0"
+								:precision="2"
+								style="width: 100%"
+							/>
+						</el-form-item>
+					</el-col>
+				</template>
+
+				<el-col :span="24" class="mb20">
+					<el-form-item label="单笔最小金额" prop="singleMinAmount">
+						<el-input-number placeholder="请输入单笔最小金额" v-model="formData.singleMinAmount" :min="0" :precision="2" style="width: 100%" />
+						<div class="form-tip">通道限制:{{ formData.baseSingleMinAmount || 0 }}</div>
+					</el-form-item>
+				</el-col>
+
+				<el-col :span="24" class="mb20">
+					<el-form-item label="单笔最大金额" prop="singleMaxAmount">
+						<el-input-number placeholder="请输入单笔最大金额" v-model="formData.singleMaxAmount" :min="0" :precision="2" style="width: 100%" />
+						<div class="form-tip">通道限制:{{ formData.baseSingleMaxAmount || 0 }}</div>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">取消</el-button>
+				<el-button @click="handleSubmit" type="primary" :disabled="formLoading">确定</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script lang="ts" name="MerchantPaymentConfigDialog" setup>
+import { editMerchantPaymentType } from '/@/api/merchant';
+import { useMessage } from '/@/hooks/message';
+
+const emit = defineEmits(['refresh']);
+
+// 定义变量
+const visible = ref(false);
+const formLoading = ref(false);
+const formRef = ref();
+
+// 表单数据
+const formData = reactive({
+	merchantPaymentTypeId: '',
+	paymentTypeId: '',
+	merchantUserId: '',
+	paymentType: '',
+	channelName: '',
+	paymentName: '',
+	status: true,
+	agentFeeType: '',
+	agentFeeRate: 0,
+	agentFeeEvery: 0,
+	merchantUserRate: 0,
+	merchantUserFeeType: '',
+	merchantUserFeeEvery: 0,
+	singleMinAmount: 0,
+	singleMaxAmount: 0,
+	baseSingleMinAmount: 0,
+	baseSingleMaxAmount: 0,
+});
+
+// 获取代理商手续费类型标签
+const getAgentFeeTypeLabel = () => {
+	if (!formData.agentFeeType) return '未设置';
+	const typeMap: Record<string, string> = {
+		PERCENTAGE: '百分比',
+		FIXED: '固定',
+		MIXED: '百分比+固定',
+	};
+	return typeMap[formData.agentFeeType] || '未设置';
+};
+
+// 表单验证规则
+const formRules = ref({
+	status: [{ required: true, message: '请选择启用状态', trigger: 'change' }],
+	merchantUserRate: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 代收:商户费率必填
+				if (formData.paymentType === 'HARVEST' && !value && value !== 0) {
+					callback(new Error('请输入商户费率'));
+				}
+				// 代付:百分比、百分比+固定 需要手续费比例
+				else if (
+					formData.paymentType === 'PAY' &&
+					(formData.merchantUserFeeType === 'PERCENTAGE' || formData.merchantUserFeeType === 'MIXED') &&
+					!value &&
+					value !== 0
+				) {
+					callback(new Error('请输入手续费比例'));
+				} else if (value !== undefined && value !== null && (value < 0 || value > 100)) {
+					callback(new Error('费率比例范围为0-100'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+	merchantUserFeeType: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 代付:手续费类型必填
+				if (formData.paymentType === 'PAY' && !value) {
+					callback(new Error('请选择手续费类型'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'change',
+		},
+	],
+	merchantUserFeeEvery: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				// 代付:固定、百分比+固定 需要手续费固定金额
+				const needFeeEvery = formData.paymentType === 'PAY' && (formData.merchantUserFeeType === 'FIXED' || formData.merchantUserFeeType === 'MIXED');
+
+				if (needFeeEvery && !value && value !== 0) {
+					callback(new Error('请输入手续费固定金额'));
+				} else if (value !== undefined && value !== null && value < 0) {
+					callback(new Error('手续费固定金额不能小于0'));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+	singleMinAmount: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				if (value && formData.singleMaxAmount && value > formData.singleMaxAmount) {
+					callback(new Error('单笔最小金额不能大于单笔最大金额'));
+				} else if (value && formData.baseSingleMinAmount && value < formData.baseSingleMinAmount) {
+					callback(new Error(`单笔最小金额不能小于通道限制(${formData.baseSingleMinAmount})`));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+	singleMaxAmount: [
+		{
+			validator: (rule: any, value: any, callback: any) => {
+				if (value && formData.singleMinAmount && value < formData.singleMinAmount) {
+					callback(new Error('单笔最大金额不能小于单笔最小金额'));
+				} else if (value && formData.baseSingleMaxAmount && value > formData.baseSingleMaxAmount) {
+					callback(new Error(`单笔最大金额不能大于通道限制(${formData.baseSingleMaxAmount})`));
+				} else {
+					callback();
+				}
+			},
+			trigger: 'blur',
+		},
+	],
+});
+
+// 打开弹窗
+const openDialog = (row: any, merchantUserId: string, paymentType: 'PAY' | 'HARVEST') => {
+	visible.value = true;
+
+	// 填充数据
+	formData.merchantPaymentTypeId = row.merchantPaymentTypeId;
+	formData.paymentTypeId = row.paymentTypeId;
+	formData.merchantUserId = merchantUserId;
+	formData.paymentType = paymentType;
+	formData.channelName = row.channelName;
+	formData.paymentName = row.paymentName;
+	formData.status = row.status ?? true;
+	formData.agentFeeType = row.agentFeeType || '';
+	formData.agentFeeRate = row.agentFeeRate || 0;
+	formData.agentFeeEvery = row.agentFeeEvery || 0;
+	formData.merchantUserRate = row.merchantUserRate || 0;
+	// 代收固定为PERCENTAGE,代付根据实际值设置
+	if (paymentType === 'HARVEST') {
+		formData.merchantUserFeeType = 'PERCENTAGE';
+		formData.merchantUserFeeEvery = 0;
+	} else {
+		formData.merchantUserFeeType = row.merchantUserFeeType || 'PERCENTAGE';
+		formData.merchantUserFeeEvery = row.merchantUserFeeEvery || 0;
+	}
+	formData.singleMinAmount = row.singleMinAmount || 0;
+	formData.singleMaxAmount = row.singleMaxAmount || 0;
+	formData.baseSingleMinAmount = row.baseSingleMinAmount || 0;
+	formData.baseSingleMaxAmount = row.baseSingleMaxAmount || 0;
+
+	nextTick(() => {
+		formRef.value?.clearValidate();
+	});
+};
+
+// 提交表单
+const handleSubmit = async () => {
+	const valid = await formRef.value.validate().catch(() => {});
+	if (!valid) return false;
+
+	try {
+		formLoading.value = true;
+		const submitData: any = {
+			merchantPaymentTypeId: formData.merchantPaymentTypeId,
+			paymentTypeId: formData.paymentTypeId,
+			merchantUserId: formData.merchantUserId,
+			paymentType: formData.paymentType,
+			status: formData.status,
+			singleMinAmount: formData.singleMinAmount,
+			singleMaxAmount: formData.singleMaxAmount,
+		};
+
+		// 代收:提交商户费率,feeType固定为PERCENTAGE
+		if (formData.paymentType === 'HARVEST') {
+			submitData.merchantUserRate = formData.merchantUserRate;
+			submitData.feeType = 'PERCENTAGE';
+			submitData.feeRate = formData.merchantUserRate; // 代收的费率就是merchantUserRate
+			submitData.feeEvery = 0;
+		}
+
+		// 代付:提交手续费类型和对应字段
+		if (formData.paymentType === 'PAY') {
+			submitData.feeType = formData.merchantUserFeeType;
+			submitData.feeRate = formData.merchantUserRate;
+			submitData.feeEvery = formData.merchantUserFeeEvery;
+		}
+
+		await editMerchantPaymentType(submitData);
+		useMessage().success('配置成功');
+		visible.value = false;
+		emit('refresh');
+	} catch (err: any) {
+		useMessage().error(err.msg);
+	} finally {
+		formLoading.value = false;
+	}
+};
+
+// 暴露方法
+defineExpose({
+	openDialog,
+});
+</script>
+
+<style scoped>
+.form-tip {
+	font-size: 12px;
+	color: #909399;
+	margin-top: 4px;
+}
+</style>

+ 163 - 0
src/views/merchant/list/merchantPaymentDialog.vue

@@ -0,0 +1,163 @@
+<template>
+	<el-dialog :close-on-click-modal="false" :title="dialogTitle" draggable v-model="visible" width="1400px" @close="handleClose">
+		<!-- 表格 -->
+		<el-table
+			:data="paymentList"
+			v-loading="loading"
+			border
+			:cell-style="tableStyle.cellStyle"
+			:header-cell-style="tableStyle.headerCellStyle"
+			style="width: 100%"
+			max-height="500"
+		>
+			<el-table-column label="通道名称" prop="channelName" show-overflow-tooltip />
+			<el-table-column label="通道编码" prop="channelCode" show-overflow-tooltip />
+			<el-table-column label="支付类型名称" prop="paymentName" show-overflow-tooltip />
+			<el-table-column label="支付类型代码" prop="paymentCode" show-overflow-tooltip />
+			<el-table-column label="启用状态" prop="status" show-overflow-tooltip>
+				<template #default="scope">
+					<el-tag :type="scope.row.status ? 'success' : 'info'">
+						{{ scope.row.status ? '启用' : '禁用' }}
+					</el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column label="代理商手续费类型" prop="agentFeeType" show-overflow-tooltip>
+				<template #default="scope">
+					<el-tag v-if="scope.row.agentFeeType === 'PERCENTAGE'" type="primary">百分比</el-tag>
+					<el-tag v-else-if="scope.row.agentFeeType === 'FIXED'" type="success">固定</el-tag>
+					<el-tag v-else-if="scope.row.agentFeeType === 'MIXED'" type="warning">百分比+固定</el-tag>
+					<el-tag v-else type="info">未设置</el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column label="代理商手续费比例(%)" prop="agentFeeRate" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.agentFeeRate !== undefined && scope.row.agentFeeRate !== null ? scope.row.agentFeeRate.toFixed(2) : '-' }}
+				</template>
+			</el-table-column>
+			<el-table-column label="代理商手续费固定金额" prop="agentFeeEvery" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.agentFeeEvery !== undefined && scope.row.agentFeeEvery !== null ? scope.row.agentFeeEvery : '-' }}
+				</template>
+			</el-table-column>
+			<!-- 代收:显示商户费率 -->
+			<el-table-column v-if="paymentType === 'HARVEST'" label="商户费率(%)" prop="merchantUserRate" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.merchantUserRate ? scope.row.merchantUserRate.toFixed(2) : '0.00' }}
+				</template>
+			</el-table-column>
+			<!-- 代付:显示商户手续费类型、手续费比例、手续费固定金额 -->
+			<template v-if="paymentType === 'PAY'">
+				<el-table-column label="商户手续费类型" prop="merchantUserFeeType" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag v-if="scope.row.merchantUserFeeType === 'PERCENTAGE'" type="primary">百分比</el-tag>
+						<el-tag v-else-if="scope.row.merchantUserFeeType === 'FIXED'" type="success">固定</el-tag>
+						<el-tag v-else-if="scope.row.merchantUserFeeType === 'MIXED'" type="warning">百分比+固定</el-tag>
+						<el-tag v-else type="info">未设置</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column label="商户手续费比例(%)" prop="merchantUserRate" show-overflow-tooltip>
+					<template #default="scope">
+						<template v-if="scope.row.merchantUserFeeType === 'PERCENTAGE' || scope.row.merchantUserFeeType === 'MIXED'">
+							{{ scope.row.merchantUserRate !== undefined && scope.row.merchantUserRate !== null ? scope.row.merchantUserRate.toFixed(2) : '-' }}
+						</template>
+						<template v-else>-</template>
+					</template>
+				</el-table-column>
+				<el-table-column label="商户手续费固定金额" prop="merchantUserFeeEvery" show-overflow-tooltip>
+					<template #default="scope">
+						<template v-if="scope.row.merchantUserFeeType === 'FIXED' || scope.row.merchantUserFeeType === 'MIXED'">
+							{{ scope.row.merchantUserFeeEvery !== undefined && scope.row.merchantUserFeeEvery !== null ? scope.row.merchantUserFeeEvery : '-' }}
+						</template>
+						<template v-else>-</template>
+					</template>
+				</el-table-column>
+			</template>
+			<el-table-column label="单笔最小金额" prop="singleMinAmount" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.singleMinAmount || 0 }}
+				</template>
+			</el-table-column>
+			<el-table-column label="单笔最大金额" prop="singleMaxAmount" show-overflow-tooltip>
+				<template #default="scope">
+					{{ scope.row.singleMaxAmount || 0 }}
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" width="100">
+				<template #default="scope">
+					<el-button icon="Setting" @click="handleConfig(scope.row)" text type="primary" v-auth="'merchant_payment_type_edit'">配置 </el-button>
+				</template>
+			</el-table-column>
+		</el-table>
+
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">关闭</el-button>
+			</span>
+		</template>
+	</el-dialog>
+
+	<!-- 配置弹窗 -->
+	<config-dialog ref="configDialogRef" @refresh="loadPaymentList" />
+</template>
+
+<script lang="ts" name="MerchantPaymentDialog" setup>
+import { fetchMerchantPaymentTypeList } from '/@/api/merchant';
+import { useMessage } from '/@/hooks/message';
+
+// 引入配置弹窗组件
+const ConfigDialog = defineAsyncComponent(() => import('./merchantPaymentConfigDialog.vue'));
+
+// 定义表格样式
+const tableStyle = {
+	cellStyle: { textAlign: 'center' },
+	headerCellStyle: { textAlign: 'center', background: '#f5f7fa' },
+};
+
+// 定义变量
+const visible = ref(false);
+const loading = ref(false);
+const configDialogRef = ref();
+const merchantUserId = ref('');
+const paymentType = ref<'PAY' | 'HARVEST'>('HARVEST');
+const dialogTitle = ref('');
+const paymentList = ref<any[]>([]);
+
+// 打开弹窗
+const openDialog = (userId: string, type: 'PAY' | 'HARVEST') => {
+	visible.value = true;
+	merchantUserId.value = userId;
+	paymentType.value = type;
+	dialogTitle.value = type === 'HARVEST' ? '商户代收配置' : '商户代付配置';
+
+	// 加载数据
+	loadPaymentList();
+};
+
+// 加载支付通道列表
+const loadPaymentList = async () => {
+	try {
+		loading.value = true;
+		const res = await fetchMerchantPaymentTypeList(merchantUserId.value, paymentType.value);
+		paymentList.value = res.data || [];
+	} catch (err: any) {
+		useMessage().error(err.msg);
+	} finally {
+		loading.value = false;
+	}
+};
+
+// 配置
+const handleConfig = (row: any) => {
+	configDialogRef.value.openDialog(row, merchantUserId.value, paymentType.value);
+};
+
+// 关闭弹窗
+const handleClose = () => {
+	paymentList.value = [];
+};
+
+// 暴露方法
+defineExpose({
+	openDialog,
+});
+</script>