hejianhao
2026-08-18 81403ccb31dbec8402f7a7e70dc5b179c0deb7c7
feat0806: 编辑诊所页面调整
4个文件已修改
104 ■■■■■ 已修改文件
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/member/dto/ClinicBankAccountUpdateRequest.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/utils/VzanHttpUtil.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tcm-training-admin/src/pages/member/clinic/manage.tsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tcm-training-admin/src/pages/member/clinic/service.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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 } });
}