index.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { Col, Form, Input, Modal, Row, Select } from 'antd';
  2. import { service } from '@/pages/device/Instance';
  3. import type { DeviceInstance } from '../typings';
  4. import { useEffect, useState } from 'react';
  5. import { useIntl } from '@@/plugin-locale/localeExports';
  6. import { UploadImage } from '@/components';
  7. import { debounce } from 'lodash';
  8. import encodeQuery from '@/utils/encodeQuery';
  9. import { onlyMessage } from '@/utils/util';
  10. interface Props {
  11. visible: boolean;
  12. close: (data: DeviceInstance | undefined) => void;
  13. reload?: () => void;
  14. model?: 'add' | 'edit';
  15. data?: Partial<DeviceInstance>;
  16. }
  17. const defaultImage = '/images/device-type-3-big.png';
  18. const Save = (props: Props) => {
  19. const { visible, close, data } = props;
  20. const [productList, setProductList] = useState<any[]>([]);
  21. const [loading, setLoading] = useState(false);
  22. const [form] = Form.useForm();
  23. useEffect(() => {
  24. if (visible && data && Object.keys(data).length) {
  25. form.setFieldsValue({
  26. ...data,
  27. });
  28. } else if (visible) {
  29. form.setFieldsValue({
  30. photoUrl: defaultImage,
  31. });
  32. }
  33. }, [visible]);
  34. const intl = useIntl();
  35. useEffect(() => {
  36. service
  37. .getProductList(
  38. encodeQuery({
  39. paging: false,
  40. sorts: {
  41. createTime: 'desc',
  42. },
  43. terms: {
  44. state: 1,
  45. },
  46. }),
  47. )
  48. .then((resp: any) => {
  49. if (resp.status === 200) {
  50. const list = resp.result.map((item: { name: any; id: any }) => ({
  51. label: item.name,
  52. value: item.id,
  53. }));
  54. setProductList(list);
  55. }
  56. });
  57. }, []);
  58. const intlFormat = (
  59. id: string,
  60. defaultMessage: string,
  61. paramsID?: string,
  62. paramsMessage?: string,
  63. ) => {
  64. const paramsObj: Record<string, string> = {};
  65. if (paramsID) {
  66. const paramsMsg = intl.formatMessage({
  67. id: paramsID,
  68. defaultMessage: paramsMessage,
  69. });
  70. paramsObj.name = paramsMsg;
  71. }
  72. return intl.formatMessage(
  73. {
  74. id,
  75. defaultMessage,
  76. },
  77. paramsObj,
  78. );
  79. };
  80. const handleSave = async () => {
  81. const values = await form.validateFields();
  82. if (values) {
  83. if (values.id === '') {
  84. delete values.id;
  85. }
  86. setLoading(true);
  87. const resp = (await service.update(values)) as any;
  88. setLoading(false);
  89. if (resp.status === 200) {
  90. onlyMessage('保存成功');
  91. if (props.reload) {
  92. props.reload();
  93. }
  94. props.close(values);
  95. form.resetFields();
  96. }
  97. }
  98. };
  99. const vailId = (_: any, value: any, callback: Function) => {
  100. if (props.model === 'add' && value) {
  101. service.isExists(value).then((resp: any) => {
  102. if (resp.status === 200 && resp.result) {
  103. callback(
  104. intl.formatMessage({
  105. id: 'pages.form.tip.existsID',
  106. defaultMessage: 'ID重复',
  107. }),
  108. );
  109. } else {
  110. callback();
  111. }
  112. });
  113. } else {
  114. callback();
  115. }
  116. };
  117. return (
  118. <Modal
  119. maskClosable={false}
  120. visible={visible}
  121. onCancel={() => {
  122. form.resetFields();
  123. close(undefined);
  124. }}
  125. width="580px"
  126. title={intl.formatMessage({
  127. id: `pages.data.option.${props.model || 'add'}`,
  128. defaultMessage: '新增',
  129. })}
  130. confirmLoading={loading}
  131. onOk={handleSave}
  132. >
  133. <Form
  134. form={form}
  135. layout={'vertical'}
  136. labelAlign={'right'}
  137. labelCol={{
  138. style: { width: 100 },
  139. }}
  140. >
  141. <Row>
  142. <Col span={8}>
  143. <Form.Item name={'photoUrl'}>
  144. <UploadImage />
  145. </Form.Item>
  146. </Col>
  147. <Col span={16}>
  148. <Form.Item
  149. label={'ID'}
  150. name={'id'}
  151. tooltip={intlFormat('pages.form.tooltip.id', '若不填写,系统将自动生成唯一ID')}
  152. rules={[
  153. {
  154. pattern: /^[a-zA-Z0-9_\-]+$/,
  155. message: intlFormat('pages.form.tip.id', '请输入英文或者数字或者-或者_'),
  156. },
  157. {
  158. max: 64,
  159. message: intlFormat('pages.form.tip.max64', '最多输入64个字符'),
  160. },
  161. {
  162. validator: debounce(vailId, 300),
  163. },
  164. ]}
  165. >
  166. <Input
  167. disabled={props.model === 'edit'}
  168. placeholder={`${intlFormat('pages.form.tip.input', '请输入')}ID`}
  169. />
  170. </Form.Item>
  171. <Form.Item
  172. label={intlFormat('pages.table.name', '名称')}
  173. name={'name'}
  174. rules={[
  175. {
  176. required: true,
  177. message: intlFormat(
  178. 'pages.form.tip.input.props',
  179. '请输入名称',
  180. 'pages.table.name',
  181. '名称',
  182. ),
  183. },
  184. {
  185. max: 64,
  186. message: intl.formatMessage({
  187. id: 'pages.form.tip.max64',
  188. defaultMessage: '最多输入64个字符',
  189. }),
  190. },
  191. ]}
  192. required
  193. >
  194. <Input
  195. placeholder={
  196. intlFormat('pages.form.tip.input', '请输入') +
  197. intlFormat('pages.table.name', '名称')
  198. }
  199. />
  200. </Form.Item>
  201. </Col>
  202. </Row>
  203. <Row>
  204. <Col span={24}>
  205. <Form.Item
  206. label={'所属产品'}
  207. name={'productId'}
  208. rules={[
  209. {
  210. required: true,
  211. message: '请选择所属产品',
  212. },
  213. ]}
  214. tooltip={'只能选择“正常”状态的产品'}
  215. required
  216. >
  217. <Select
  218. showSearch
  219. allowClear
  220. options={productList}
  221. disabled={props.model === 'edit'}
  222. onSelect={(_: any, node: any) => {
  223. form.setFieldsValue({
  224. productName: node.label,
  225. });
  226. }}
  227. placeholder={'请选择状态为“正常”的产品'}
  228. filterOption={(input, option) => option.label.includes(input)}
  229. />
  230. </Form.Item>
  231. <Form.Item hidden={true} name={'productName'}>
  232. <Input />
  233. </Form.Item>
  234. </Col>
  235. </Row>
  236. <Row>
  237. <Col span={24}>
  238. <Form.Item label={intlFormat('pages.table.description', '说明')} name={'describe'}>
  239. <Input.TextArea
  240. placeholder={
  241. intlFormat('pages.form.tip.input', '请输入') +
  242. intlFormat('pages.table.describe', '说明')
  243. }
  244. rows={4}
  245. style={{ width: '100%' }}
  246. maxLength={200}
  247. showCount={true}
  248. />
  249. </Form.Item>
  250. </Col>
  251. </Row>
  252. </Form>
  253. </Modal>
  254. );
  255. };
  256. export default Save;