From 9835b6332cf7d2ce8584b5f1609a3e89035706db Mon Sep 17 00:00:00 2001
From: 刘帅 <rr.iii@qq.com>
Date: 星期一, 14 九月 2026 10:08:06 +0800
Subject: [PATCH] 机器人设置页面调整

---
 management/src/pages/settings/outboundRobotSetting/index.jsx  |  106 +++++++++++++++++++++++++++++++++-
 management/src/pages/settings/outboundRobotSetting/style.less |   19 ++++++
 2 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/management/src/pages/settings/outboundRobotSetting/index.jsx b/management/src/pages/settings/outboundRobotSetting/index.jsx
index 71a26af..62b42ca 100644
--- a/management/src/pages/settings/outboundRobotSetting/index.jsx
+++ b/management/src/pages/settings/outboundRobotSetting/index.jsx
@@ -1,6 +1,8 @@
+import { allAreaList } from '@/utils/area';
+import { PlusOutlined } from '@ant-design/icons';
 import { PageContainer } from '@ant-design/pro-components';
-import { Button, Empty, message, Select, Spin } from 'antd';
-import { useEffect, useState } from 'react';
+import { Button, Cascader, Empty, message, Select, Spin, Tag } from 'antd';
+import { useEffect, useMemo, useState } from 'react';
 import { getList, update } from './service';
 import styles from './style.less';
 
@@ -12,14 +14,47 @@
         .filter(Number.isFinite)
     : [];
 
+const commaTextToArray = (value) =>
+  value
+    ? String(value)
+        .split(',')
+        .map((item) => item.trim())
+        .filter(Boolean)
+    : [];
+
 const arraysEqual = (a = [], b = []) =>
   a.length === b.length && [...a].sort().join(',') === [...b].sort().join(',');
 
+const buildAreaOptions = () => {
+  const codeMap = {};
+  const options = (allAreaList || []).map((provinceItem) => {
+    codeMap[provinceItem.value] = provinceItem.province;
+    return {
+      label: provinceItem.province,
+      value: provinceItem.value,
+      children: (provinceItem.data || []).map((cityItem) => {
+        codeMap[cityItem.value] = cityItem.city;
+        return {
+          label: cityItem.city,
+          value: cityItem.value,
+          children: (cityItem.dataList || []).map((areaItem) => {
+            codeMap[areaItem.value] = areaItem.area;
+            return { label: areaItem.area, value: areaItem.value };
+          }),
+        };
+      }),
+    };
+  });
+  return { options, codeMap };
+};
+
 export default function OutboundRobotSetting() {
+  const { options: areaOptions, codeMap } = useMemo(() => buildAreaOptions(), []);
   const [loading, setLoading] = useState(false);
   const [saving, setSaving] = useState(false);
   const [robotList, setRobotList] = useState([]);
   const [siteOptions, setSiteOptions] = useState([]);
+  const [draftArea, setDraftArea] = useState({});
   const [originList, setOriginList] = useState([]);
 
   const loadList = async () => {
@@ -30,6 +65,7 @@
         const list = (res?.data?.robotSettings || []).map((item) => ({
           ...item,
           siteIds: commaTextToNumberArray(item.siteIds),
+          dialAreaCodes: commaTextToArray(item.dialAreaCodes),
         }));
         setSiteOptions(
           (res?.data?.sites || []).map((item) => ({ label: item.siteName, value: item.id })),
@@ -39,6 +75,7 @@
           list.map((item) => ({
             id: item.id,
             siteIds: [...item.siteIds],
+            dialAreaCodes: [...item.dialAreaCodes],
           })),
         );
       } else {
@@ -59,13 +96,44 @@
     );
   };
 
+  const setAreaValue = (id, value) => {
+    setDraftArea((prev) => ({ ...prev, [id]: value }));
+  };
+
+  const addArea = (id) => {
+    const selectedPath = draftArea[id];
+    const code = Array.isArray(selectedPath) ? selectedPath[selectedPath.length - 1] : selectedPath;
+    if (!code) return;
+
+    setRobotList((prev) =>
+      prev.map((item) => {
+        if (item.id !== id || item.dialAreaCodes.includes(code)) return item;
+        return { ...item, dialAreaCodes: [...item.dialAreaCodes, code] };
+      }),
+    );
+    setDraftArea((prev) => ({ ...prev, [id]: undefined }));
+  };
+
+  const removeArea = (id, code) => {
+    setRobotList((prev) =>
+      prev.map((item) =>
+        item.id === id
+          ? { ...item, dialAreaCodes: item.dialAreaCodes.filter((itemCode) => itemCode !== code) }
+          : item,
+      ),
+    );
+  };
+
   const save = async () => {
     const changedList = robotList.filter((item) => {
       const origin = originList.find((originItem) => originItem.id === item.id);
       if (!origin) {
         return true;
       }
-      return !arraysEqual(origin.siteIds, item.siteIds);
+      return (
+        !arraysEqual(origin.siteIds, item.siteIds) ||
+        !arraysEqual(origin.dialAreaCodes, item.dialAreaCodes)
+      );
     });
 
     if (changedList.length === 0) {
@@ -79,6 +147,7 @@
         const res = await update({
           id: item.id,
           siteIds: item.siteIds || [],
+          dialAreaCodes: item.dialAreaCodes || [],
         });
         if (String(res?.code) !== '200') {
           message.error(res?.msg || `机器人 ${item.robotNumber || item.id} 保存失败`);
@@ -97,8 +166,8 @@
       <Spin spinning={loading}>
         <div className={styles.page}>
           <div className={styles.header}>
-            <div className={styles.title}>机器人可外呼站点设置</div>
-            <div className={styles.subTitle}>按订单所属站点配置机器人可外呼范围</div>
+            <div className={styles.title}>机器人外呼设置</div>
+            <div className={styles.subTitle}>按订单所属站点和拨打区域配置机器人外呼范围</div>
           </div>
 
           {robotList.length === 0 && !loading ? <Empty description="暂无配置" /> : null}
@@ -131,6 +200,33 @@
                   />
                 </div>
               </div>
+
+              <div className={styles.fieldRow}>
+                <div className={styles.label}>拨打区域</div>
+                <div className={styles.value}>
+                  <div className={styles.tags}>
+                    {item.dialAreaCodes.map((code) => (
+                      <Tag key={code} closable onClose={() => removeArea(item.id, code)}>
+                        {codeMap[code] || code}
+                      </Tag>
+                    ))}
+                  </div>
+                  <div className={styles.areaRow}>
+                    <Cascader
+                      className={styles.cascader}
+                      value={draftArea[item.id]}
+                      options={areaOptions}
+                      placeholder="请选择省 / 市 / 区"
+                      changeOnSelect
+                      expandTrigger="hover"
+                      onChange={(value) => setAreaValue(item.id, value)}
+                    />
+                    <Button icon={<PlusOutlined />} onClick={() => addArea(item.id)}>
+                      添加
+                    </Button>
+                  </div>
+                </div>
+              </div>
             </section>
           ))}
 
diff --git a/management/src/pages/settings/outboundRobotSetting/style.less b/management/src/pages/settings/outboundRobotSetting/style.less
index 2f331cd..e2d3962 100644
--- a/management/src/pages/settings/outboundRobotSetting/style.less
+++ b/management/src/pages/settings/outboundRobotSetting/style.less
@@ -72,6 +72,25 @@
   width: min(520px, 100%);
 }
 
+.tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+  min-height: 32px;
+  margin-bottom: 10px;
+}
+
+.areaRow {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+  align-items: center;
+}
+
+.cascader {
+  width: min(420px, 100%);
+}
+
 .footer {
   display: flex;
   justify-content: flex-start;

--
Gitblit v1.7.1