user-modal.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. 'use client'
  2. import React, { useEffect, useState } from 'react'
  3. import { RiAddLine, RiCloseLine } from '@remixicon/react'
  4. import Modal from '@/app/components/base/modal'
  5. import Button from '@/app/components/base/button'
  6. import { deptAddUsers, deptDelUsers, fetchIntent, fetchNoDeptUsers } from '@/service/common'
  7. import 'react-multi-email/dist/style.css'
  8. import cn from '@/utils/classnames'
  9. import Confirm from '@/app/components/base/confirm'
  10. import { Select as AntdSelect } from 'antd'
  11. const UserModal = ({
  12. onCancel,
  13. onSend,
  14. transfer,
  15. }: any) => {
  16. const [list, setList] = useState<any>([])
  17. const [total, setTotal] = useState(0)
  18. const handlePage = () => {
  19. fetchIntent({
  20. url: `/dept/dept-accounts/${transfer.row.dept_id}`,
  21. params: {},
  22. }).then((res: any) => {
  23. setList(res.data)
  24. setTotal(res.data.length)
  25. })
  26. }
  27. useEffect(() => {
  28. handlePage()
  29. }, [])
  30. const [showConfirmDelete, setShowConfirmDelete] = useState(false)
  31. const [row, setRow] = useState<any>({})
  32. const handleDel = async () => {
  33. try {
  34. const { result }: any = await deptDelUsers({
  35. url: '/dept/dept-accounts',
  36. body: { dept_id: transfer.row.dept_id, account_ids: [{ account_id: row.account_id }] },
  37. })
  38. if (result === 'success') {
  39. setShowConfirmDelete(false)
  40. handlePage()
  41. }
  42. }
  43. catch (e) { }
  44. }
  45. const [showDetail, setShowDetail] = useState(false)
  46. const [selectUser, setSelectUser] = useState<any>([])
  47. const [userOptions, setUserOptions] = useState<any>([])
  48. useEffect(() => {
  49. fetchNoDeptUsers({
  50. url: '/account/nodept',
  51. params: {},
  52. }).then((res: any) => {
  53. setUserOptions(res.data.map((v: any) => ({ label: v.email, value: v.account_id })) || [])
  54. })
  55. }, [])
  56. const handleSave = async () => {
  57. try {
  58. const { result }: any = await deptAddUsers({
  59. url: '/dept/dept-accounts',
  60. body: { dept_id: transfer.row.dept_id, account_ids: selectUser.map((v: any) => ({ account_id: v })) },
  61. })
  62. if (result === 'success') {
  63. setShowDetail(false)
  64. handlePage()
  65. }
  66. }
  67. catch (e) { }
  68. }
  69. return (
  70. <div>
  71. <Modal overflowVisible isShow onClose={() => { }} className="p-[24px 32px] w-[800px] max-w-[800px]">
  72. <div className='mb-2 flex justify-between'>
  73. <div className='text-xl font-semibold text-text-primary'>关联用户</div>
  74. <RiCloseLine className='h-4 w-4 cursor-pointer text-text-tertiary' onClick={onCancel} />
  75. </div>
  76. <div className='flex h-[600px] flex-col'>
  77. {/* <div className="flex items-center gap-2"> */}
  78. {/* <div className="flex shrink-0 items-center text-gray-500"> */}
  79. {/* 用户名称 */}
  80. {/* <Input */}
  81. {/* className="ml-2" */}
  82. {/* showClearIcon */}
  83. {/* wrapperClassName='!w-[200px]' */}
  84. {/* value={name} */}
  85. {/* onChange={e => setName(e.target.value)} */}
  86. {/* onClear={() => setName('')} */}
  87. {/* /> */}
  88. {/* </div> */}
  89. {/* <Button variant='primary' className={cn('ml-auto shrink-0')} onClick={() => { */}
  90. {/* handleSearch(false) */}
  91. {/* }}> */}
  92. {/* <RiSearchLine className='mr-1 h-4 w-4' /> */}
  93. {/* 搜索 */}
  94. {/* </Button> */}
  95. {/* <Button variant='primary' className={cn('shrink-0')} onClick={() => { */}
  96. {/* handleSearch(true) */}
  97. {/* }}> */}
  98. {/* <RiRefreshLine className='mr-1 h-4 w-4' /> */}
  99. {/* 重置 */}
  100. {/* </Button> */}
  101. {/* </div> */}
  102. <div className="mt-2">
  103. <Button variant='primary' className={cn('shrink-0')}
  104. onClick={() => {
  105. setShowDetail(true)
  106. }}>
  107. <RiAddLine className='mr-1 h-4 w-4' />
  108. 添加用户
  109. </Button>
  110. </div>
  111. <div className="flex-1">
  112. <div className='relative flex h-full w-full flex-col'>
  113. <div className='relative grow overflow-x-auto'>
  114. <table className={'mt-3 w-full min-w-[700px] max-w-full border-collapse border-0 text-sm'}>
  115. <thead className="h-8 border-b border-divider-subtle text-xs font-medium uppercase leading-8 text-text-tertiary">
  116. <tr>
  117. <td>用户名称</td>
  118. <td>用户账号</td>
  119. <td className="w-[120px] text-center">操作</td>
  120. </tr>
  121. </thead>
  122. <tbody className="text-text-secondary">
  123. {list.map((item: any) => (
  124. <tr
  125. key={item.id}
  126. className={'h-8 border-b border-divider-subtle hover:bg-background-default-hover'}
  127. >
  128. <td>{item.name}</td>
  129. <td>{item.email}</td>
  130. <td className="flex justify-center gap-2">
  131. <Button variant='ghost' size='small' className={cn('shrink-0 text-red-600')} onClick={() => {
  132. setRow(item)
  133. setShowConfirmDelete(true)
  134. }}>
  135. 解除关联
  136. </Button>
  137. </td>
  138. </tr>
  139. ))}
  140. </tbody>
  141. </table>
  142. </div>
  143. {/* Show Pagination only if the total is more than the limit */}
  144. {/* {total && ( */}
  145. {/* <Pagination */}
  146. {/* total={total} */}
  147. {/* limit={limit} */}
  148. {/* onLimitChange={setLimit} */}
  149. {/* current={page} */}
  150. {/* onChange={setPage} */}
  151. {/* className='w-full shrink-0 px-0 pb-0' */}
  152. {/* /> */}
  153. {/* )} */}
  154. </div>
  155. </div>
  156. </div>
  157. </Modal>
  158. {showConfirmDelete && (
  159. <Confirm
  160. title="取消确认"
  161. content={`请确认是否取消关联${row.name}?`}
  162. isShow={showConfirmDelete}
  163. onConfirm={handleDel}
  164. onCancel={() => setShowConfirmDelete(false)}
  165. />
  166. )}
  167. {
  168. showDetail && (
  169. <Modal overflowVisible isShow onClose={() => { }} className="p-[24px 32px] w-[400px]">
  170. <div className='mb-2 flex justify-between'>
  171. <div className='text-xl font-semibold text-text-primary'>添加用户</div>
  172. <RiCloseLine className='h-4 w-4 cursor-pointer text-text-tertiary' onClick={() => setShowDetail(false)} />
  173. </div>
  174. <div>
  175. <div className={cn('flex flex-wrap items-center justify-between py-4')}>
  176. <div className='shrink-0 py-2 text-sm font-medium leading-[20px] text-text-primary'>
  177. 选择用户
  178. </div>
  179. <div className='w-full'>
  180. <AntdSelect
  181. className="w-full"
  182. mode="multiple"
  183. showSearch
  184. placeholder="请选择用户"
  185. optionFilterProp="label"
  186. onChange={v => setSelectUser(v)}
  187. options={userOptions}
  188. />
  189. </div>
  190. </div>
  191. <Button
  192. tabIndex={0}
  193. className='w-full'
  194. onClick={handleSave}
  195. disabled={!selectUser.length}
  196. variant='primary'
  197. >
  198. 保存
  199. </Button>
  200. </div>
  201. </Modal>
  202. )
  203. }
  204. </div>
  205. )
  206. }
  207. export default UserModal