tcm-training-admin-backend/src/main/java/com/tcm/training/admin/member/dto/ClinicBankAccountUpdateRequest.java
@@ -8,6 +8,19 @@ @Getter @Setter public class ClinicBankAccountUpdateRequest { private String avatar; private String name; private String loginAccount; private String provinceCode; private String provinceName; private String cityCode; private String cityName; private String districtCode; private String districtName; private String address; private String businessLicenseUrl; private Integer status; private Long agentId; @Size(max = 100, message = "银行名称不能超过100个字") private String bankName; @Size(max = 50, message = "账号名称不能超过50个字") tcm-training-admin-backend/src/main/java/com/tcm/training/admin/utils/VzanHttpUtil.java
@@ -11,6 +11,7 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @@ -164,6 +165,71 @@ } } /** * 创建微赞代理。接口返回顶层code或data.result非成功时抛出运行时异常。 * * @return 微赞返回的代理业务数据 */ public JsonNode createAgent(String agentMobile, String agentName, Integer levelCode, String parentMobile, String storeName) { String token = getToken(); Map<String, Object> body = new LinkedHashMap<String, Object>(); body.put("agent_mobile", requireText(agentMobile, "代理手机号不能为空")); body.put("agent_name", requireText(agentName, "代理名称不能为空")); if (levelCode == null) { throw new IllegalArgumentException("代理等级不能为空"); } body.put("level_code", levelCode); putIfHasText(body, "parent_mobile", parentMobile); putIfHasText(body, "store_name", storeName); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(token); try { ResponseEntity<String> response = restOperations.postForEntity( "https://openapi.njyqkj0ksyz.com/api/v2/agent/createAgent", new HttpEntity<Map<String, Object>>(body, headers), String.class); return parseCreateAgentResponse(response.getBody()); } catch (RestClientException ex) { throw new IllegalStateException("调用微赞创建代理接口失败", ex); } } private JsonNode parseCreateAgentResponse(String responseBody) { if (!StringUtils.hasText(responseBody)) { throw new IllegalStateException("微赞创建代理接口返回为空"); } try { JsonNode root = objectMapper.readTree(responseBody); if (!"0".equals(root.path("code").asText())) { throw new IllegalStateException("微赞创建代理失败: " + root.path("msg").asText("未知错误")); } JsonNode data = root.path("data"); if (!data.isObject() || data.path("result").asInt(-1) != 0) { throw new IllegalStateException("微赞创建代理失败: 业务处理未成功"); } return data; } catch (IllegalStateException ex) { throw ex; } catch (Exception ex) { throw new IllegalStateException("解析微赞创建代理响应失败", ex); } } private static String requireText(String value, String message) { if (!StringUtils.hasText(value)) { throw new IllegalArgumentException(message); } return value.trim(); } private static void putIfHasText(Map<String, Object> body, String key, String value) { if (StringUtils.hasText(value)) { body.put(key, value.trim()); } } private static String md5Lowercase(String text) { try { MessageDigest digest = MessageDigest.getInstance("MD5"); tcm-training-admin/src/pages/member/clinic/manage.tsx
@@ -1,23 +1,35 @@ import { history, useAccess, useParams } from '@umijs/max'; import { Button, Form, Input, message } from 'antd'; import { Avatar, Button, Form, Input, Select, message } from 'antd'; import React, { useEffect, useState } from 'react'; import { getClinicDetail, updateClinic } from './service'; import RegionCascader from '@/components/RegionCascader'; import { getClinicDetail, getProvincialAgentOptions, updateClinic } from './service'; type FormValues = { bankName?: string; accountHolder?: string; accountNumber?: string; branchName?: string }; type FormValues = { avatar?: string; name?: string; loginAccount?: string; regionCodes?: string[]; address?: string; businessLicenseUrl?: string; status?: number; agentId?: number; bankName?: string; accountHolder?: string; accountNumber?: string; branchName?: string }; const ClinicManagePage: React.FC = () => { const access = useAccess(); const params = useParams<{ id: string }>(); const [form] = Form.useForm<FormValues>(); const [loading, setLoading] = useState(false); const [agentOptions, setAgentOptions] = useState<{ label: string; value: number }[]>([]); useEffect(() => { if (!access['member:clinic:edit']) { history.replace('/Welcome'); return; } getProvincialAgentOptions().then((response) => setAgentOptions((response.data?.list || []).map((item: any) => ({ label: item.agentName, value: item.id })))); if (params.id) getClinicDetail(params.id).then((response) => form.setFieldsValue(response.data || {})); }, [params.id]); const submit = async () => { const values = await form.validateFields(); if (!params.id) return; setLoading(true); try { await updateClinic(params.id, values); message.success('保存成功'); history.push(`/member/user/clinic/${params.id}`); } try { const [provinceCode, cityCode, districtCode] = values.regionCodes || []; await updateClinic(params.id, { ...values, provinceCode, cityCode, districtCode }); message.success('保存成功'); history.push(`/member/user/clinic/${params.id}`); } finally { setLoading(false); } }; return <div style={{ padding: 24, background: '#fff' }}><h2>编辑诊所</h2> <Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 10 }}> <Form.Item shouldUpdate noStyle>{() => <div style={{ marginBottom: 20 }}><Avatar size={72} src={form.getFieldValue("avatar")} /></div>}</Form.Item> <Form.Item name="avatar" label="头像"><Input placeholder="请输入头像地址" /></Form.Item> <Form.Item name="name" label="诊所名称"><Input maxLength={100} placeholder="请输入诊所名称" /></Form.Item> <Form.Item name="loginAccount" label="登录账号"><Input maxLength={50} placeholder="请输入登录账号" /></Form.Item> <Form.Item name="regionCodes" label="诊所地址"><RegionCascader placeholder="请选择省/市/区" /></Form.Item> <Form.Item name="address" label="详细地址"><Input maxLength={255} placeholder="请输入详细地址" /></Form.Item> <Form.Item name="businessLicenseUrl" label="营业执照"><Input placeholder="请输入营业执照图片地址" /></Form.Item> <Form.Item name="status" label="状态"><Select options={[{ label: "启用", value: 1 }, { label: "禁用", value: 0 }]} placeholder="请选择状态" /></Form.Item> <Form.Item name="agentId" label="所属省区代理"><Select allowClear showSearch optionFilterProp="label" options={agentOptions} placeholder="请选择省区代理" /></Form.Item> <Form.Item name="bankName" label="银行名称"><Input maxLength={100} placeholder="请输入银行名称" /></Form.Item> <Form.Item name="accountHolder" label="账号名称"><Input maxLength={50} placeholder="请输入账号名称" /></Form.Item> <Form.Item name="accountNumber" label="账号"><Input maxLength={30} placeholder="请输入账号" /></Form.Item> tcm-training-admin/src/pages/member/clinic/service.ts
@@ -69,4 +69,7 @@ const result = await response.json(); if (!response.ok || result.code !== 0) throw new Error(result.msg || '更新绑定关系失败'); return result; } } export async function getProvincialAgentOptions() { return request('/provincial-agents', { method: 'GET', params: { page: 1, pageSize: 1000 } }); }