| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- import { Button, Checkbox, Popover, Input, message, Spin } from 'antd'
- import React, { useState, useRef, useEffect } from 'react'
- import { connect } from 'dva'
- import styles from './index.scss'
- import { apiConnOrDelTag, apiUpdateTag } from '@/services/customer'
- import consts from '@/basic/consts'
- const DropdownTypeEnum = {
- check: 0,
- edit: 1
- }
- // 数据类型
- export const TagDataTypeEnum = {
- CONTACT: 1, // 联系人
- COMPANY: 2 // 客户
- }
- // 标签类型
- export const TagTypeEnum = {
- PERSONTAG: 0, // 个人
- TEAMTAG: 1 // 协作
- }
- export const LabelModeType = {
- column: 0, // 列操作
- toolbar: 1 // 常用于表格批量操作
- }
- export const LabelStatusColorMap = {
- [TagTypeEnum.PERSONTAG]: [
- '#16A085',
- '#2980B9',
- '#8E44AD',
- '#f90000',
- '#B8651B',
- '#2C3E50',
- '#efd200',
- '#f47300'
- ],
- [TagTypeEnum.TEAMTAG]: [
- '#F8AC59',
- '#FF69B4',
- '#999999',
- '#7186ab',
- '#778b72',
- '#c292ca',
- '#a14751',
- '#57ECCC'
- ]
- }
- const PersonLabel = props => {
- const {
- children,
- dataId,
- tagIds = [],
- tagType,
- tagColumn,
- modeType = LabelModeType.column,
- checkCallBack,
- contactPersonTags,
- companyPersonTags,
- dispatch
- } = props
- const [dropdownType, setDropdownType] = useState(DropdownTypeEnum.check)
- const [checkedIds, setCheckedIds] = useState([])
- useEffect(() => {
- if (modeType === LabelModeType.column && tagIds.length) {
- setCheckedIds(tagIds)
- }
- }, [tagIds])
- const [showOkBtn, setShowOkBtn] = useState(false)
- const initData = () => {
- dispatch({
- type: `${tagColumn === TagDataTypeEnum.COMPANY ? 'contact' : 'company'}/fetchTags`,
- payload: { tagType, tagColumn }
- })
- }
- // 列操作->更新个人标签勾选情况
- const handleOnConfirm = async () => {
- const payload = {
- tagIds: checkedIds,
- dataId,
- dataType: tagColumn,
- tagType
- }
- const { code = -1 } = await apiConnOrDelTag(payload)
- if (code === consts.RET_CODE.SUCCESS) {
- setShowOkBtn(false)
- }
- }
- const menu = (
- <div className="zh-mg-tb-7 zh-mg-lf-14">
- <DropDownMenu
- checkedIds={checkedIds}
- setCheckedIds={setCheckedIds}
- dataId={dataId}
- personTags={tagColumn === TagDataTypeEnum.CONTACT ? contactPersonTags : companyPersonTags}
- menuType={dropdownType}
- tagType={tagType}
- tagColumn={tagColumn}
- modeType={modeType}
- checkCallBack={checkCallBack}
- initCallBack={initData}
- />
- <div className="zh-mg-top-5">
- {dropdownType === DropdownTypeEnum.check ? (
- <div className="zh-justify-between">
- <span
- onClick={() => setDropdownType(DropdownTypeEnum.edit)}
- className="zh-primary zh-pointer">
- 编辑标签
- </span>
- {modeType === LabelModeType.column && showOkBtn ? (
- <Button size="small" onClick={() => handleOnConfirm()}>
- 确认
- </Button>
- ) : null}
- </div>
- ) : (
- <>
- <Button onClick={() => setDropdownType(DropdownTypeEnum.check)}>返回</Button>
- </>
- )}
- </div>
- </div>
- )
- return (
- <Popover content={menu} trigger="click" className={styles.dropdownMenu}>
- {children}
- </Popover>
- )
- }
- const DropDownMenu = props => {
- // 保存选中的checkbox ids
- const {
- checkedIds,
- setCheckedIds,
- dataId,
- menuType,
- tagType,
- tagColumn,
- personTags,
- modeType,
- checkCallBack,
- initCallBack
- } = props
- const [activeState, setActiveState] = useState({
- id: '',
- activeId: '',
- loading: false
- })
- const inputRef = useRef(null)
- const handleOnchange = async (e, id) => {
- const { checked } = e.target
- let canRender = true
- const ids = checked ? [...checkedIds, id] : checkedIds.filter(item => item !== id)
- if (modeType === LabelModeType.column) {
- const { code = -1, msg = '操作失败' } = await apiConnOrDelTag({
- type: checked,
- payload: { dataId, tagId: id, dataType: tagColumn, tagType }
- })
- if (code !== consts.RET_CODE.SUCCESS) {
- canRender = false
- message.error(msg)
- }
- checkCallBack()
- } else {
- checkCallBack &&
- checkCallBack(tagType === TagTypeEnum.PERSONTAG ? 'tagIds' : 'tagCooperationIds', ids)
- }
- if (canRender) {
- setCheckedIds(ids)
- }
- }
- const labelOnClick = id => {
- setActiveState({ ...activeState, id, activeId: id })
- }
- useEffect(() => {
- activeState.id && inputRef.current?.focus()
- }, [activeState.id])
- const labelTextChange = async (e, oldVal) => {
- const { value: newVal = '' } = e.currentTarget
- if (newVal && oldVal !== newVal) {
- const { code = -1 } = await apiUpdateTag({ name: newVal, id: activeState.id })
- if (code === consts.RET_CODE.SUCCESS) {
- setActiveState({ ...activeState, loading: true })
- initCallBack()
- const delayUpdate = () => {
- setTimeout(() => {
- setActiveState({ ...activeState, activeId: '', loading: false })
- message.success('标签已更新')
- }, 500)
- }
- await delayUpdate()
- }
- }
- }
- return (
- <ul className={styles.labelContent}>
- {menuType === DropdownTypeEnum.check
- ? personTags.map((item, idx) => (
- <li key={item.id} className={styles.menuItem}>
- <div className={styles.labelText}>
- <div
- className={[
- styles.statusIcon,
- tagType === TagTypeEnum.PERSONTAG ? styles.suqare : ''
- ].join(' ')}
- style={{ backgroundColor: LabelStatusColorMap[tagType][idx] }}
- />
- <span>{item.name}</span>
- </div>
- <div className={styles.checkSpan}>
- <Checkbox
- checked={checkedIds.includes(item.id)}
- onChange={e => handleOnchange(e, item.id)}
- />
- </div>
- </li>
- ))
- : null}
- {menuType === DropdownTypeEnum.edit
- ? personTags.map((item, idx) => (
- <Spin
- key={item.id}
- spinning={item.id === activeState.id ? activeState.loading : false}
- wrapperClassName={[
- styles.menuItem,
- styles.editMenuItem,
- item.id === activeState.activeId ? styles.active : ''
- ].join(' ')}>
- <li onClick={() => labelOnClick(item.id)} style={{ width: '100%' }}>
- <div className={styles.editLabel}>
- <div
- className={[
- styles.statusIcon,
- tagType === TagTypeEnum.PERSONTAG ? styles.suqare : ''
- ].join(' ')}
- style={{ backgroundColor: LabelStatusColorMap[tagType][idx] }}
- />
- {activeState.activeId === item.id ? (
- <Input
- ref={inputRef}
- size="small"
- bordered={false}
- defaultValue={item.name}
- onBlur={e => labelTextChange(e, item.name)}
- onPressEnter={e => labelTextChange(e, item.name)}
- />
- ) : (
- <span>{item.name}</span>
- )}
- </div>
- </li>
- </Spin>
- ))
- : null}
- </ul>
- )
- }
- export default connect(({ contact, company }) => ({
- contactPersonTags: contact.personTags,
- companyPersonTags: company.personTags
- }))(PersonLabel)
|