Преглед изворни кода

Merge pull request #615 from jetlinks/next-wzy

Next wzy
孙超 пре 3 година
родитељ
комит
daddd02bb2
29 измењених фајлова са 277 додато и 96 уклоњено
  1. 25 10
      src/app.tsx
  2. 3 3
      src/components/FRuleEditor/index.tsx
  3. 7 2
      src/components/ProTableCard/CardItems/Stream/index.tsx
  4. 4 1
      src/components/SearchComponent/index.tsx
  5. 1 1
      src/pages/account/Center/bind/index.tsx
  6. 9 1
      src/pages/account/NotificationSubscription/save/index.tsx
  7. 2 0
      src/pages/device/Firmware/Task/Detail/index.tsx
  8. 7 12
      src/pages/device/Firmware/index.tsx
  9. 4 1
      src/pages/device/Instance/Detail/Functions/form.tsx
  10. 1 1
      src/pages/device/Instance/Detail/Modbus/index.tsx
  11. 11 1
      src/pages/device/Instance/index.tsx
  12. 1 0
      src/pages/device/Product/Detail/Access/AccessConfig/index.tsx
  13. 0 1
      src/pages/device/Product/Detail/Access/index.tsx
  14. 1 4
      src/pages/device/components/Metadata/Base/Edit/index.tsx
  15. 2 2
      src/pages/document.ejs
  16. 14 9
      src/pages/link/Channel/Opcua/Export/index.tsx
  17. 6 14
      src/pages/link/Channel/Opcua/index.tsx
  18. 9 7
      src/pages/link/Channel/Opcua/savePoint.tsx
  19. 10 0
      src/pages/link/Channel/Opcua/service.ts
  20. 52 1
      src/pages/media/Stream/index.tsx
  21. 4 0
      src/pages/media/Stream/typings.d.ts
  22. 1 1
      src/pages/notice/Template/Detail/doc/DingTalk.tsx
  23. 1 1
      src/pages/notice/Template/Detail/doc/DingTalkRebot.tsx
  24. 1 1
      src/pages/notice/Template/Detail/index.tsx
  25. 7 3
      src/pages/system/Apply/Menu/index.tsx
  26. 47 18
      src/pages/system/Apply/Save/index.tsx
  27. 1 1
      src/pages/system/Apply/index.tsx
  28. 10 0
      src/pages/system/Menu/Setting/baseMenu.ts
  29. 36 0
      src/utils/menu/index.ts

+ 25 - 10
src/app.tsx

@@ -19,6 +19,7 @@ import getRoutes, {
   getMenus,
   handleRoutes,
   saveMenusCache,
+  getRoutesLayout,
 } from '@/utils/menu';
 import { AIcon } from '@/components';
 import React from 'react';
@@ -282,7 +283,6 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
     onPageChange: () => {
       const { location } = history;
       // 如果没有登录,重定向到 login
-      console.log(location, 'location');
       if (
         !initialState?.currentUser &&
         location.pathname !== loginPath &&
@@ -298,7 +298,6 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
     menuItemRender: (menuItemProps, defaultDom) => {
       return MenuItemIcon(menuItemProps, defaultDom, {
         onClick: () => {
-          console.log('menuItemProps', menuItemProps);
           history.push(menuItemProps.path!);
         },
       });
@@ -348,7 +347,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
 };
 
 export function patchRoutes(routes: any) {
-  // console.log(routes,'11111111111')
+  console.log(routes);
   if (extraRoutes && extraRoutes.length) {
     const basePath = routes.routes.find((_route: any) => _route.path === '/')!;
 
@@ -417,10 +416,26 @@ export function render(oldRender: any) {
   }
 }
 
-// export function onRouteChange({ routes, location }) {
-//   console.log(routes,location,'onRouteChange')
-//   // const route = matchRoutes(clientRoutes, location.pathname)?.pop()?.route
-//   // if (route) {
-//   //   document.title = route.title || '';
-//   // }
-// }
+export function onRouteChange({ routes, location }: any) {
+  // console.log(11111111111)
+  // debugger;
+  if (location.query && location.query.layout === 'false') {
+    // console.log(routes, 'onRouteChange')
+    const basePath = routes.find((_route: any) => _route.path === '/')!;
+    const _routes = getRoutesLayout(extraRoutes);
+    const baseRedirect = {
+      path: '/',
+      layout: false,
+      routes: [
+        ..._routes,
+        {
+          path: '/',
+          layout: false,
+          redirect: _routes[0].path,
+        },
+      ],
+    };
+    // debugger
+    basePath.routes = [...basePath.routes, baseRedirect];
+  }
+}

+ 3 - 3
src/components/FRuleEditor/index.tsx

@@ -29,15 +29,15 @@ interface Props {
 const FRuleEditor = observer((props: Props) => {
   const { value, onChange, property, virtualRule } = props;
   useEffect(() => {
-    // console.log(virtualRule, 111111111);
+    // console.log(value, 111111111);
     State.property = property;
     const subscription = Store.subscribe('rule-editor-value', onChange);
     State.code = value;
     return () => {
-      subscription.unsubscribe();
       State.code = '';
+      subscription.unsubscribe();
     };
-  });
+  }, []);
   return (
     <>
       <Editor

+ 7 - 2
src/components/ProTableCard/CardItems/Stream/index.tsx

@@ -2,6 +2,7 @@ import React from 'react';
 import { Ellipsis, TableCard } from '@/components';
 import '@/style/common.less';
 import './index.less';
+import { StatusColorEnum } from '@/components/BadgeStatus';
 
 export interface StreamCardProps extends StreamItem {
   detail?: React.ReactNode;
@@ -16,8 +17,12 @@ export default (props: StreamCardProps) => {
     <TableCard
       detail={props.detail}
       actions={props.actions}
-      showStatus={false}
-      showMask={false}
+      status={props?.state?.value}
+      statusText={props?.state?.text}
+      statusNames={{
+        enabled: StatusColorEnum.success,
+        disabled: StatusColorEnum.error,
+      }}
       className={'stream-card-item'}
     >
       <div className="context-stream">

+ 4 - 1
src/components/SearchComponent/index.tsx

@@ -290,7 +290,10 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
                     state.componentType = 'DatePicker';
                     state.componentProps = { showTime: true, allowClear: true };
                   });
-                  console.log(isModified);
+                  f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                    state.value = 'gte';
+                  });
+                  // console.log(isModified);
                   if (isModified) {
                     f.setFieldState(typeFiled.query('.termType'), async (state) => {
                       state.value = 'gte';

+ 1 - 1
src/pages/account/Center/bind/index.tsx

@@ -23,7 +23,7 @@ const Bind = () => {
   const Vector = require('/public/images/bind/Vector.png');
   const Rectangle = require('/public/images/bind/Rectangle.png');
   const logo = require('/public/images/bind/jetlinksLogo.png');
-  // const defaultImg = require('/public/images/apply/provider1.png');
+  const defaultImg = require('/public/images/apply/provider1.png');
 
   const iconMap = new Map();
   iconMap.set('dingtalk-ent-app', require('/public/images/notice/dingtalk.png'));

+ 9 - 1
src/pages/account/NotificationSubscription/save/index.tsx

@@ -1,7 +1,7 @@
 import { Modal } from 'antd';
 import { useEffect, useMemo, useState } from 'react';
 import { Checkbox, Form, FormGrid, FormItem, Input, Select } from '@formily/antd';
-import { createForm } from '@formily/core';
+import { createForm, onFieldReact } from '@formily/core';
 import type { ISchema } from '@formily/react';
 import { createSchemaField } from '@formily/react';
 import { onlyMessage, useAsyncDataSource } from '@/utils/util';
@@ -23,6 +23,14 @@ const Save = (props: Props) => {
       createForm({
         validateFirst: true,
         initialValues: data,
+        effects: () => {
+          onFieldReact('topicProvider', (field: any) => {
+            const list = field.dataSource;
+            if (list && list.length !== 0) {
+              field.dataSource = list?.filter((item: any) => item.value === 'alarm');
+            }
+          });
+        },
       }),
     [],
   );

+ 2 - 0
src/pages/device/Firmware/Task/Detail/index.tsx

@@ -194,6 +194,7 @@ const Detail = observer(() => {
       ellipsis: true,
       dataIndex: 'productId',
       valueType: 'select',
+      hideInSearch: true,
       render: (text: any, record: any) => record?.productName,
       request: async () => {
         const res: any = await service.queryProduct({
@@ -209,6 +210,7 @@ const Detail = observer(() => {
     {
       title: '创建时间',
       ellipsis: true,
+      hideInSearch: true,
       dataIndex: 'createTime',
       valueType: 'dateTime',
       // render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),

+ 7 - 12
src/pages/device/Firmware/index.tsx

@@ -17,6 +17,7 @@ import usePermissions from '@/hooks/permission';
 import SearchComponent from '@/components/SearchComponent';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { onlyMessage } from '@/utils/util';
+import _ from 'lodash';
 
 export const service = new Service('firmware');
 
@@ -64,20 +65,14 @@ const Firmware = observer(() => {
         service
           .queryProduct({
             paging: false,
-            // terms: [
-            //   {
-            //     column: 'state',
-            //     value: 1,
-            //   },
-            // ],
             sorts: [{ name: 'name', order: 'desc' }],
           })
-          .then((resp: any) =>
-            (resp?.result || []).map((item: any) => ({
-              label: item.name,
-              value: item.id,
-            })),
-          ),
+          .then((resp: any) => {
+            const _data = resp.result.filter((it: any) => {
+              return _.map(it?.features || [], 'id').includes('supportFirmware');
+            });
+            return _data.map((item: any) => ({ label: item.name, value: item.id }));
+          }),
     },
     {
       title: intl.formatMessage({

+ 4 - 1
src/pages/device/Instance/Detail/Functions/form.tsx

@@ -270,7 +270,10 @@ export default (props: FunctionProps) => {
           })}
         </p>
-        <Input.TextArea value={JSON.stringify(result?.[0])} rows={6} />
+        <Input.TextArea
+          value={Array.isArray(result) ? JSON.stringify(result?.[0]) : JSON.stringify(result)}
+          rows={6}
+        />
       </div>
     </div>
   );

+ 1 - 1
src/pages/device/Instance/Detail/Modbus/index.tsx

@@ -222,7 +222,7 @@ export default (props: Props) => {
     });
   }, []);
   useEffect(() => {
-    const metadata = JSON.parse(data.metadata).properties?.map((item: any) => ({
+    const metadata = JSON.parse(data.metadata || '{}').properties?.map((item: any) => ({
       metadataId: item.id,
       metadataName: `${item.name}(${item.id})`,
       metadataType: 'property',

+ 11 - 1
src/pages/device/Instance/index.tsx

@@ -319,7 +319,7 @@ const Instance = () => {
     },
     {
       title: '网关类型',
-      dataIndex: 'productId$product-info',
+      dataIndex: 'accessProvider',
       width: 150,
       ellipsis: true,
       valueType: 'select',
@@ -586,6 +586,11 @@ const Instance = () => {
                 column: 'productId$product-info',
                 value: [e],
               };
+            } else if (e.column === 'accessProvider') {
+              return {
+                ...e,
+                column: 'productId$product-info',
+              };
             } else {
               return e;
             }
@@ -597,6 +602,11 @@ const Instance = () => {
                   column: 'productId$product-info',
                   value: [e],
                 };
+              } else if (e.column === 'accessProvider') {
+                return {
+                  ...e,
+                  column: 'productId$product-info',
+                };
               } else {
                 return e;
               }

+ 1 - 0
src/pages/device/Product/Detail/Access/AccessConfig/index.tsx

@@ -84,6 +84,7 @@ const AccessConfig = (props: Props) => {
     };
     service.queryList({ ...temp, sorts: [{ name: 'createTime', order: 'desc' }] }).then((resp) => {
       setDataSource(resp?.result);
+      setCurrrent(resp?.result?.data?.[0]);
     });
   };
 

+ 0 - 1
src/pages/device/Product/Detail/Access/index.tsx

@@ -552,7 +552,6 @@ const Access = () => {
           >
             保存
           </PermissionButton>
-          ,
           {/* <Button
             type="primary"
             onClick={async () => {

+ 1 - 4
src/pages/device/components/Metadata/Base/Edit/index.tsx

@@ -32,7 +32,7 @@ import {
   FileTypeList,
   PropertySource,
 } from '@/pages/device/data';
-import { useEffect, useMemo, useState } from 'react';
+import { useMemo, useState } from 'react';
 import { productModel } from '@/pages/device/Product';
 import { service } from '@/pages/device/components/Metadata';
 import { Store } from 'jetlinks-store';
@@ -63,9 +63,6 @@ interface Props {
 const Edit = observer((props: Props) => {
   const intl = useIntl();
   const [loading, setLoading] = useState<boolean>(false);
-  useEffect(() => {
-    console.log(props.tabs);
-  }, []);
   const form = useMemo(
     () =>
       createForm({

+ 2 - 2
src/pages/document.ejs

@@ -224,11 +224,11 @@
           </div>
         </div>
         <div style="display: flex; align-items: center; justify-content: center">
-          <img
+          <!-- <img
             src="<%= context.config.publicPath + 'logo.svg' %>"
             width="200"
             style="margin-right: 8px"
-          />
+          /> -->
         </div>
       </div>
     </div>

+ 14 - 9
src/pages/link/Channel/Opcua/Export/index.tsx

@@ -26,15 +26,20 @@ const Export = (props: Props) => {
   });
 
   useEffect(() => {
-    service.noPagingOpcua({ paging: false }).then((resp) => {
-      if (resp.status === 200) {
-        const items = resp.result.map((item: { name: any; id: any }) => ({
-          label: item.name,
-          value: item.id,
-        }));
-        setList(items);
-      }
-    });
+    service
+      .noPagingOpcua({
+        paging: false,
+        sorts: [{ name: 'createTime', order: 'desc' }],
+      })
+      .then((resp) => {
+        if (resp.status === 200) {
+          const items = resp.result.map((item: { name: any; id: any }) => ({
+            label: item.name,
+            value: item.id,
+          }));
+          setList(items);
+        }
+      });
   }, []);
 
   const form = createForm();

+ 6 - 14
src/pages/link/Channel/Opcua/index.tsx

@@ -51,11 +51,9 @@ const NewOpc = () => {
   const [currentData, setCurrentData] = useState<any>({});
 
   const collectMap = new Map();
-  collectMap.set('good', 'success');
-  collectMap.set('failed', 'error');
-  collectMap.set('bad', 'warning');
-  collectMap.set('uncertain', 'default');
-  collectMap.set('unknown', 'default');
+  collectMap.set('running', 'success');
+  collectMap.set('error', 'error');
+  collectMap.set('stopped', 'warning');
 
   const menu = (
     <Menu>
@@ -195,15 +193,9 @@ const NewOpc = () => {
             }),
             onConfirm: async () => {
               if (record.state.value === 'disabled') {
-                await service.editPoint(record.id, {
-                  ...record,
-                  state: 'enabled',
-                });
+                await service._enable([record.id]);
               } else {
-                await service.editPoint(record.id, {
-                  ...record,
-                  state: 'disabled',
-                });
+                await service._disabled([record.id]);
               }
               onlyMessage(
                 intl.formatMessage({
@@ -367,7 +359,7 @@ const NewOpc = () => {
                 isPermission={permission.add}
                 key="add"
                 icon={<PlusOutlined />}
-                type="default"
+                type="primary"
                 style={{ width: '100%', marginTop: 16, marginBottom: 16 }}
               >
                 新增

+ 9 - 7
src/pages/link/Channel/Opcua/savePoint.tsx

@@ -15,6 +15,7 @@ const SavePoint = (props: Props) => {
 
   const handleSave = async () => {
     const formData = await form.validateFields();
+    console.log(formData, 'formData');
     if (props.data.id) {
       service
         .editPoint(props.data.id, {
@@ -43,7 +44,6 @@ const SavePoint = (props: Props) => {
   };
 
   useEffect(() => {
-    console.log(props.data);
     if (props.data.id) {
       setDataMode(props.data.dataMode?.value);
     }
@@ -183,16 +183,16 @@ const SavePoint = (props: Props) => {
                 <Select.Option value="pull" key={'pull'}>
                   拉取
                 </Select.Option>
-                <Select.Option value="pullChange" key={'pullChange'}>
+                <Select.Option value="pullChanged" key={'pullChanged'}>
                   拉取变更值
                 </Select.Option>
-                <Select.Option value="pullPassive" key={'pullPassive'}>
+                <Select.Option value="active" key={'active'}>
                   被动读取
                 </Select.Option>
               </Select>
             </Form.Item>
           </Col>
-          {dataMode !== 'pullPassive' && (
+          {dataMode !== 'active' && (
             <Col span={12}>
               {dataMode === 'sub' && (
                 <Form.Item
@@ -200,9 +200,10 @@ const SavePoint = (props: Props) => {
                   name="interval"
                   tooltip="OPC UA服务器采样点位数据发生变化的频率"
                   rules={[
+                    { required: true, message: '采集频率必填' },
                     ({}) => ({
                       validator(_, value) {
-                        if (value !== 0 || /(^[1-9]\d*$)/.test(value)) {
+                        if (value > 0 || /(^[1-9]\d*$)/.test(value)) {
                           return Promise.resolve();
                         }
                         return Promise.reject(new Error('请输入正整数'));
@@ -217,14 +218,15 @@ const SavePoint = (props: Props) => {
                   />
                 </Form.Item>
               )}
-              {(dataMode === 'pullChange' || dataMode === 'pull') && (
+              {(dataMode === 'pullChanged' || dataMode === 'pull') && (
                 <Form.Item
                   label="拉取频率"
                   name="interval"
                   rules={[
+                    { required: true, message: '拉取频率必填' },
                     ({}) => ({
                       validator(_, value) {
-                        if (value !== 0 || /(^[1-9]\d*$)/.test(value)) {
+                        if (value > 0 || /(^[1-9]\d*$)/.test(value)) {
                           return Promise.resolve();
                         }
                         return Promise.reject(new Error('请输入正整数'));

+ 10 - 0
src/pages/link/Channel/Opcua/service.ts

@@ -37,6 +37,16 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data: params,
     });
+  _enable = (params: any) =>
+    request(`${SystemConst.API_BASE}/opc/point/_enable`, {
+      method: 'POST',
+      data: params,
+    });
+  _disabled = (params: any) =>
+    request(`${SystemConst.API_BASE}/opc/point/_disable`, {
+      method: 'POST',
+      data: params,
+    });
   PointList = (params: any) =>
     request(`${SystemConst.API_BASE}/opc/point/_query`, {
       method: 'POST',

+ 52 - 1
src/pages/media/Stream/index.tsx

@@ -6,7 +6,13 @@ import { useEffect, useState } from 'react';
 import Service from '@/pages/media/Stream/service';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { useHistory } from 'umi';
-import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
+import {
+  CloseCircleOutlined,
+  DeleteOutlined,
+  EditOutlined,
+  PlayCircleOutlined,
+  PlusOutlined,
+} from '@ant-design/icons';
 import { model } from '@formily/reactive';
 import { PermissionButton } from '@/components';
 import { useDomFullHeight } from '@/hooks';
@@ -34,6 +40,21 @@ const Stream = () => {
       title: '名称',
       ellipsis: true,
     },
+    {
+      dataIndex: 'state',
+      title: '状态',
+      valueType: 'select',
+      valueEnum: {
+        disabled: {
+          text: '禁用',
+          status: 'disabled',
+        },
+        enabled: {
+          text: '正常',
+          status: 'enabled',
+        },
+      },
+    },
   ];
 
   const [dataSource, setDataSource] = useState<any>({
@@ -120,6 +141,36 @@ const Stream = () => {
                             编辑
                           </PermissionButton>,
                           <PermissionButton
+                            isPermission={permission.action}
+                            key="action"
+                            type={'link'}
+                            popConfirm={{
+                              title: `确认${item?.state?.value === 'enabled' ? '禁用' : '启用'}?`,
+                              onConfirm: async () => {
+                                if (item?.state?.value === 'enabled') {
+                                  const res = await service.disable(item.id);
+                                  if (res.status === 200) {
+                                    onlyMessage('操作成功');
+                                    handleSearch(param);
+                                  }
+                                } else {
+                                  const res = await service.enalbe(item.id);
+                                  if (res.status === 200) {
+                                    onlyMessage('操作成功');
+                                    handleSearch(param);
+                                  }
+                                }
+                              },
+                            }}
+                          >
+                            {item?.state?.value === 'enabled' ? (
+                              <CloseCircleOutlined />
+                            ) : (
+                              <PlayCircleOutlined />
+                            )}
+                            {item?.state?.value === 'enabled' ? '禁用' : '启用'}
+                          </PermissionButton>,
+                          <PermissionButton
                             isPermission={permission.delete}
                             popConfirm={{
                               title: '确认删除',

+ 4 - 0
src/pages/media/Stream/typings.d.ts

@@ -12,4 +12,8 @@ type StreamItem = {
     dynamicRtpPort: boolean;
     dynamicRtpPortRange: number[];
   };
+  state: {
+    value: string;
+    text: string;
+  };
 };

+ 1 - 1
src/pages/notice/Template/Detail/doc/DingTalk.tsx

@@ -29,7 +29,7 @@ const DingTalk = () => {
       <div> 使用固定的通知配置发送此通知模板</div>
       <h2> 2、Agentid</h2>
       <div> 应用唯一标识</div>
-      <div> 获取路径:“钉钉开平台”--“应用开发”--“查看应用”</div>
+      <div> 获取路径:“钉钉开平台”--“应用开发”--“查看应用”</div>
       <div className="image">
         <Image width="100%" src={agentId} />
       </div>

+ 1 - 1
src/pages/notice/Template/Detail/doc/DingTalkRebot.tsx

@@ -15,7 +15,7 @@ const DingTalkRebot = () => {
         通知模板结合通知配置为告警消息通知提供支撑。通知模板只能调用同一类型的通知配置服务。
       </div>
       <div>
-        使用钉钉群机器人消息通知时需在钉钉开平台中创建好对应的机器人,再到钉钉客户端在对应的群众绑定智能机器人。
+        使用钉钉群机器人消息通知时需在钉钉开平台中创建好对应的机器人,再到钉钉客户端在对应的群众绑定智能机器人。
       </div>
       <h1>2.模板配置说明</h1>
       <div>

+ 1 - 1
src/pages/notice/Template/Detail/index.tsx

@@ -795,7 +795,7 @@ const Detail = observer(() => {
                     properties: {
                       departmentIdList: {
                         title: '收信部门',
-                        required: true,
+                        // required: true,
                         'x-component': 'Select',
                         'x-decorator': 'FormItem',
                         // 'x-decorator-props': {

+ 7 - 3
src/pages/system/Apply/Menu/index.tsx

@@ -93,9 +93,12 @@ const MenuPage = (props: Props) => {
   };
 
   useEffect(() => {
-    getOwner();
-    getMenus();
-  }, []);
+    console.log(data);
+    if (data.id) {
+      getOwner();
+      getMenus();
+    }
+  }, [data]);
 
   return (
     <Modal
@@ -135,6 +138,7 @@ const MenuPage = (props: Props) => {
           </Option>
         ))}
       </Select>
+      <div>{treeData.length !== 0 ? '当前集成菜单' : ''}</div>
       <Tree
         fieldNames={{
           title: 'name',

+ 47 - 18
src/pages/system/Apply/Save/index.tsx

@@ -29,6 +29,7 @@ import type { Response } from '@/utils/typings';
 import usePermissions from '@/hooks/permission';
 import { useHistory, useLocation } from '@/hooks';
 import { getMenuPathByCode } from '@/utils/menu';
+import MenuPage from '../Menu';
 
 const Save = () => {
   const location = useLocation();
@@ -38,6 +39,8 @@ const Save = () => {
   const { permission } = PermissionButton.usePermission('system/Apply');
   const [view, setView] = useState<boolean>(false);
   const [id, setId] = useState<string>('');
+  const [visible, setVisiable] = useState<boolean>(false);
+  const [detail, setDetail] = useState<any>({});
 
   const provider1 = require('/public/images/apply/provider1.png');
   const provider2 = require('/public/images/apply/provider2.png');
@@ -142,7 +145,6 @@ const Save = () => {
         if (!id) return;
         const resp = await service.detail(id);
         const integrationModes = resp.result.integrationModes.map((item: any) => item.value);
-        console.log(integrationModes);
         formInit.setInitialValues({
           ...resp.result,
           integrationModes,
@@ -151,7 +153,7 @@ const Save = () => {
       });
       onFieldValueChange('provider', (field, form1) => {
         const value = field.value;
-        console.log(value);
+        // console.log(value);
         if (field.modified) {
           switch (value) {
             case 'internal-standalone':
@@ -210,7 +212,7 @@ const Save = () => {
       });
       onFieldReact('apiClient.authConfig.oauth2.clientId', (filed) => {
         const parms = filed.query('provider').get('value');
-        console.log(parms);
+        // console.log(parms);
         if (id && parms === 'internal-standalone') {
           filed.componentProps = {
             disabled: true,
@@ -235,22 +237,43 @@ const Save = () => {
         data.id = data.apiServer.appId;
       }
     }
-    if (id) {
-      const resp: any = await service.modify(id, data);
-      if (resp.status === 200) {
-        onlyMessage('保存成功');
-        const url = getMenuPathByCode('system/Apply');
-        history.push(url);
-      }
+    //独立应用,单点登录需要api配置和单点登录配置
+    if (
+      data.provider === 'internal-standalone' &&
+      data.integrationModes.includes('ssoClient') &&
+      data.integrationModes.length === 1
+    ) {
+      onlyMessage('配置单点登录需同时配置api配置', 'warning');
     } else {
-      const res: any = await service.save(data);
-      if (res.status === 200) {
-        onlyMessage('保存成功');
-        const url = getMenuPathByCode('system/Apply');
-        history.push(url);
+      if (id) {
+        const resp: any = await service.modify(id, data);
+        if (resp.status === 200) {
+          const isPage = data.integrationModes.includes('page');
+          if (isPage) {
+            setVisiable(true);
+            setDetail(data);
+          } else {
+            onlyMessage('保存成功');
+            const url = getMenuPathByCode('system/Apply');
+            history.push(url);
+          }
+        }
+      } else {
+        const res: any = await service.save(data);
+        if (res.status === 200) {
+          const isPage = data.integrationModes.includes('page');
+          if (isPage) {
+            setVisiable(true);
+            setDetail(data);
+          } else {
+            onlyMessage('保存成功');
+            const url = getMenuPathByCode('system/Apply');
+            history.push(url);
+          }
+        }
       }
     }
-    console.log(data);
+    // console.log(data);
   };
 
   //单点登录
@@ -1033,7 +1056,6 @@ const Save = () => {
                       style={{ padding: 0 }}
                       isPermission={rolePermission.add}
                       onClick={() => {
-                        console.log(rolePermission.add, permission.update);
                         const tab: any = window.open(`${origin}/#/system/role?save=true`);
                         tab!.onTabSaveSuccess = (value: any) => {
                           form.setFieldState('roleIdList', async (state) => {
@@ -1537,7 +1559,6 @@ const Save = () => {
                           style={{ padding: 0 }}
                           isPermission={rolePermission.add}
                           onClick={() => {
-                            console.log(rolePermission.add, permission.update);
                             const tab: any = window.open(`${origin}/#/system/role?save=true`);
                             tab!.onTabSaveSuccess = (value: any) => {
                               form.setFieldState('roleIdList', async (state) => {
@@ -1676,6 +1697,14 @@ const Save = () => {
           </Col>
         </Row>
       </Card>
+      {visible && (
+        <MenuPage
+          data={detail}
+          close={() => {
+            setVisiable(false);
+          }}
+        />
+      )}
     </PageContainer>
   );
 };

+ 1 - 1
src/pages/system/Apply/index.tsx

@@ -148,7 +148,7 @@ const Apply = () => {
         isPage(record.integrationModes) ? (
           <PermissionButton
             isPermission={permission.update}
-            key="edit"
+            key="page"
             onClick={() => {
               setData(record);
               setMenuVisiable(true);

+ 10 - 0
src/pages/system/Menu/Setting/baseMenu.ts

@@ -510,6 +510,11 @@ export default [
                 name: '新增',
                 permissions: [{ permission: 'certificate', actions: ['save'] }],
               },
+              {
+                id: 'view',
+                name: '查看',
+                permissions: [{ permission: 'certificate', actions: ['query'] }],
+              },
             ],
           },
           {
@@ -538,6 +543,11 @@ export default [
                 permissions: [{ permission: 'media-server', actions: ['query', 'save'] }],
               },
               {
+                id: 'action',
+                name: '启/禁用',
+                permissions: [{ permission: 'media-server', actions: ['save'] }],
+              },
+              {
                 id: 'add',
                 name: '新增',
                 permissions: [{ permission: 'media-server', actions: ['query', 'save'] }],

+ 36 - 0
src/utils/menu/index.ts

@@ -270,6 +270,42 @@ const getRoutes = (extraRoutes: MenuItem[], level = 1): IRouteProps[] => {
     return _route;
   });
 };
+export const getRoutesLayout = (extraRoutes: MenuItem[], level = 1): IRouteProps[] => {
+  const allComponents = findComponents(require.context('@/pages', true, /index(\.tsx)$/));
+  return extraRoutes.map((route) => {
+    const component = allComponents[route.code] || null;
+    const _route: IRouteProps = {
+      key: route.url,
+      name: route.name,
+      path: route.url,
+      layout: false,
+    };
+
+    // console.log(_route,'layout')
+    if (route.children && route.children.length) {
+      const flatRoutes = getRoutes(flatRoute(route.children || []), level + 1);
+      const redirect = flatRoutes.filter((r) => r.component)[0]?.path;
+      _route.children = redirect
+        ? [
+            ...flatRoutes,
+            {
+              path: _route.path,
+              exact: true,
+              redirect: redirect,
+            },
+          ]
+        : flatRoutes;
+    } else if (component) {
+      _route.component = component;
+    }
+
+    if (level !== 1) {
+      _route.exact = true;
+    }
+    // console.log(_route);
+    return _route;
+  });
+};
 
 export const getMenus = (extraRoutes: IRouteProps[]): any[] => {
   return extraRoutes.map((route) => {