|
|
@@ -1,15 +1,11 @@
|
|
|
-import { message, Modal } from 'antd';
|
|
|
-import type { Field } from '@formily/core';
|
|
|
-import { createForm, onFieldValueChange } from '@formily/core';
|
|
|
-import { Form, FormItem, FormLayout, Input, Radio, Select, TreeSelect } from '@formily/antd';
|
|
|
-import { createSchemaField } from '@formily/react';
|
|
|
-import type { ISchema } from '@formily/json-schema';
|
|
|
-import FUpload from '@/components/Upload';
|
|
|
+import { useEffect } from 'react';
|
|
|
import { service } from '@/pages/device/Product';
|
|
|
-import { action } from '@formily/reactive';
|
|
|
-import 'antd/lib/tree-select/style/index.less';
|
|
|
import type { ProductItem } from '@/pages/device/Product/typings';
|
|
|
import { useIntl } from '@@/plugin-locale/localeExports';
|
|
|
+import { RadioCard, UploadImage } from '@/components';
|
|
|
+import { Col, Form, Input, message, Modal, Row, TreeSelect } from 'antd';
|
|
|
+import { useRequest } from 'umi';
|
|
|
+import { debounce } from 'lodash';
|
|
|
|
|
|
interface Props {
|
|
|
visible: boolean;
|
|
|
@@ -19,27 +15,16 @@ interface Props {
|
|
|
model: 'add' | 'edit';
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 处理品类数据
|
|
|
- * @param tree
|
|
|
- */
|
|
|
-const treeToArray = (tree: any) => {
|
|
|
- const arr: any[] = [];
|
|
|
- const expanded = (datas: any[]) => {
|
|
|
- if (datas && datas.length > 0) {
|
|
|
- datas.forEach((e) => {
|
|
|
- arr.push(e);
|
|
|
- expanded(e.children);
|
|
|
- });
|
|
|
- }
|
|
|
- };
|
|
|
- expanded(tree);
|
|
|
- return arr;
|
|
|
-};
|
|
|
-
|
|
|
const Save = (props: Props) => {
|
|
|
const { visible, close, data } = props;
|
|
|
const intl = useIntl();
|
|
|
+ const [form] = Form.useForm();
|
|
|
+ const { data: classOptions, run: classRequest } = useRequest(service.category, {
|
|
|
+ manual: true,
|
|
|
+ formatResult: (response) => {
|
|
|
+ return response.result;
|
|
|
+ },
|
|
|
+ });
|
|
|
|
|
|
const handleData = () => {
|
|
|
// 特殊处理deviceType字段
|
|
|
@@ -50,200 +35,233 @@ const Save = (props: Props) => {
|
|
|
}
|
|
|
return data;
|
|
|
};
|
|
|
- const form = createForm({
|
|
|
- initialValues: handleData(),
|
|
|
- effects() {
|
|
|
- onFieldValueChange('messageProtocol', (field, f) => {
|
|
|
- const protocol = (field as Field).value;
|
|
|
- f.setFieldState('transportProtocol', async (state) => {
|
|
|
- state.loading = true;
|
|
|
- const resp = await service.getTransport(protocol);
|
|
|
- state.dataSource = resp.result.map((item: { name: string; id: string }) => ({
|
|
|
- label: item.name,
|
|
|
- value: item.id,
|
|
|
- }));
|
|
|
- state.loading = false;
|
|
|
- });
|
|
|
- });
|
|
|
- },
|
|
|
- });
|
|
|
|
|
|
- const SchemaField = createSchemaField({
|
|
|
- components: {
|
|
|
- FormItem,
|
|
|
- Input,
|
|
|
- Select,
|
|
|
- Radio,
|
|
|
- FUpload,
|
|
|
- FormLayout,
|
|
|
- TreeSelect,
|
|
|
- },
|
|
|
- });
|
|
|
- const serviceMap = new Map<string, Promise<any>>();
|
|
|
- serviceMap.set('classifiedId', service.category());
|
|
|
- serviceMap.set('protocol', service.getProtocol());
|
|
|
- serviceMap.set('storePolicy', service.getStorage());
|
|
|
- serviceMap.set('org', service.getOrg());
|
|
|
-
|
|
|
- let classifiedList: any[] = [];
|
|
|
- const useAsyncDataSource = (type: string) => (field: Field) => {
|
|
|
- field.loading = true;
|
|
|
- serviceMap.get(type)!.then(
|
|
|
- action.bound!((resp) => {
|
|
|
- if (type === 'classifiedId') {
|
|
|
- // 处理key错误
|
|
|
- field.dataSource = resp.result.map((item: Record<string, unknown>) => ({
|
|
|
- ...item,
|
|
|
- key: item.id,
|
|
|
- }));
|
|
|
- // 考虑冗余分类字段
|
|
|
- classifiedList = resp.result;
|
|
|
- } else {
|
|
|
- field.dataSource = resp.result.map((item: { name: any; id: any }) => ({
|
|
|
- label: item.name,
|
|
|
- value: item.id,
|
|
|
- }));
|
|
|
- }
|
|
|
- field.loading = false;
|
|
|
- }),
|
|
|
+ const intlFormat = (
|
|
|
+ id: string,
|
|
|
+ defaultMessage: string,
|
|
|
+ paramsID?: string,
|
|
|
+ paramsMessage?: string,
|
|
|
+ ) => {
|
|
|
+ const paramsObj: Record<string, string> = {};
|
|
|
+ if (paramsID) {
|
|
|
+ const paramsMsg = intl.formatMessage({
|
|
|
+ id: paramsID,
|
|
|
+ defaultMessage: paramsMessage,
|
|
|
+ });
|
|
|
+ paramsObj.name = paramsMsg;
|
|
|
+ }
|
|
|
+ const msg = intl.formatMessage(
|
|
|
+ {
|
|
|
+ id,
|
|
|
+ defaultMessage,
|
|
|
+ },
|
|
|
+ paramsObj,
|
|
|
);
|
|
|
+ return msg;
|
|
|
};
|
|
|
|
|
|
- const handleSave = async () => {
|
|
|
- const values = (await form.submit()) as any;
|
|
|
- // 冗余classifiedName 字段;
|
|
|
- // 如果只存储string。 可考虑字段解构方式处理
|
|
|
- // 可能存在数据反显问题,此处考虑与后台协商处理
|
|
|
- const classifiedId = values.classifiedId;
|
|
|
- if (classifiedId) {
|
|
|
- const tempClassifiedList = treeToArray(classifiedList);
|
|
|
- const classified = tempClassifiedList.find((i) => i.id === classifiedId);
|
|
|
- // values.classifiedId = classifiedId[classifiedId.length - 1];
|
|
|
- values.classfiedName = classified.name;
|
|
|
+ useEffect(() => {
|
|
|
+ if (visible) {
|
|
|
+ // 获取产品分类
|
|
|
+ classRequest();
|
|
|
+ form.setFieldsValue(handleData());
|
|
|
}
|
|
|
- const resp = (await service.update(values)) as any;
|
|
|
- if (resp.status === 200) {
|
|
|
- message.success('保存成功');
|
|
|
- props.reload();
|
|
|
- props.close();
|
|
|
+ }, [visible]);
|
|
|
+
|
|
|
+ const handleSave = async () => {
|
|
|
+ const formData = await form.validateFields();
|
|
|
+ if (formData) {
|
|
|
+ const res = await service.update(formData);
|
|
|
+ if (res.status === 200) {
|
|
|
+ message.success('保存成功');
|
|
|
+ if (props.reload) {
|
|
|
+ props.reload();
|
|
|
+ }
|
|
|
+ props.close();
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
- const schema: ISchema = {
|
|
|
- type: 'object',
|
|
|
- properties: {
|
|
|
- layout: {
|
|
|
- type: 'void',
|
|
|
- 'x-component': 'FormLayout',
|
|
|
- 'x-component-props': {
|
|
|
- labelCol: 4,
|
|
|
- wrapperCol: 18,
|
|
|
- },
|
|
|
- properties: {
|
|
|
- photoUrl: {
|
|
|
- title: '图标',
|
|
|
- 'x-component': 'FUpload',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- },
|
|
|
- id: {
|
|
|
- title: 'ID',
|
|
|
- 'x-component': 'Input',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- 'x-decorator-props': {
|
|
|
- tooltip: <div>若不填写,系统将自动生成唯一ID</div>,
|
|
|
- },
|
|
|
- 'x-component-props': {
|
|
|
- disabled: props.model === 'edit',
|
|
|
- },
|
|
|
- },
|
|
|
- name: {
|
|
|
- title: '名称',
|
|
|
- 'x-component': 'Input',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- 'x-validator': [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入名称',
|
|
|
- },
|
|
|
- {
|
|
|
- max: 64,
|
|
|
- message: '最多可输入64个字符',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- classifiedId: {
|
|
|
- title: '所属品类',
|
|
|
- 'x-component': 'TreeSelect',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- 'x-component-props': {
|
|
|
- fieldNames: { label: 'name', value: 'id', children: 'children', key: 'id' },
|
|
|
- },
|
|
|
- 'x-reactions': ['{{useAsyncDataSource("classifiedId")}}'],
|
|
|
- },
|
|
|
- // orgId: {
|
|
|
- // title: '所属机构',
|
|
|
- // 'x-component': 'Select',
|
|
|
- // 'x-decorator': 'FormItem',
|
|
|
- // 'x-reactions': ['{{useAsyncDataSource("org")}}'],
|
|
|
- // },
|
|
|
- // messageProtocol: {
|
|
|
- // title: '消息协议',
|
|
|
- // 'x-component': 'Select',
|
|
|
- // 'x-decorator': 'FormItem',
|
|
|
- // 'x-reactions': ['{{useAsyncDataSource("protocol")}}'],
|
|
|
- // },
|
|
|
- // transportProtocol: {
|
|
|
- // title: '传输协议',
|
|
|
- // 'x-component': 'Select',
|
|
|
- // 'x-decorator': 'FormItem',
|
|
|
- // },
|
|
|
- // storePolicy: {
|
|
|
- // title: '存储策略',
|
|
|
- // 'x-component': 'Select',
|
|
|
- // 'x-decorator': 'FormItem',
|
|
|
- // 'x-reactions': ['{{useAsyncDataSource("storePolicy")}}'],
|
|
|
- // },
|
|
|
- deviceType: {
|
|
|
- title: '设备类型',
|
|
|
- 'x-component': 'Radio.Group',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- enum: [
|
|
|
- { label: '直连设备', value: 'device' },
|
|
|
- { label: '网关子设备', value: 'childrenDevice' },
|
|
|
- { label: '网关设备', value: 'gateway' },
|
|
|
- ],
|
|
|
- 'x-validator': [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请选择设备类型',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- describe: {
|
|
|
- title: '描述',
|
|
|
- 'x-component': 'Input.TextArea',
|
|
|
- 'x-decorator': 'FormItem',
|
|
|
- 'x-component-props': {
|
|
|
- showCount: true,
|
|
|
- maxLength: 200,
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
+
|
|
|
+ const vailId = (_: any, value: any, callback: Function) => {
|
|
|
+ if (props.model === 'add') {
|
|
|
+ service.existsID(value).then((res) => {
|
|
|
+ if (res.status === 200 && res.result) {
|
|
|
+ callback(
|
|
|
+ intl.formatMessage({
|
|
|
+ id: 'pages.form.tip.existsID',
|
|
|
+ defaultMessage: 'ID重复',
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ callback();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
};
|
|
|
+
|
|
|
return (
|
|
|
<Modal
|
|
|
visible={visible}
|
|
|
- onCancel={() => close()}
|
|
|
- width="30vw"
|
|
|
+ onCancel={() => {
|
|
|
+ form.resetFields();
|
|
|
+ close();
|
|
|
+ }}
|
|
|
+ width={610}
|
|
|
title={intl.formatMessage({
|
|
|
- id: `pages.data.option.${props.model}`,
|
|
|
+ id: `pages.data.option.${props.model || 'add'}`,
|
|
|
defaultMessage: '新增',
|
|
|
})}
|
|
|
onOk={handleSave}
|
|
|
>
|
|
|
- <Form form={form}>
|
|
|
- <SchemaField schema={schema} scope={{ useAsyncDataSource }} />
|
|
|
+ <Form
|
|
|
+ form={form}
|
|
|
+ layout={'vertical'}
|
|
|
+ labelAlign={'right'}
|
|
|
+ labelCol={{
|
|
|
+ style: { width: 100 },
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Row>
|
|
|
+ <Col span={8}>
|
|
|
+ <Form.Item name={'photoUrl'}>
|
|
|
+ <UploadImage />
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ <Col span={16}>
|
|
|
+ <Form.Item
|
|
|
+ label={'ID'}
|
|
|
+ name={'id'}
|
|
|
+ tooltip={intl.formatMessage({
|
|
|
+ id: 'pages.form.tooltip.id',
|
|
|
+ defaultMessage: '若不填写,系统将自动生成唯一ID',
|
|
|
+ })}
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ pattern: /^[a-zA-Z0-9_\-]+$/,
|
|
|
+ message: intl.formatMessage({
|
|
|
+ id: 'pages.form.tip.id',
|
|
|
+ defaultMessage: '请输入英文或者数字或者-或者_',
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ max: 64,
|
|
|
+ message: intl.formatMessage({
|
|
|
+ id: 'pages.form.tip.max64',
|
|
|
+ defaultMessage: '最多输入64个字符',
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ validator: debounce(vailId, 300),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <Input
|
|
|
+ disabled={props.model === 'edit'}
|
|
|
+ placeholder={intlFormat('pages.form.tip.input', '请输入')}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label={intlFormat('pages.table.name', '名称')}
|
|
|
+ name={'name'}
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: intlFormat(
|
|
|
+ 'pages.form.tip.input.props',
|
|
|
+ '请输入名称',
|
|
|
+ 'pages.table.name',
|
|
|
+ '名称',
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ max: 64,
|
|
|
+ message: intl.formatMessage({
|
|
|
+ id: 'pages.form.tip.max64',
|
|
|
+ defaultMessage: '最多输入64个字符',
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <Input placeholder={intlFormat('pages.form.tip.input', '请输入')} />
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ <Row>
|
|
|
+ <Col span={24}>
|
|
|
+ <Form.Item label={'分类'} name={'classifiedId'}>
|
|
|
+ <TreeSelect
|
|
|
+ showSearch
|
|
|
+ onSelect={(_: any, node: any) => {
|
|
|
+ form.setFieldsValue({
|
|
|
+ classifiedName: node.name,
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ filterTreeNode={(input, treeNode) => treeNode.name.includes(input)}
|
|
|
+ placeholder={intlFormat('pages.form.tip.select', '请选择')}
|
|
|
+ fieldNames={{
|
|
|
+ label: 'name',
|
|
|
+ value: 'id',
|
|
|
+ }}
|
|
|
+ treeData={classOptions}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item hidden={true} name={'classifiedName'}>
|
|
|
+ <Input />
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ <Col span={24}>
|
|
|
+ <Form.Item
|
|
|
+ label={intlFormat('pages.device.instanceDetail.deviceType', '设备类型')}
|
|
|
+ name={'deviceType'}
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: intlFormat(
|
|
|
+ 'pages.form.tip.select.props',
|
|
|
+ '请选择设备类型',
|
|
|
+ 'pages.device.instanceDetail.deviceType',
|
|
|
+ '设备类型',
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <RadioCard
|
|
|
+ model={'singular'}
|
|
|
+ options={[
|
|
|
+ {
|
|
|
+ label: intlFormat('pages.device.type.device', '直连设备'),
|
|
|
+ value: 'device',
|
|
|
+ imgUrl: require('/public/images/device-type-1.png'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: intlFormat('pages.device.type.childrenDevice', '网关子设备'),
|
|
|
+ value: 'childrenDevice',
|
|
|
+ imgUrl: require('/public/images/device-type-2.png'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: intlFormat('pages.device.type.gateway', '网关设备'),
|
|
|
+ value: 'gateway',
|
|
|
+ imgUrl: require('/public/images/device-type-3.png'),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ <Col span={24}>
|
|
|
+ <Form.Item label={intlFormat('pages.table.description', '说明')} name={'describe'}>
|
|
|
+ <Input.TextArea
|
|
|
+ placeholder={intlFormat('pages.form.tip.input', '请输入')}
|
|
|
+ rows={4}
|
|
|
+ style={{ width: '100%' }}
|
|
|
+ maxLength={200}
|
|
|
+ showCount={true}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
</Form>
|
|
|
</Modal>
|
|
|
);
|