二手回收后台,师傅端,用户端
刘帅
2026-09-09 141b9a77d488e4c2d83159665ac3f9cc6f687218
通话记录接口调整
2个文件已修改
271 ■■■■■ 已修改文件
management/src/pages/order/callRecords/index.jsx 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/order/callRecords/service.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/order/callRecords/index.jsx
@@ -1,199 +1,206 @@
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { DatePicker, Select, Tag } from 'antd';
import { useRef } from 'react';
import { maskPhoneNumber } from '@/utils/utils';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { DatePicker, Input, message, Select, Tag, Typography } from 'antd';
import moment from 'moment';
import { useRef } from 'react';
import { getCallRecords } from './service';
const { RangePicker } = DatePicker;
const intentionOptions = ['A', 'B', 'C', 'D', 'E', 'F', 'G'].map((item) => ({
  label: item,
  value: item,
}));
const callTypeOptions = [
  { label: '呼入', value: 'callin' },
  { label: '外呼', value: 'callout' },
  { label: '双向呼叫', value: 'twoWayCall' },
  { label: '智能外呼', value: 'autoCallout' },
  { label: '外呼任务', value: 'callTask' },
];
const callTypeLabels = Object.fromEntries(
  callTypeOptions.map(({ label, value }) => [value, label]),
);
const formatDateTime = (value) => {
  if (!value) {
    return '';
  }
  if (typeof value === 'string') {
    return value;
  }
  if (typeof value.format === 'function') {
    return value.format('YYYY-MM-DD HH:mm:ss');
  }
  return '';
  if (!value) return '';
  return typeof value.format === 'function' ? value.format('YYYY-MM-DD HH:mm:ss') : value;
};
const normalizeSearchParams = (params) => {
  const { current, pageSize, created_time, intention, ...rest } = params;
  const [startTime, endTime] = Array.isArray(created_time) ? created_time : [];
  const { current, pageSize, timeRange, ...rest } = params;
  const [startTime, endTime] = Array.isArray(timeRange) ? timeRange : [];
  return {
    ...rest,
    created_time: startTime && endTime ? `${formatDateTime(startTime)}~${formatDateTime(endTime)}` : '',
    intention: Array.isArray(intention) ? intention.join(',') : intention || '',
    page: current || 1,
    pagesize: pageSize || 10,
    startTime: formatDateTime(startTime),
    endTime: formatDateTime(endTime),
    page: current > 0 ? current : 1,
    pageSize: pageSize > 0 ? pageSize : 1000,
  };
};
const renderText = (text) => text || '-';
const CallRecords = () => {
  const actionRef = useRef();
  const defaultTimeRange = [moment().subtract(6, 'days').startOf('day'), moment().endOf('day')];
  const columns = [
    {
      title: '呼叫时间',
      dataIndex: 'created_time',
      width: 180,
      title: '查询时间',
      dataIndex: 'timeRange',
      width: 260,
      renderFormItem: () => (
        <RangePicker
          showTime
          format="YYYY-MM-DD HH:mm:ss"
          style={{ width: 380 }}
        />
        <RangePicker showTime format="YYYY-MM-DD HH:mm:ss" style={{ width: '100%' }} />
      ),
    },
    {
      title: '任务ID',
      dataIndex: 'task_id',
      width: 100,
    },
    {
      title: '任务名称',
      dataIndex: 'task_name',
      width: 160,
      hideInSearch: true,
    },
    {
      title: '手机号',
      dataIndex: 'phone',
      width: 140,
      render: (_, record) => maskPhoneNumber(record.phone),
    },
    {
      title: '关键词',
      dataIndex: 'key_word',
      formItemProps: { rules: [{ required: true, message: '请选择查询时间' }] },
      hideInTable: true,
    },
    {
      title: '意向等级',
      dataIndex: 'intention',
      width: 100,
      title: '呼叫类型',
      dataIndex: 'callType',
      width: 130,
      renderFormItem: () => (
        <Select
          mode="multiple"
          allowClear
          placeholder="请选择意向等级"
          options={intentionOptions}
        />
        <Select mode="multiple" allowClear options={callTypeOptions} placeholder="请选择呼叫类型" />
      ),
      render: (_, record) => record.intention ? <Tag color="blue">{record.intention}</Tag> : '-',
      render: (text) => <Tag color="blue">{callTypeLabels[text] || text || '-'}</Tag>,
    },
    {
      title: '类型',
      dataIndex: 'sys_type',
      title: '客户号码',
      dataIndex: 'customerNumber',
      width: 140,
      render: (text) => maskPhoneNumber(text) || '-',
    },
    { title: '外显号码', dataIndex: 'disNumber', width: 140, render: renderText },
    { title: '服务号码', dataIndex: 'serviceNumber', width: 140, render: renderText },
    {
      title: '通话状态',
      dataIndex: 'status',
      width: 140,
      renderFormItem: () => <Input placeholder="如 ANSWER" />,
      render: renderText,
    },
    {
      title: '通话 ID',
      dataIndex: 'callId',
      width: 220,
      hideInSearch: true,
      ellipsis: true,
      render: renderText,
    },
    {
      title: '座席名称',
      dataIndex: 'agentName',
      width: 120,
      hideInSearch: true,
      valueEnum: {
        1: { text: 'AI外呼记录' },
        2: { text: '群呼记录' },
      },
      render: renderText,
    },
    {
      title: '座席工号',
      dataIndex: 'agentNumber',
      width: 120,
      hideInSearch: true,
      render: renderText,
    },
    { title: '服务组', dataIndex: 'queueName', width: 140, hideInSearch: true, render: renderText },
    {
      title: '开始时间',
      dataIndex: 'startTime',
      width: 180,
      hideInSearch: true,
      render: renderText,
    },
    {
      title: '接通时间',
      dataIndex: 'answered_time',
      dataIndex: 'answerTime',
      width: 180,
      hideInSearch: true,
      render: (text) => text || '-',
      render: renderText,
    },
    { title: '结束时间', dataIndex: 'endTime', width: 180, hideInSearch: true, render: renderText },
    {
      title: '挂机时间',
      dataIndex: 'hungup_time',
      width: 180,
      hideInSearch: true,
      render: (text) => text || '-',
    },
    {
      title: '通话时长(秒)',
      dataIndex: 'billsec',
      width: 120,
      hideInSearch: true,
      render: (text) => text || '-',
    },
    {
      title: '呼叫总时间(秒)',
      dataIndex: 'duration',
      title: '通话时长(秒)',
      dataIndex: 'callDuration',
      width: 130,
      hideInSearch: true,
      render: (text) => text || '-',
      render: renderText,
    },
    {
      title: '通话轮次',
      dataIndex: 'cti_asr_call_count',
      width: 100,
      title: '排队时长(秒)',
      dataIndex: 'queueDuration',
      width: 130,
      hideInSearch: true,
      render: (text) => text || '-',
      render: renderText,
    },
    {
      title: '是否转人工',
      dataIndex: 'bridge_uuid',
      title: '挂机方',
      dataIndex: 'hangUpParty',
      width: 110,
      hideInSearch: true,
      render: (text) => text ? <Tag color="green">是</Tag> : <Tag>否</Tag>,
      render: renderText,
    },
    {
      title: '是否查看',
      dataIndex: 'is_eyes',
      width: 100,
      hideInSearch: true,
      valueEnum: {
        1: { text: '未查看', status: 'Warning' },
        2: { text: '已查看', status: 'Success' },
      },
    },
    {
      title: '挂断原因',
      dataIndex: 'hangup_cause',
      width: 160,
      hideInSearch: true,
      ellipsis: true,
      render: (text) => text || '-',
    },
    {
      title: '录音文件',
      dataIndex: 'record_filename',
      title: '失败原因',
      dataIndex: 'failReasonMsg',
      width: 180,
      hideInSearch: true,
      ellipsis: true,
      render: (text) => text || '-',
      render: renderText,
    },
    {
      title: '通话UUID',
      dataIndex: 'uuid',
      width: 240,
      title: '通话录音',
      dataIndex: 'recordUrl',
      width: 120,
      hideInSearch: true,
      ellipsis: true,
      render: (url) =>
        url ? (
          <Typography.Link href={url} target="_blank">
            播放录音
          </Typography.Link>
        ) : (
          '-'
        ),
    },
    {
      title: '留言录音',
      dataIndex: 'leaveMsgUrl',
      width: 120,
      hideInSearch: true,
      render: (url) =>
        url ? (
          <Typography.Link href={url} target="_blank">
            播放录音
          </Typography.Link>
        ) : (
          '-'
        ),
    },
  ];
  return (
    <PageContainer title="通话记录">
      <ProTable
        rowKey="id"
        rowKey="callId"
        actionRef={actionRef}
        columns={columns}
        form={{ initialValues: { timeRange: defaultTimeRange } }}
        search={{ defaultCollapsed: false }}
        scroll={{ x: 2000 }}
        pagination={{
          showSizeChanger: true,
          showQuickJumper: true,
          defaultPageSize: 10,
        }}
        scroll={{ x: 2600 }}
        pagination={{ showSizeChanger: true, showQuickJumper: true, defaultPageSize: 20 }}
        request={async (params) => {
          const response = await getCallRecords(normalizeSearchParams(params));
          const requestData = normalizeSearchParams(params);
          const start = moment(requestData.startTime, 'YYYY-MM-DD HH:mm:ss', true);
          const end = moment(requestData.endTime, 'YYYY-MM-DD HH:mm:ss', true);
          if (!start.isValid() || !end.isValid() || end.isBefore(start)) {
            message.error('请选择有效的查询时间范围');
            return { data: [], total: 0, success: false };
          }
          if (end.diff(start, 'seconds') > 7 * 24 * 60 * 60) {
            message.error('查询时间跨度不能超过 7 天');
            return { data: [], total: 0, success: false };
          }
          const response = await getCallRecords(requestData);
          return {
            data: response?.data?.list || [],
            total: response?.data?.total || 0,
management/src/pages/order/callRecords/service.js
@@ -1,8 +1,8 @@
import { request } from '@umijs/max';
// 呼大侠通话记录列表
// Useasy 通话记录列表
export const getCallRecords = async (data) => {
  return request('/hudaxia/callRecords', {
  return request('/admin/useasy/callRecords', {
    method: 'POST',
    data,
  });