二手回收后台,师傅端,用户端
刘帅
2026-09-11 71917fa3a5e723e10666d7c67aa5baddfa84c777
机器人设置更改
2个文件已修改
211 ■■■■■ 已修改文件
management/src/pages/settings/outboundRobotSetting/index.jsx 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/settings/outboundRobotSetting/style.less 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/settings/outboundRobotSetting/index.jsx
@@ -1,54 +1,25 @@
import { PageContainer } from '@ant-design/pro-components';
import { Button, Cascader, Checkbox, Empty, Input, message, Spin, Tag } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { useEffect, useMemo, useState } from 'react';
import { allAreaList } from '@/utils/area';
import { Button, Checkbox, Empty, message, Spin } from 'antd';
import { useEffect, useState } from 'react';
import { getList, update } from './service';
import styles from './style.less';
const PLATFORM_OPTIONS = [
  { label: '京东', value: 'jd' },
  { label: '淘宝', value: 'tm' },
  { label: '抖音', value: 'douyin' },
  { label: '拼多多', value: 'pdd' },
];
const commaTextToNumberArray = (value) =>
  value
    ? String(value)
        .split(',')
        .map((item) => Number(item.trim()))
        .filter(Number.isFinite)
    : [];
const commaTextToArray = (value) => (value ? String(value).split(',').filter(Boolean) : []);
const arraysEqual = (a = [], b = []) => a.length === b.length && a.join(',') === b.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 };
};
const arraysEqual = (a = [], b = []) =>
  a.length === b.length && [...a].sort().join(',') === [...b].sort().join(',');
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 [draftArea, setDraftArea] = useState({});
  const [siteOptions, setSiteOptions] = useState([]);
  const [originList, setOriginList] = useState([]);
  const loadList = async () => {
@@ -56,18 +27,18 @@
    try {
      const res = await getList();
      if (String(res?.code) === '200') {
        const list = (res.data || []).map((item) => ({
        const list = (res?.data?.robotSettings || []).map((item) => ({
          ...item,
          orderPlatformsArr: commaTextToArray(item.orderPlatforms),
          dialAreaCodesArr: commaTextToArray(item.dialAreaCodes),
          siteIds: commaTextToNumberArray(item.siteIds),
        }));
        setSiteOptions(
          (res?.data?.sites || []).map((item) => ({ label: item.siteName, value: item.id })),
        );
        setRobotList(list);
        setOriginList(
          list.map((item) => ({
            id: item.id,
            orderPlatformsArr: [...item.orderPlatformsArr],
            dialAreaCodesArr: [...item.dialAreaCodesArr],
            robotConfigInfo: item.robotConfigInfo || '',
            siteIds: [...item.siteIds],
          })),
        );
      } else {
@@ -82,41 +53,10 @@
    loadList();
  }, []);
  const setPlatformValue = (id, value) => {
    setRobotList((prev) => prev.map((item) => (item.id === id ? { ...item, orderPlatformsArr: value } : item)));
  };
  const setAreaValue = (id, value) => {
    setDraftArea((prev) => ({ ...prev, [id]: value }));
  };
  const addArea = (id) => {
    const value = draftArea[id];
    const code = Array.isArray(value) ? value[value.length - 1] : value;
    if (!code) {
      return;
    }
  const setSiteIds = (id, value) => {
    setRobotList((prev) =>
      prev.map((item) => {
        if (item.id !== id || item.dialAreaCodesArr.includes(code)) {
          return item;
        }
        return { ...item, dialAreaCodesArr: [...item.dialAreaCodesArr, code] };
      }),
      prev.map((item) => (item.id === id ? { ...item, siteIds: value } : item)),
    );
    setDraftArea((prev) => ({ ...prev, [id]: undefined }));
  };
  const removeArea = (id, area) => {
    setRobotList((prev) =>
      prev.map((item) =>
        item.id === id ? { ...item, dialAreaCodesArr: item.dialAreaCodesArr.filter((text) => text !== area) } : item,
      ),
    );
  };
  const setConfigInfo = (id, value) => {
    setRobotList((prev) => prev.map((item) => (item.id === id ? { ...item, robotConfigInfo: value } : item)));
  };
  const save = async () => {
@@ -125,11 +65,7 @@
      if (!origin) {
        return true;
      }
      return (
        !arraysEqual(origin.orderPlatformsArr, item.orderPlatformsArr) ||
        !arraysEqual(origin.dialAreaCodesArr, item.dialAreaCodesArr) ||
        (origin.robotConfigInfo || '') !== (item.robotConfigInfo || '')
      );
      return !arraysEqual(origin.siteIds, item.siteIds);
    });
    if (changedList.length === 0) {
@@ -142,9 +78,7 @@
      for (const item of changedList) {
        const res = await update({
          id: item.id,
          orderPlatforms: (item.orderPlatformsArr || []).join(','),
          dialAreaCodes: (item.dialAreaCodesArr || []).join(','),
          robotConfigInfo: item.robotConfigInfo || '',
          siteIds: item.siteIds || [],
        });
        if (String(res?.code) !== '200') {
          message.error(res?.msg || `机器人 ${item.robotNumber || item.id} 保存失败`);
@@ -163,8 +97,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}
@@ -173,7 +107,9 @@
            <section className={styles.robotBlock} key={item.id}>
              <div className={styles.robotHead}>
                <div className={styles.robotTitle}>{index + 1}号机器人</div>
                {item.updateTime ? <div className={styles.robotTime}>更新时间:{item.updateTime}</div> : null}
                {item.updateTime ? (
                  <div className={styles.robotTime}>更新时间:{item.updateTime}</div>
                ) : null}
              </div>
              <div className={styles.fieldRow}>
@@ -182,52 +118,13 @@
              </div>
              <div className={styles.fieldRow}>
                <div className={styles.label}>订单平台</div>
                <div className={styles.label}>可外呼站点</div>
                <div className={styles.value}>
                  <Checkbox.Group
                    className={styles.platformGroup}
                    options={PLATFORM_OPTIONS}
                    value={item.orderPlatformsArr}
                    onChange={(value) => setPlatformValue(item.id, value)}
                  />
                </div>
              </div>
              <div className={styles.fieldRow}>
                <div className={styles.label}>拨打区域</div>
                <div className={styles.value}>
                  <div className={styles.tags}>
                    {item.dialAreaCodesArr.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>
              <div className={styles.fieldRow}>
                <div className={styles.label}>机器人配置信息</div>
                <div className={styles.value}>
                  <Input.TextArea
                    value={item.robotConfigInfo}
                    onChange={(e) => setConfigInfo(item.id, e.target.value)}
                    placeholder="请输入机器人配置信息"
                    autoSize={{ minRows: 3, maxRows: 6 }}
                    className={styles.siteGroup}
                    options={siteOptions}
                    value={item.siteIds}
                    onChange={(value) => setSiteIds(item.id, value)}
                  />
                </div>
              </div>
management/src/pages/settings/outboundRobotSetting/style.less
@@ -7,20 +7,20 @@
}
.title {
  font-size: 18px;
  font-weight: 600;
  color: #1f1f1f;
  font-weight: 600;
  font-size: 18px;
}
.subTitle {
  margin-top: 6px;
  font-size: 13px;
  color: #8c8c8c;
  font-size: 13px;
}
.robotBlock {
  padding: 18px 20px 20px;
  margin-bottom: 18px;
  padding: 18px 20px 20px;
  background: #fff;
  border: 1px solid #f0f0f0;
  border-radius: 8px;
@@ -28,23 +28,23 @@
.robotHead {
  display: flex;
  gap: 16px;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  padding-bottom: 10px;
  border-bottom: 1px solid #f0f0f0;
}
.robotTitle {
  font-size: 15px;
  font-weight: 600;
  color: #111;
  font-weight: 600;
  font-size: 15px;
}
.robotTime {
  font-size: 12px;
  color: #8c8c8c;
  font-size: 12px;
  white-space: nowrap;
}
@@ -58,45 +58,25 @@
.label {
  padding-top: 4px;
  line-height: 22px;
  text-align: right;
  color: #444;
  line-height: 22px;
  white-space: nowrap;
  text-align: right;
}
.value {
  min-width: 0;
}
.platformGroup {
.siteGroup {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  padding-top: 4px;
}
.platformGroup :global(.ant-checkbox-wrapper) {
.siteGroup :global(.ant-checkbox-wrapper) {
  margin-inline-start: 0;
}
.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;
  margin-top: 2px;
}
.cascader {
  width: min(420px, 100%);
}
.footer {