| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- import { Input, Button, message, Tooltip } from 'antd'
- import { connect, useAccess, useModel } from 'umi'
- import React, { useEffect, useState, useRef, useMemo } from 'react'
- import consts from '@/consts'
- import LazyCascader, { formatValues } from '@/components/LazyCascader'
- import PersonLabel from '../Company/components/PersonLabel'
- import { TagTypeEnum, TagDataTypeEnum, LabelModeType } from '../Company/components/PersonLabel/const'
- import { Add, Down, Check } from '@icon-park/react'
- import { apiAddClient, queryClient } from '@/services/customer'
- import { apiBatchLink } from '@/services/customer'
- import styles from './index.less'
- import { generateFilterField, generateSortField } from '@/utils/utils'
- import { PermDataTypeEunm } from '../Company/components/PermSelect'
- import BasicTable from '@/components/Table'
- import { getPermAuthCache } from '@/utils/auth'
- import { useModal } from '@/components/ModalStore'
- import { Plus } from '@icon-park/react'
- const Client = props => {
- const dispatchModal = useModal()
- const {
- personTagColorMap,
- teamTagColorMap,
- personTags,
- teamTags,
- dispatch,
- shouldUpdate,
- loading,
- sourceList
- } = props
- const { initialState: { permData } = { permData: {} } } = useModel('@@initialState')
- const hasAddPerm = useAccess()?.validatePermByType('client_add') || false
- const tRef = useRef()
- const [tagState, setTagState] = useState({
- tagIds: [],
- tagCooperationIds: []
- })
- const [state, setState] = useState({
- params: {},
- orderIds: []
- })
- const tag = useMemo(() => {
- const personTagMap = {}
- const teamTagMap = {}
- const personOptions = []
- const teamOptions = []
- personTags.forEach(item => {
- // personOptions.push({ label: item.name, value: item.id })
- personTagMap[item.id] = {
- text: (
- <>
- <span
- className="w-12px h-12px inline-block rounded-1/2 mr-3px"
- style={{ backgroundColor: personTagColorMap[item.id] }}
- />
- <span>{item.name}</span>
- </>
- )
- }
- })
- teamTags.forEach(item => {
- // teamOptions.push({ label: item.name, value: item.id })
- teamTagMap[item.id] = {
- text: (
- <>
- <span
- className="w-12px h-12px inline-block mr-3px"
- style={{ backgroundColor: teamTagColorMap[item.id] }}
- />
- <span>{item.name}</span>
- </>
- )
- }
- })
- return { personTagMap, teamTagMap, personOptions, teamOptions }
- }, [loading, shouldUpdate])
- // 默认刷新一次列表请求数据
- useEffect(() => {
- if (!sourceList?.length) {
- dispatch({
- type: 'client/fetchSourceList'
- })
- }
- if (!personTags.length) {
- dispatch({
- type: 'client/fetchPersonTags',
- payload: { tagType: TagTypeEnum.PERSONTAG, tagColumn: TagDataTypeEnum.CLIENT }
- })
- }
- if (!teamTags.length) {
- dispatch({
- type: 'client/fetchTeamTags',
- payload: { tagType: TagTypeEnum.TEAMTAG, tagColumn: TagDataTypeEnum.CLIENT }
- })
- }
- if (shouldUpdate) {
- tRef.current.reload()
- }
- }, [shouldUpdate])
- const toolbarOptionsChange = (type, ids) => {
- setTagState({ ...tagState, [type]: ids })
- }
- const [defaultPermAuthCache] = getPermAuthCache(PermDataTypeEunm.CUSTOMER)
- // 重置到默认值,包括表单
- const initData = () => {
- tRef.current?.reset()
- }
- // 刷新
- const refreshData = () => {
- tRef.current?.reload()
- }
- const handleAddClient = async values => {
- const payload = formatValues(values)
- const { code = -1, msg = '新增失败' } = await apiAddClient(payload)
- if (code === consts.RET_CODE.SUCCESS) {
- message.success(msg)
- initData()
- }
- return code === consts.RET_CODE.SUCCESS
- }
- const columns = [
- {
- title: '客户',
- dataIndex: 'clientName',
- key: 'clientName',
- width: 80,
- fixed: 'left',
- render: (clientName, record) => (
- <span
- onClick={() => dispatchModal('D_CLIENT_DETAIL', { dataId: record.id, orderIds: state.orderIds })}
- className="text-primary cursor-pointer hover:text-hex-967bbd">
- {clientName}
- </span>
- ),
- sorter: true,
- search: false
- },
- {
- title: '单位名称',
- dataIndex: 'companyName',
- key: 'companyName',
- width: 200,
- // ellipsis: true,
- render: (companyName, record) =>
- record.companyId ? (
- <span
- onClick={() => {
- if (record.companyId !== consts.ENCRYPTION_ZERO) {
- dispatchModal('D_COMPANY_DETAIL', {
- updateKey: 'client',
- dataId: record.companyId,
- orderIds: state.orderIds
- })
- }
- }}
- className="text-primary cursor-pointer hover:text-hex-967bbd">
- {companyName}
- </span>
- ) : (
- '-'
- ),
- sorter: true,
- search: false
- },
- {
- title: '部门',
- dataIndex: 'department',
- key: 'department',
- ellipsis: true,
- width: 70,
- search: false
- },
- {
- title: '职务',
- dataIndex: 'position',
- key: 'position',
- width: 75,
- search: false
- },
- {
- title: '办公室',
- dataIndex: 'office',
- key: 'office',
- width: 90,
- ellipsis: true,
- search: false
- },
- {
- title: '电话',
- dataIndex: 'phone',
- key: 'phone',
- width: 120,
- search: false,
- sorter: true
- },
- {
- title: '手机',
- dataIndex: 'telephone',
- key: 'telephone',
- width: 120,
- sorter: true,
- search: false
- },
- {
- title: 'QQ',
- dataIndex: 'qq',
- key: 'qq',
- width: 120,
- sorter: true,
- search: false
- },
- {
- title: '邮箱',
- dataIndex: 'email',
- key: 'email',
- width: 165,
- sorter: true,
- // ellipsis: true,
- search: false
- },
- {
- title: '地区',
- dataIndex: 'districtName',
- key: 'districtName',
- width: 120,
- search: false,
- // ellipsis: true,
- // filterDropdown: filterDropdownProps => <FilterCascader {...filterDropdownProps} />,
- renderText: text => text?.replaceAll(' / ', ' , ')
- },
- {
- title: '个人标签',
- dataIndex: 'tagIds',
- key: 'tagIds',
- width: 160,
- filters: true,
- search: false,
- // onFilter: true,
- valueEnum: tag.personTagMap,
- // valueType: 'select',
- // fieldProps: {
- // mode: 'multiple',
- // options: tag.personOptions,
- // showArrow: true
- // },
- render: (_, record) => (
- <div className="flex items-center flex-wrap">
- {record.tagIds.map(item => (
- <Tooltip title={personTags.find(i => i.id === item)?.name} key={record.id + item}>
- <span
- className="inline-block w-12px h-12px rounded-1/2 mr-3px mb-3px"
- style={{ backgroundColor: personTagColorMap[item] }}
- />
- </Tooltip>
- ))}
- <PersonLabel
- dataId={record.id}
- tagIds={record.tagIds}
- tagType={TagTypeEnum.PERSONTAG}
- tagColumn={TagDataTypeEnum.CLIENT}
- checkCallBack={refreshData}
- modeType={LabelModeType.column}>
- <Add theme="filled" size="20" fill="#868e96" className="cursor-pointer" />
- </PersonLabel>
- </div>
- )
- },
- {
- title: '协作标签',
- dataIndex: 'tagCooperationIds',
- key: 'tagCooperationIds',
- width: 160,
- filters: true,
- search: false,
- valueEnum: tag.teamTagMap,
- // valueType: 'select',
- // fieldProps: {
- // mode: 'multiple',
- // options: tag.teamOptions,
- // showArrow: true
- // },
- render: (_, record) => (
- <div className="flex items-center flex-wrap">
- {record.tagCooperationIds.map(item => (
- <Tooltip title={teamTags.find(i => i.id === item)?.name} key={record.id + item}>
- <span
- key={record.id + item}
- className="inline-block w-12px h-12px mr-3px mb-3px"
- style={{ backgroundColor: teamTagColorMap[item] }}
- />
- </Tooltip>
- ))}
- <PersonLabel
- dataId={record.id}
- tagIds={record.tagCooperationIds}
- tagType={TagTypeEnum.TEAMTAG}
- tagColumn={TagDataTypeEnum.CLIENT}
- checkCallBack={refreshData}
- modeType={LabelModeType.column}>
- <Add theme="filled" size="20" fill="#868e96" className="cursor-pointer" />
- </PersonLabel>
- </div>
- )
- },
- {
- title: '地址',
- dataIndex: 'address',
- key: 'address',
- ellipsis: true,
- width: 150,
- sorter: true,
- search: false
- },
- {
- title: '乘车',
- dataIndex: 'ride',
- key: 'ride',
- ellipsis: true,
- width: 80,
- search: false
- },
- {
- title: '地标',
- dataIndex: 'landmarks',
- key: 'landmarks',
- ellipsis: true,
- width: 80,
- search: false
- },
- {
- title: '住宿',
- dataIndex: 'stay',
- key: 'stay',
- ellipsis: true,
- width: 80,
- search: false
- },
- {
- title: '来源',
- dataIndex: 'sourceName',
- key: 'sourceName',
- width: 80,
- search: false,
- filters: true,
- filterMultiple: false,
- valueEnum: sourceList.reduce((prev, curr) => {
- prev[curr.value] = { text: curr.label }
- return prev
- }, {})
- },
- {
- title: '备注',
- dataIndex: 'mark',
- key: 'mark',
- ellipsis: true,
- width: 80,
- search: false
- },
- // {
- // title: '软件锁',
- // dataIndex: 'keynum',
- // key: 'keynum',
- // width: 50,
- // render: keynum => <a>{keynum}</a>,
- // search: false
- // },
- {
- title: '创建人',
- dataIndex: 'staffName',
- key: 'staffName',
- width: 80,
- search: false
- }
- ]
- const columnsStateMap = {
- phone: {
- show: false
- },
- qq: {
- show: false
- },
- position: {
- show: false
- },
- office: {
- show: false
- },
- local: {
- show: false
- },
- stay: {
- show: false
- },
- keynum: {
- show: false
- },
- mark: {
- show: false
- },
- ride: {
- show: false
- },
- landmarks: {
- show: false
- },
- address: {
- show: false
- },
- staffName: {
- show: false
- },
- sourceName: {
- show: false
- }
- }
- const handleSearch = value => {
- tRef.current.reloadAndRest()
- setState({ ...state, params: { ...state.params, search: value } })
- }
- const onDistrictChange = value => {
- if (!value) return
- tRef.current.reloadAndRest()
- const [province = '', city = '', area = ''] = value || []
- setState({ ...state, params: { ...state.params, province, city, area } })
- }
- // 批量设置-确认触发
- const tagsSettingConfirm = async clientIds => {
- let requestSuccess = true
- if (tagState.tagIds.length) {
- const { code = -1 } = await apiBatchLink({
- tagIds: tagState.tagIds,
- dataIds: clientIds,
- dataType: TagDataTypeEnum.CLIENT,
- tagType: TagTypeEnum.PERSONTAG
- })
- if (code !== consts.RET_CODE.SUCCESS) {
- requestSuccess = false
- }
- }
- if (tagState.tagCooperationIds.length) {
- const { code = -1 } = await apiBatchLink({
- tagIds: tagState.tagCooperationIds,
- dataIds: clientIds,
- dataType: TagDataTypeEnum.CLIENT,
- tagType: TagTypeEnum.TEAMTAG
- })
- if (code !== consts.RET_CODE.SUCCESS) {
- requestSuccess = false
- }
- }
- requestSuccess && refreshData()
- }
- const renderTableAlert = ({ selectedRowKeys }) => {
- return (
- <div className="flex flex-row">
- <div className="mr-5px">
- <PersonLabel
- tagType={TagTypeEnum.PERSONTAG}
- tagColumn={TagDataTypeEnum.CLIENT}
- checkCallBack={toolbarOptionsChange}
- modeType={LabelModeType.toolbar}>
- {tagState.tagIds.length ? (
- <Button>
- {tagState.tagIds.map(item => (
- <span
- key={item}
- className="w-12px h-12px inline-block rounded-1/2 mr-3px"
- style={{ backgroundColor: personTagColorMap[item] }}
- />
- ))}
- <Down />
- </Button>
- ) : (
- <Button>
- 个人标签
- <Down />
- </Button>
- )}
- </PersonLabel>
- </div>
- <div className="mr-5">
- <PersonLabel
- tagType={TagTypeEnum.TEAMTAG}
- tagColumn={TagDataTypeEnum.CLIENT}
- checkCallBack={toolbarOptionsChange}
- modeType={LabelModeType.toolbar}>
- {tagState.tagCooperationIds.length ? (
- <Button>
- {tagState.tagCooperationIds.map(item => (
- <span
- key={item}
- className="w-12px h-12px inline-block mr-3px"
- style={{ backgroundColor: teamTagColorMap[item] }}
- />
- ))}
- <Down />
- </Button>
- ) : (
- <Button>
- 协作标签
- <Down />
- </Button>
- )}
- </PersonLabel>
- </div>
- <Button onClick={() => tagsSettingConfirm(selectedRowKeys)}>
- <Check size={14} />
- 确认
- </Button>
- </div>
- )
- }
- return (
- <div className={styles.contactContent}>
- <BasicTable
- mainMenuType="customer"
- columnStateType="CLIENT"
- params={state.params}
- actionRef={tRef}
- rowKey={record => record.id}
- columns={columns}
- request={async (params, sort, filter) => {
- const srotOrder = generateSortField(sort)
- const nFilter = generateFilterField(filter)
- const {
- code = -1,
- data: { client = [], total = 0 }
- } = await queryClient({ ...params, ...srotOrder, ...nFilter })
- setState({ ...state, orderIds: client.map(item => item.id) })
- return {
- data: client,
- success: code === consts.RET_CODE.SUCCESS,
- total
- }
- }}
- tableAlertRender={renderTableAlert}
- rowSelection={{
- type: 'checkbox',
- columnWidth: 25
- }}
- search={{ filterType: 'light' }}
- toolbar={{
- search: (
- <Tooltip placement="bottom" title="输入客户、单位名称、电话邮箱等">
- <Input.Search
- style={{ width: '250px' }}
- allowClear={true}
- placeholder={`在${
- permData[PermDataTypeEunm.CUSTOMER]?.find(item => item.value === defaultPermAuthCache)
- ?.label
- }下搜索`}
- onSearch={handleSearch}
- />
- </Tooltip>
- ),
- actions: [
- <LazyCascader
- key="lazyCascader"
- onChange={onDistrictChange}
- changeOnSelect={true}
- bordered={false}
- showFooter={true}
- className="hover:bg-[rgba(0,0,0,0.1)]"
- />,
- <Button
- type="primary"
- key="addClientBtn"
- disabled={!hasAddPerm}
- onClick={() =>
- dispatchModal('M_CLIENT_ADD', {
- onConfirm: handleAddClient,
- reload: () => tRef.current?.reload()
- })
- }>
- <Plus className="mr-1" />
- 客户
- </Button>
- ]
- }}
- columnsStateMap={columnsStateMap}
- />
- </div>
- )
- }
- export default connect(({ client, refresh, loading }) => ({
- personTagColorMap: client.personTagColorMap,
- personTags: client.personTags,
- sourceList: client.sourceList,
- teamTagColorMap: client.teamTagColorMap,
- teamTags: client.teamTags,
- loading: loading.models.client,
- shouldUpdate: refresh.client
- }))(Client)
|