index.tsx 6.8 KB

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