You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
6.9 KiB

  1. import { useEffect, useRef } from 'react'
  2. import { useTranslation } from '@/i18n.ts'
  3. import { useStyle } from './style.ts'
  4. import {
  5. Alert,
  6. Button,
  7. Divider,
  8. Form,
  9. Input,
  10. InputNumber,
  11. InputRef,
  12. notification,
  13. Flex
  14. } from 'antd'
  15. import { useAtom, useAtomValue } from 'jotai'
  16. import TwoColPageLayout from '@/layout/TwoColPageLayout.tsx'
  17. import { ProCard } from '@ant-design/pro-components'
  18. import { PlusOutlined } from '@ant-design/icons'
  19. import Glass from '@/components/glass'
  20. import { categoryAtom, saveOrUpdateCategoryAtom } from '@/store/videos/category.ts'
  21. import Switch from '@/components/switch'
  22. import CategoryTree from './components/CategoryTree.tsx'
  23. const Category = () => {
  24. const { t } = useTranslation()
  25. const { styles, cx } = useStyle()
  26. const [ form ] = Form.useForm()
  27. const inputRef = useRef<InputRef>()
  28. const { mutate, isPending, isError, error } = useAtomValue(saveOrUpdateCategoryAtom)
  29. const [ current, setCurrent ] = useAtom(categoryAtom)
  30. useEffect(() => {
  31. if (isError) {
  32. notification.error({
  33. message: t('message.error', '错误'),
  34. description: (error as any).message ?? t('message.saveFail', '保存失败'),
  35. })
  36. }
  37. }, [ isError ])
  38. useEffect(() => {
  39. if (current?.id === 0 && inputRef.current) {
  40. inputRef.current.focus()
  41. }
  42. }, [ current ])
  43. return (
  44. <TwoColPageLayout
  45. leftPanel={<>
  46. <ProCard title={t('videos.category.title', '分类')}>
  47. <CategoryTree form={form}/>
  48. </ProCard>
  49. <div className={styles.treeActions}>
  50. <Divider style={{ flex: 1, margin: '8px 0' }}/>
  51. <Button style={{ flex: 1 }} size={'small'}
  52. block={true} type={'dashed'}
  53. icon={<PlusOutlined/>}
  54. onClick={() => {
  55. const data = {
  56. name: '',
  57. extend: {
  58. class: '',
  59. area: '',
  60. lang: '',
  61. year: '',
  62. tag: '',
  63. state: '',
  64. version: '',
  65. },
  66. sort: 0,
  67. status: 1,
  68. parent_id: 0,
  69. id: 0,
  70. }
  71. setCurrent(data)
  72. form.setFieldsValue(data)
  73. }}
  74. >{t('actions.news')}</Button>
  75. </div>
  76. </>}
  77. >
  78. <Glass
  79. enabled={current?.id === undefined}
  80. description={<>
  81. <Alert
  82. message={t('message.infoTitle', '提示')}
  83. description={t('videos.category.form.empty', '请从左侧选择一行数据操作')}
  84. type="info"
  85. />
  86. </>}
  87. >
  88. <ProCard title={t('videos.category.setting', '编辑')}>
  89. <Form form={form}
  90. initialValues={current!}
  91. labelAlign="right"
  92. labelWrap
  93. colon={false}
  94. className={cx(styles.form, {
  95. [styles.emptyForm]: current?.id === undefined
  96. })}
  97. >
  98. <Form.Item hidden={true} label={'id'} name={'id'}>
  99. <Input disabled={true}/>
  100. </Form.Item>
  101. <Form.Item
  102. rules={[
  103. { required: true, message: t('rules.required') }
  104. ]}
  105. label={t('videos.category.form.name', '名称')} name={'name'}>
  106. <Input ref={inputRef as any}
  107. placeholder={t('videos.category.form.name', '名称')}/>
  108. </Form.Item>
  109. <Form.Item label={t('videos.category.form.tag', 'Tag')}
  110. name={[ 'extend', 'class' ]}
  111. >
  112. <Input/>
  113. </Form.Item>
  114. <Form.Item label={t('videos.category.form.area', '地区')}
  115. name={[ 'extend', 'area' ]}
  116. >
  117. <Input/>
  118. </Form.Item>
  119. <Form.Item label={t('videos.category.form.lang', '语言')}
  120. name={[ 'extend', 'lang' ]}
  121. >
  122. <Input/>
  123. </Form.Item>
  124. <Form.Item label={t('videos.category.form.year', '年份')}
  125. name={[ 'extend', 'year' ]}
  126. >
  127. <Input/>
  128. </Form.Item>
  129. <Form.Item label={t('videos.category.form.state', '资源')}
  130. name={[ 'extend', 'state' ]}
  131. >
  132. <Input/>
  133. </Form.Item>
  134. <Form.Item label={t('videos.category.form.version', '版本')}
  135. name={[ 'extend', 'version' ]}
  136. >
  137. <Input/>
  138. </Form.Item>
  139. <Flex flex={1}>
  140. <Flex flex={1}>
  141. <Form.Item label={t('videos.category.form.sort', '排序')} name={'sort'}>
  142. <InputNumber/>
  143. </Form.Item>
  144. </Flex>
  145. <Flex flex={1}>
  146. <Form.Item label={t('videos.category.form.status', '状态')}
  147. name={'status'}>
  148. <Switch/>
  149. </Form.Item>
  150. </Flex>
  151. </Flex>
  152. <Form.Item label={' '}>
  153. <Button type="primary"
  154. htmlType={'submit'}
  155. loading={isPending}
  156. onClick={() => {
  157. form.validateFields().then((values) => {
  158. mutate({
  159. ...values,
  160. status: values.status ? 1 : 0,
  161. extend: JSON.stringify(values.extend),
  162. })
  163. })
  164. }}
  165. >
  166. {t('videos.category.form.save', '保存')}
  167. </Button>
  168. </Form.Item>
  169. </Form>
  170. </ProCard>
  171. </Glass>
  172. </TwoColPageLayout>
  173. )
  174. }
  175. export default Category