Kaynağa Gözat

feat: 大司空2.0个人版关联联系人、移除联系人、升级产品

outaozhen 4 yıl önce
ebeveyn
işleme
9182431eb4

+ 3 - 1
src/components/ModalStore/index.tsx

@@ -20,6 +20,7 @@ import ReceiveLock from '@/pages/Product/Lock/LockStore/components/ReceiveLock'
 import CustomPerm from '@/pages/Customer/Company/components/CustomPerm'
 import MessageDrawer from '@/pages/Hr/Notification/components/MessageDrawer'
 import CloudDetail from '@/pages/Product/Cloud/components/Detail'
+import PersonalDetail from '@/pages/Product/Road/Personal/components/Detail'
 const modalMap = {
   M_CLIENT_ADD: AddClient, // 添加客户弹窗
   M_COMPANY_ADD: AddCompany, // 添加单位弹窗
@@ -40,7 +41,8 @@ const modalMap = {
   M_RECEIVE_LOCK: ReceiveLock, // 接受锁库弹窗
   M_CUSTOM_PERM: CustomPerm, // 自定义数据权限弹窗
   D_NOTICE_DETAIL: MessageDrawer, // 通知详情
-  D_CLOUD_DETAIL: CloudDetail // 云版详情
+  D_CLOUD_DETAIL: CloudDetail, // 云版详情
+  D_PERSONAL_DETAIL: PersonalDetail // 大司空2.0个人版详情
 }
 
 export const useModal = createModalHook<typeof modalMap>()

+ 2 - 1
src/models/refresh.js

@@ -8,7 +8,8 @@ export default {
     department: false,
     staffList: false,
     business: false,
-    cloud: false
+    cloud: false,
+    road: false
   },
   // 用于处理异步操作和业务逻辑,由action触发,但不能修改state
   effects: {

+ 8 - 7
src/pages/Product/Cloud/components/Detail/UpgradeModal.jsx

@@ -25,14 +25,15 @@ export const titleType = {
   DEADLINE: 5 // 限期
 }
 
+export const modalTitleEnum = {
+  1: '借出',
+  2: '销售',
+  3: '赠送',
+  4: '降级',
+  5: '限期'
+}
+
 const UpgradeModal = props => {
-  const modalTitleEnum = {
-    1: '借出',
-    2: '销售',
-    3: '赠送',
-    4: '降级',
-    5: '限期'
-  }
   const {
     visible,
     onCancel,

+ 93 - 0
src/pages/Product/Road/Personal/components/Detail/Form.jsx

@@ -0,0 +1,93 @@
+import React from 'react'
+import { Row, Col } from 'antd'
+import EditableForm from '@/components/EditableForm'
+
+const PersonalForm = props => {
+  const { cloudUser, updateKey, projectType } = props
+  const columns = [
+    {
+      dataIndex: 'mobile',
+      label: '手机',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'email',
+      label: '邮箱',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'username',
+      label: '称呼',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'qq',
+      label: 'QQ',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'real_name',
+      label: '真实姓名',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'create_time',
+      label: '注册云版',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'company',
+      label: '企业名称',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'province',
+      label: '企业地区',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'latest_usedName',
+      label: '最近使用',
+      editable: false,
+      span: 24
+    },
+    {
+      dataIndex: 'online_times',
+      label: '累计时长',
+      editable: false,
+      span: 24
+    }
+  ]
+  return (
+    <div>
+      <Row>
+        <Col span={8}>
+          <h2 className="text-gray-500">个人版用户</h2>
+        </Col>
+        <Col span={16} className="text-right text-gray-500">
+          创建于 {cloudUser.create_time}
+        </Col>
+        <Col span={22}>
+          <h2 className="text-2xl pb-4">{cloudUser.mobile}</h2>
+        </Col>
+        <Col span={2} />
+      </Row>
+      <EditableForm
+        dataSource={cloudUser}
+        columns={columns}
+        tartgetUrl="/cloud/update"
+        type={updateKey}
+      />
+    </div>
+  )
+}
+
+export default PersonalForm

+ 62 - 0
src/pages/Product/Road/Personal/components/Detail/LowerList.jsx

@@ -0,0 +1,62 @@
+import React from 'react'
+import { Tabs, List, Row, Col } from 'antd'
+import { dayjsFormat } from '@/utils/utils'
+import { servicelogEnum } from '@/pages/Customer/Client/components/ClientDetail/LowerList'
+
+const PersonalLowerList = props => {
+  const {
+    log: { log = [] },
+    serviceLog
+  } = props
+  const { TabPane } = Tabs
+  return (
+    <div>
+      <div className="pl-4">
+        <Tabs>
+          <TabPane tab="服务记录" key="服务记录">
+            <div className="sheet-panel-record">
+              <Row>
+                <Col span="8">类型/时间</Col>
+                <Col span="16">服务内容</Col>
+              </Row>
+              <List
+                dataSource={serviceLog}
+                split={false}
+                renderItem={item => (
+                  <List.Item>
+                    <Row className="w-full">
+                      <Col span="8">
+                        <a className="mr-1">@{item.staffName}</a>
+                        {servicelogEnum[item.status]}
+                        <List.Item.Meta description={dayjsFormat(item.date, 'YYYY-MM-DD')} />
+                      </Col>
+                      <Col span="16" className="whitespace-pre-line">
+                        {item.mark}
+                      </Col>
+                    </Row>
+                  </List.Item>
+                )}
+              />
+            </div>
+          </TabPane>
+          <TabPane tab="日志" key="日志">
+            <div className="sheet-panel-record">
+              <List
+                dataSource={log}
+                split={false}
+                renderItem={item => (
+                  <List.Item>
+                    <a>@{item.operatorName}</a> {item.content}
+                    <List.Item.Meta description={dayjsFormat(item.create_time)} />
+                  </List.Item>
+                )}
+              />
+            </div>
+          </TabPane>
+        </Tabs>
+      </div>
+    </div>
+  )
+}
+
+export default PersonalLowerList

+ 285 - 0
src/pages/Product/Road/Personal/components/Detail/TabList.jsx

@@ -0,0 +1,285 @@
+import React, { useState, useRef } from 'react'
+import { Button, Tabs, Tag, message } from 'antd'
+import ProTable from '@ant-design/pro-table'
+import consts from '@/consts'
+import { useDispatch } from 'dva'
+import { lockEnum } from '@/pages/Product/Cloud/components/Detail/TabList'
+import UpgradeModalv2 from './UpgradeModal'
+import {
+  upgradeTypeEnum,
+  lockTypeEnum,
+  titleType,
+  modalTitleEnum
+} from '@/pages/Product/Cloud/components/Detail/UpgradeModal'
+import { apiRoadPricingUpgradeV2 } from '@/services/product'
+
+const PersonalTabList = props => {
+  const {
+    compilationList,
+    cloudUser: { online_list = [], mobile, username },
+    projectType,
+    ssoId
+  } = props
+  const isUpgradeEnum = {
+    true: '已升级',
+    undefined: ''
+  }
+  const { TabPane } = Tabs
+  const dispatch = useDispatch()
+  const tRef = useRef(null)
+  const [roadPricingUpgradev2, setRoadPricingUpgradev2] = useState({
+    type: '',
+    compilationId: '',
+    compilationName: '',
+    upgradeTypeEnum: '',
+    compilationListName: '',
+    deadline: '',
+    lockTypeEnum: '',
+    visible: false,
+    loading: false
+  })
+  const handleRoadPricingUpgradev2 = async values => {
+    setRoadPricingUpgradev2({ ...roadPricingUpgradev2, loading: true })
+    const { code = -1 } = await apiRoadPricingUpgradeV2({
+      ...values,
+      ssoId
+    })
+    if (code === consts.RET_CODE.SUCCESS) {
+      message.success('新增成功')
+      // 请求完了
+      setRoadPricingUpgradev2({ ...roadPricingUpgradev2, loading: false, visible: false })
+      // 刷新数据
+      dispatch({
+        type: 'refresh/commitAction',
+        payload: 'road'
+      })
+    }
+  }
+  const columns = [
+    {
+      title: '产品',
+      dataIndex: 'name',
+      width: '10%',
+      render: (_, record) => <Tag color="purple">{record.name}</Tag>
+    },
+    {
+      title: '状态',
+      dataIndex: 'lock',
+      onFilter: true,
+      width: '8%',
+      render: lock => <span>{lockEnum[lock]}</span>
+    },
+    {
+      title: '专业版',
+      dataIndex: 'isUpgrade',
+      width: '10%',
+      render: isUpgrade => <span>{isUpgradeEnum[isUpgrade]}</span>
+    },
+    {
+      title: '限期',
+      dataIndex: 'deadline',
+      width: '10%'
+    },
+    {
+      title: '操作',
+      width: '25%',
+      render: (_, record) => (
+        <>
+          <Button
+            type="primary"
+            ghost
+            size="small"
+            className="m-2px"
+            onClick={() =>
+              setRoadPricingUpgradev2({
+                ...setRoadPricingUpgradev2,
+                visible: true,
+                type: titleType.GIVE,
+                // eslint-disable-next-line no-underscore-dangle
+                compilationId: record._id,
+                compilationName: record.name,
+                lockTypeEnum: lockTypeEnum.GIVE,
+                upgradeTypeEnum: upgradeTypeEnum.UPGRADE
+              })
+            }>
+            赠送
+          </Button>
+          {record.lock === 1 ? (
+            <>
+              <Button
+                type="primary"
+                ghost
+                size="small"
+                className="m-2px"
+                onClick={() =>
+                  setRoadPricingUpgradev2({
+                    ...setRoadPricingUpgradev2,
+                    visible: true,
+                    type: titleType.SALE,
+                    // eslint-disable-next-line no-underscore-dangle
+                    compilationId: record._id,
+                    compilationName: record.name,
+                    lockTypeEnum: lockTypeEnum.SALE,
+                    upgradeTypeEnum: upgradeTypeEnum.UPGRADE
+                  })
+                }>
+                销售
+              </Button>
+            </>
+          ) : null}
+          {record.isUpgrade ? (
+            <>
+              <Button
+                type="primary"
+                ghost
+                size="small"
+                className="m-2px"
+                onClick={() =>
+                  setRoadPricingUpgradev2({
+                    ...setRoadPricingUpgradev2,
+                    visible: true,
+                    type: titleType.DEMOTION,
+                    // eslint-disable-next-line no-underscore-dangle
+                    compilationId: record._id,
+                    compilationName: record.name,
+                    compilationListName: record.name,
+                    upgradeTypeEnum: upgradeTypeEnum.DEMOTION
+                  })
+                }>
+                降级
+              </Button>
+              <Button
+                type="primary"
+                ghost
+                danger
+                size="small"
+                onClick={() =>
+                  setRoadPricingUpgradev2({
+                    ...setRoadPricingUpgradev2,
+                    visible: true,
+                    type: titleType.DEADLINE,
+                    deadline: record.deadline,
+                    // eslint-disable-next-line no-underscore-dangle
+                    compilationId: record._id,
+                    compilationName: record.name,
+                    compilationListName: record.name,
+                    lockTypeEnum: record.lock,
+                    upgradeTypeEnum: upgradeTypeEnum.DEADLINE
+                  })
+                }>
+                限期
+              </Button>
+            </>
+          ) : (
+            <>
+              <Button
+                type="primary"
+                ghost
+                size="small"
+                className="m-2px"
+                onClick={() =>
+                  setRoadPricingUpgradev2({
+                    ...setRoadPricingUpgradev2,
+                    visible: true,
+                    type: titleType.LEND,
+                    // eslint-disable-next-line no-underscore-dangle
+                    compilationId: record._id,
+                    compilationName: record.name,
+                    lockTypeEnum: lockTypeEnum.LEND,
+                    upgradeTypeEnum: upgradeTypeEnum.UPGRADE
+                  })
+                }>
+                借出
+              </Button>
+              <Button
+                type="primary"
+                ghost
+                size="small"
+                className="m-2px"
+                onClick={() =>
+                  setRoadPricingUpgradev2({
+                    ...setRoadPricingUpgradev2,
+                    visible: true,
+                    type: titleType.SALE,
+                    // eslint-disable-next-line no-underscore-dangle
+                    compilationId: record._id,
+                    compilationName: record.name,
+                    lockTypeEnum: lockTypeEnum.SALE,
+                    upgradeTypeEnum: upgradeTypeEnum.UPGRADE
+                  })
+                }>
+                销售
+              </Button>
+            </>
+          )}
+        </>
+      )
+    }
+  ]
+  const columnOnline = [
+    {
+      title: '日期',
+      dataIndex: 'dateString',
+      width: '12%'
+    },
+    {
+      title: '时长',
+      dataIndex: 'online_times',
+      width: '17%'
+    }
+  ]
+  return (
+    <div>
+      <div className="pl-15px">
+        <Tabs>
+          <TabPane tab="个人版" key="个人版">
+            <div className="sheet-right-panel" ref={tRef}>
+              <ProTable
+                size="small"
+                columns={columns}
+                search={false}
+                toolBarRender={false}
+                // eslint-disable-next-line no-underscore-dangle
+                rowKey={record => record._id}
+                dataSource={compilationList}
+                pagination={false}
+              />
+            </div>
+          </TabPane>
+          <TabPane tab="在线时长" key="在线时长">
+            <div className="sheet-right-panel">
+              <ProTable
+                size="small"
+                columns={columnOnline}
+                search={false}
+                toolBarRender={false}
+                // eslint-disable-next-line no-underscore-dangle
+                rowKey={record => record._id}
+                dataSource={online_list}
+                pagination={false}
+              />
+            </div>
+          </TabPane>
+        </Tabs>
+      </div>
+      <UpgradeModalv2
+        onConfirm={handleRoadPricingUpgradev2}
+        loading={roadPricingUpgradev2.loading}
+        visible={roadPricingUpgradev2.visible}
+        type={roadPricingUpgradev2.type}
+        onCancel={() => setRoadPricingUpgradev2({ ...roadPricingUpgradev2, visible: false })}
+        projectType={projectType}
+        ssoId={ssoId}
+        cloudUser={{ mobile, username }}
+        compilationId={roadPricingUpgradev2.compilationId}
+        compilationName={roadPricingUpgradev2.compilationName}
+        lock={roadPricingUpgradev2.lockTypeEnum}
+        upgradeType={roadPricingUpgradev2.upgradeTypeEnum}
+        compilationListName={roadPricingUpgradev2.compilationListName}
+        deadline={roadPricingUpgradev2.deadline}
+      />
+    </div>
+  )
+}
+
+export default PersonalTabList

+ 123 - 0
src/pages/Product/Road/Personal/components/Detail/UpgradeModal.jsx

@@ -0,0 +1,123 @@
+import React, { useEffect, useState } from 'react'
+import { Modal, Form, Switch, DatePicker } from 'antd'
+// import dayjs from 'dayjs'
+import { dayjsFormat } from '@/utils/utils'
+import { useDispatch } from 'umi'
+import dayjs from 'dayjs'
+import {
+  upgradeTypeEnum,
+  lockTypeEnum,
+  titleType,
+  modalTitleEnum
+} from '@/pages/Product/Cloud/components/Detail/UpgradeModal'
+
+const UpgradeModal = props => {
+  const {
+    visible,
+    onCancel,
+    loading,
+    onConfirm,
+    type,
+    projectType,
+    ssoId,
+    compilationId,
+    compilationName,
+    compilationListName,
+    lock,
+    upgradeType,
+    cloudUser,
+    deadline
+  } = props
+  const [form] = Form.useForm()
+  const dispatch = useDispatch()
+  const [showDeadline, setShowDeadline] = useState(false)
+  const layout = {
+    layout: 'vertical'
+  }
+  useEffect(() => {
+    if (upgradeType === upgradeTypeEnum.DEADLINE) {
+      form?.setFieldsValue({ deadline: dayjs(deadline) })
+      setShowDeadline(true)
+    }
+  }, [upgradeType])
+
+  const onChange = value => {
+    setShowDeadline(value)
+  }
+  const handleonOk = () => {
+    form.validateFields().then(values => {
+      const newVal = { ...values }
+      if (values.deadline) {
+        newVal.deadline = dayjsFormat(values.deadline, 'YYYY-MM-DD')
+      }
+      onConfirm({
+        ...newVal,
+        projectType,
+        ssoId,
+        compilationId,
+        compilationName,
+        compilationListName,
+        lock,
+        upgradeType
+      })
+      form.resetFields()
+      dispatch({
+        type: 'refresh/commitAction',
+        payload: 'road'
+      })
+    })
+  }
+  return (
+    <Modal
+      getContainer={false}
+      width={800}
+      title={`确认${modalTitleEnum[type]}`}
+      visible={visible}
+      confirmLoading={loading}
+      onCancel={() => {
+        setShowDeadline(false)
+        onCancel()
+        form?.resetFields()
+      }}
+      onOk={handleonOk}>
+      {type === lockTypeEnum.GIVE || type === lockTypeEnum.LEND || type === lockTypeEnum.SALE ? (
+        <div className="mb-6">
+          <p className="pb-3">
+            为用户<b>{cloudUser.mobile}</b>,<b>{cloudUser.username}</b> {modalTitleEnum[type]}{' '}
+            <b>{compilationName}</b>
+          </p>
+          <div className="pb-5">
+            <Switch onChange={onChange} checked={showDeadline} />
+            <span className="ml-2">限期</span>
+          </div>
+        </div>
+      ) : null}
+
+      {type === titleType.DEMOTION ? (
+        <div className="mb-6">
+          未用户<b>{cloudUser.mobile}</b>,<b>{cloudUser.username}</b> 降级 <b>{cloudUser.name}</b>{' '}
+          <b>{compilationListName}</b>
+        </div>
+      ) : null}
+      {type === titleType.DEADLINE ? (
+        <div className="mb-6">
+          未用户<b>{cloudUser.mobile}</b>,<b>{cloudUser.username}</b> <b>{cloudUser.name}</b>{' '}
+          <b>{compilationListName}</b> 设置延期
+          <div className="pt-5 pb-5">
+            当前限期为 <b>{deadline}</b>
+          </div>
+        </div>
+      ) : null}
+
+      {type !== titleType.DEMOTION ? (
+        <Form {...layout} form={form}>
+          <Form.Item name="deadline" label="到期时间">
+            <DatePicker style={{ width: '100%' }} disabled={!showDeadline} />
+          </Form.Item>
+        </Form>
+      ) : null}
+    </Modal>
+  )
+}
+
+export default UpgradeModal

+ 154 - 0
src/pages/Product/Road/Personal/components/Detail/index.jsx

@@ -0,0 +1,154 @@
+import React, { useState, useEffect } from 'react'
+import { LinkOne, LinkInterrupt } from '@icon-park/react'
+import { Row, Col, Button, Tooltip, Spin, Modal, Drawer } from 'antd'
+import { connect } from 'umi'
+import consts from '@/consts'
+import { apiRoadpricingDetailV2, apiRoadPricingUnLinkClientV2 } from '@/services/product'
+import Form from './Form'
+import LowerList from './LowerList'
+import TabList from './TabList'
+import ClientDetail from '@/pages/Customer/Client/components/ClientDetail/Form'
+import { useModal } from '@/components/ModalStore'
+
+const PersonalDetail = props => {
+  const {
+    dispatch,
+    updateKey = 'road',
+    refresh,
+    visible,
+    dataId = '',
+    projectType,
+    filterTag = true,
+    ...resetDrawerProps
+  } = props
+  const [state, setState] = useState({
+    loading: false,
+    cloudUser: {},
+    compilationList: [],
+    log: [],
+    serviceLog: [],
+    client: {}
+  })
+  const dispatchModal = useModal()
+  const shouldUpdate = refresh?.[updateKey] || false
+  const refreshClient = () => {
+    dispatch({
+      type: 'refresh/commitAction',
+      payload: 'road'
+    })
+  }
+  const initData = async id => {
+    setState({ ...state, loading: true })
+    const {
+      data: { cloudUser = {}, compilationList = [], log = [], serviceLog = [], client = {} },
+      code = -1
+    } = await apiRoadpricingDetailV2({ ssoId: id, projectType })
+    if (code === consts.RET_CODE.SUCCESS) {
+      if (shouldUpdate) {
+        dispatch({
+          type: 'refresh/commitAction',
+          payload: updateKey
+        })
+      }
+      setState({ ...state, cloudUser, compilationList, log, serviceLog, client, loading: false })
+    }
+  }
+  const handleConnectClient = () => {
+    dispatchModal('M_CONNECT_CLIENT', {
+      onSelect: refreshClient,
+      dataId: state.cloudUser.ssoId,
+      preUrl: 'RoadPersonal',
+      showFooter: false,
+      otherParams: { projectType }
+    })
+  }
+  // 移除cld客户
+  const pricingUnLinkClient = clientId => {
+    Modal.confirm({
+      zIndex: 1002,
+      title: '确认移除',
+      onOk: async () => {
+        const { code = -1 } = await apiRoadPricingUnLinkClientV2({
+          id: dataId,
+          clientId,
+          projectType
+        })
+        if (code === consts.RET_CODE.SUCCESS) {
+          dispatch({
+            type: 'refresh/commitAction',
+            payload: updateKey
+          })
+        }
+      }
+    })
+  }
+  useEffect(() => {
+    shouldUpdate && initData(dataId)
+  }, [shouldUpdate])
+  useEffect(() => {
+    visible && initData(dataId)
+  }, [visible])
+  return (
+    <Drawer {...resetDrawerProps} visible={visible} className="zh-drawer">
+      <Spin spinning={state.loading}>
+        <div className="sheet-box">
+          <Row>
+            <Col span={9} className="sheet-box-left">
+              <div className="sheet-left-panel pr-4">
+                <Form cloudUser={state.cloudUser} updateKey={updateKey} projectType={projectType} />
+                {state.cloudUser.cld?.clientId ? (
+                  <>
+                    <div className="mt-4">
+                      <ClientDetail client={state.client} filterTag={filterTag} />
+                    </div>
+                    <div className="text-center mt-6">
+                      <Tooltip placement="right" title="移除CLD客户">
+                        <Button
+                          type="primary"
+                          ghost
+                          size="small"
+                          onClick={() => {
+                            pricingUnLinkClient(state.cloudUser.cld?.clientId)
+                          }}>
+                          <LinkInterrupt size="14" />
+                          <span className="ml-5px">移除CLD客户</span>
+                        </Button>
+                      </Tooltip>
+                    </div>
+                  </>
+                ) : (
+                  <div className="text-center mt-6">
+                    <Button type="primary" ghost size="small" onClick={handleConnectClient}>
+                      <LinkOne size="14" />
+                      <span className="ml-5px">关联CLD客户</span>
+                    </Button>
+                  </div>
+                )}
+              </div>
+            </Col>
+            <Col
+              span={15}
+              // sm={{ span: 24 }}
+              // md={{ span: 24 }}
+              // lg={{ span: 15 }}
+              // xl={{ span: 15 }}
+              flex={{ flexDirection: 'column' }}
+              className="sheet-box-right">
+              <TabList
+                compilationList={state.compilationList}
+                cloudUser={state.cloudUser}
+                projectType={projectType}
+                ssoId={state.cloudUser.ssoId}
+              />
+              <LowerList log={state.log} serviceLog={state.serviceLog} />
+            </Col>
+          </Row>
+        </div>
+      </Spin>
+    </Drawer>
+  )
+}
+
+export default connect(({ refresh }) => ({
+  refresh
+}))(PersonalDetail)

+ 15 - 1
src/pages/Product/Road/Personal/index.jsx

@@ -5,10 +5,12 @@ import { queryRoadpricingListV2 } from '@/services/product'
 import consts from '@/consts'
 import { useLocation, useSelector, useDispatch, connect } from 'umi'
 import { Input, Tooltip, Tag } from 'antd'
+import { useModal } from '@/components/ModalStore'
 
 const Personal = props => {
   const { compilationv2, provincev2 } = props
   const dispatch = useDispatch()
+  const dispatchModal = useModal()
   const tRef = useRef()
   const [state, setState] = useState({
     params: {
@@ -40,7 +42,19 @@ const Personal = props => {
       dataIndex: 'mobile',
       key: 'mobile',
       width: 110,
-      fixed: 'left'
+      fixed: 'left',
+      render: (text, record) => (
+        <span
+          onClick={() =>
+            dispatchModal('D_PERSONAL_DETAIL', {
+              dataId: record.ssoId,
+              projectType: 1
+            })
+          }
+          className="text-primary cursor-pointer hover:text-[#967bbd]">
+          {text}
+        </span>
+      )
     },
     {
       title: '称呼',

+ 3 - 0
src/services/customer.js

@@ -231,6 +231,9 @@ export async function apiChangeClient(preUrl, params) {
   if (preUrl === 'RoadPricing') {
     url = '/RoadPricing/link/client'
   }
+  if (preUrl === 'RoadPersonal') {
+    url = '/RoadPricingv2/link/client'
+  }
   return request(url, {
     method: 'POST',
     data: params

+ 22 - 0
src/services/product.js

@@ -135,3 +135,25 @@ export async function queryProvinceListV2(params) {
     params
   })
 }
+/** 大司空2.0获得云版详情 */
+export async function apiRoadpricingDetailV2(params) {
+  return request('/RoadPricingv2/detail', { params })
+}
+/** 大司空2.0云版关联客户 */
+export async function apiRoadPricingLinkClientV2(params) {
+  return request('/RoadPricingv2/link/client', {
+    method: 'POST',
+    data: params
+  })
+}
+/** 大司空2.0云版移除客户 */
+export async function apiRoadPricingUnLinkClientV2(params) {
+  return request('/RoadPricingv2/unlink/client', {
+    method: 'POST',
+    data: params
+  })
+}
+/** 设云版置升级产品 */
+export async function apiRoadPricingUpgradeV2(payload) {
+  return request('/RoadPricingv2/upgrade', { method: 'POST', data: payload })
+}