list.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import { useEffect, useRef, useState } from 'react'
  2. import { ActionsButton } from 'components'
  3. import style from '../style.module.scss'
  4. import { AntUploadProps, addExampleFile, deleteExampleFile } from 'api'
  5. import { UploadOutlined } from '@ant-design/icons'
  6. import { confirm } from 'utils'
  7. import {
  8. Modal,
  9. Button,
  10. Table,
  11. Empty,
  12. Form,
  13. Input,
  14. Select,
  15. Upload,
  16. message,
  17. ConfigProvider
  18. } from 'antd'
  19. import {
  20. useDispatch,
  21. useSelector,
  22. fetchExampleFileTypes,
  23. fetchExampleFiles,
  24. exampleTypeFiles
  25. } from 'store'
  26. import type { Example, ExampleFile } from "api";
  27. import type { ColumnsType } from 'antd/es/table'
  28. import type { FormInstance } from 'antd/es/form'
  29. import type { UploadProps } from 'antd'
  30. export type ExampleScenesProps = Pick<Example, 'caseId'> & { onClose: () => void,}
  31. export const ExampleFiles = (props: ExampleScenesProps) => {
  32. const [inertCaseId, setInsertCaseId] = useState<Example['caseId'] | null>(null)
  33. const typeFiles = useSelector(exampleTypeFiles)
  34. const dispatch = useDispatch()
  35. const fileColumns: ColumnsType<ExampleFile> = [
  36. {
  37. width: '300px',
  38. title: '名称',
  39. dataIndex: 'filesTitle',
  40. key: 'filesTitle',
  41. },
  42. {
  43. width: '200px',
  44. title: '创建时间',
  45. dataIndex: 'createTime',
  46. key: 'createTime',
  47. },
  48. {
  49. title: '操作',
  50. key: 'action',
  51. render(data: ExampleFile) {
  52. const actions = [
  53. {
  54. text: '查看',
  55. action: () => {
  56. window.open(data.filesUrl)
  57. },
  58. },
  59. {
  60. text: '删除',
  61. action: async () => {
  62. if (await confirm('确定要删除此数据?')) {
  63. await deleteExampleFile(data)
  64. dispatch(fetchExampleFiles({ caseId: props.caseId }))
  65. }
  66. },
  67. },
  68. ]
  69. return <ActionsButton actions={actions} />
  70. }
  71. },
  72. ]
  73. useEffect(() => {
  74. dispatch(fetchExampleFileTypes())
  75. dispatch(fetchExampleFiles({ caseId: props.caseId }))
  76. }, [dispatch, props.caseId])
  77. const total = typeFiles.reduce((t, c) => t + c.children.length ,0)
  78. const renderContent = total
  79. ? typeFiles.map((typeFile, i) =>
  80. !!typeFile.children.length && (
  81. <>
  82. <p className={style['file-type-name']}>{typeFile.filesTypeName}</p>
  83. <Table
  84. showHeader={false}
  85. key={typeFile.filesTypeId}
  86. pagination={false}
  87. columns={fileColumns}
  88. dataSource={typeFile.children}
  89. />
  90. </>
  91. )
  92. )
  93. : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
  94. const renderAddFile = inertCaseId
  95. && <AddExampleFile caseId={inertCaseId} onClose={() => setInsertCaseId(null)} />
  96. return (
  97. <Modal
  98. width="800px"
  99. title="卷宗管理"
  100. visible={true}
  101. onOk={props.onClose}
  102. onCancel={props.onClose}
  103. okText="确定"
  104. cancelText="取消"
  105. >
  106. {renderAddFile}
  107. <div className={style['model-header']}>
  108. <Button type="primary" onClick={() => setInsertCaseId(props.caseId)}>
  109. 上传附件
  110. </Button>
  111. </div>
  112. <ConfigProvider renderEmpty={() => null}>
  113. <Table
  114. className={style['header-table']}
  115. pagination={false}
  116. columns={fileColumns}
  117. dataSource={[]}
  118. />
  119. </ConfigProvider>
  120. { renderContent }
  121. </Modal>
  122. )
  123. }
  124. export type AddExampleFileProps = Pick<Example, 'caseId'> & { onClose: () => void,}
  125. export const AddExampleFile = (props: AddExampleFileProps) => {
  126. const dispatch = useDispatch()
  127. const from = useRef<FormInstance | null>(null)
  128. const types = useSelector(state => state['example/file'].types)
  129. const renderTypeOptions = types.map(type => (
  130. <Select.Option value={type.filesTypeId} children={type.filesTypeName} key={type.filesTypeId} />
  131. ))
  132. const onFinish = async (values: any) => {
  133. if (!values.filesUrl.fileList.length) {
  134. message.error('附件文件不能为空!')
  135. }
  136. await addExampleFile({
  137. ...values,
  138. caseId: props.caseId,
  139. filesUrl: values.filesUrl.fileList[0].response
  140. })
  141. props.onClose()
  142. dispatch(fetchExampleFiles({ caseId: props.caseId }))
  143. };
  144. const onSubmit = () => {
  145. from.current?.submit()
  146. }
  147. const uploadProps: UploadProps = {
  148. ...AntUploadProps,
  149. listType: 'picture',
  150. maxCount: 1,
  151. onPreview(file) {
  152. window.open(file.response)
  153. }
  154. };
  155. return (
  156. <Modal
  157. width="400px"
  158. title="上传附件"
  159. visible={true}
  160. onOk={onSubmit}
  161. onCancel={props.onClose}
  162. okText="确定"
  163. cancelText="取消"
  164. >
  165. <Form
  166. labelCol={{span: 8}}
  167. wrapperCol={{span: 16}}
  168. name="control-ref"
  169. ref={from}
  170. onFinish={onFinish}
  171. >
  172. <Form.Item name="filesTypeId" label="附件类型" rules={[{ required: true, message: '附件类型不能为空' }]}>
  173. <Select placeholder="选择附件类型">
  174. {renderTypeOptions}
  175. </Select>
  176. </Form.Item>
  177. <Form.Item name="filesUrl" label="上传附件" rules={[{ required: true, message: '附件文件不能为空' }]}>
  178. <Upload {...uploadProps}>
  179. <Button icon={<UploadOutlined />}>请上传pdf/word/jpg格式文件</Button>
  180. </Upload>
  181. </Form.Item>
  182. <Form.Item name="filesTitle" label="附件标题" rules={[{ required: true, message: '附件标题不能为空' }]}>
  183. <Input />
  184. </Form.Item>
  185. </Form>
  186. </Modal>
  187. )
  188. }