Explorar el Código

feat: 应用管理列表

wzyyy hace 3 años
padre
commit
f3bcf01843

+ 4 - 4
config/proxy.ts

@@ -15,13 +15,13 @@ export default {
       // target: 'http://120.79.18.123:8844/',
       // ws: 'ws://120.79.18.123:8844/',
       // 测试环境
-      // target: 'http://120.77.179.54:8844/',
-      // ws: 'ws://120.77.179.54:8844/',
+      target: 'http://120.77.179.54:8844/',
+      ws: 'ws://120.77.179.54:8844/',
       // target: 'http://192.168.66.5:8844/',
       // ws: 'ws://192.168.66.5:8844/',
       //v2环境
-      ws: 'ws://47.109.52.230:8844',
-      target: 'http://47.109.52.230:8844',
+      // ws: 'ws://47.109.52.230:8844',
+      // target: 'http://47.109.52.230:8844',
       changeOrigin: true,
       pathRewrite: { '^/api': '' },
     },

BIN
public/images/apply.png


BIN
public/images/apply/provider1.png


BIN
public/images/apply/provider2.png


BIN
public/images/apply/provider3.png


BIN
public/images/apply/provider4.png


BIN
public/images/apply/provider5.png


+ 56 - 0
src/components/ProTableCard/CardItems/applyCard.tsx

@@ -0,0 +1,56 @@
+import React from 'react';
+import { StatusColorEnum } from '@/components/BadgeStatus';
+import { Ellipsis, TableCard } from '@/components';
+import '@/style/common.less';
+import '../index.less';
+
+export interface DeviceCardProps extends ApplyItem {
+  actions: React.ReactNode[];
+  detail?: React.ReactNode;
+}
+
+const defaultImage = require('/public/images/apply.png');
+
+const providerType = new Map();
+providerType.set('internal-standalone', '内部独立应用');
+providerType.set('wechat-webapp', '微信网站应用');
+providerType.set('internal-integrated', '内部集成应用');
+providerType.set('dingtalk-ent-app', '钉钉企业内部应用');
+providerType.set('third-party', '第三方应用');
+
+export default (props: DeviceCardProps) => {
+  return (
+    <TableCard
+      showMask={false}
+      detail={props.detail}
+      actions={props.actions}
+      status={props.state}
+      statusText={props.state === 'disabled' ? '禁用' : '正常'}
+      statusNames={{
+        enabled: StatusColorEnum.success,
+        disabled: StatusColorEnum.error,
+      }}
+    >
+      <div className={'pro-table-card-item'}>
+        <div className={'card-item-avatar'}>
+          <img width={88} height={88} src={defaultImage} alt={''} />
+        </div>
+        <div className={'card-item-body'}>
+          <div className={'card-item-header'}>
+            <Ellipsis title={props.name} titleClassName={'card-item-header-name'} />
+          </div>
+          <div className={'card-item-content'}>
+            <div>
+              <label>类型</label>
+              <Ellipsis title={providerType.get(props.provider)} />
+            </div>
+            <div>
+              <label>说明</label>
+              <Ellipsis title={props.description} />
+            </div>
+          </div>
+        </div>
+      </div>
+    </TableCard>
+  );
+};

+ 1 - 1
src/pages/rule-engine/Scene/Save/action/action.tsx

@@ -152,7 +152,6 @@ export default observer((props: ActionProps) => {
         setNotifyType(data.notify?.notifyType);
         setConfigId(data.notify?.notifierId);
         setTemplateId(data.notify?.templateId);
-        // console.log(props.form.getFieldsValue(),'actions')
       }
     }
   }, []);
@@ -272,6 +271,7 @@ export default observer((props: ActionProps) => {
     if (type1 === 'notify') {
       queryMessageTypes();
     }
+    console.log(props.form.getFieldsValue(), 'action');
   }, [type1]);
 
   return (

+ 2 - 3
src/pages/rule-engine/Scene/Save/action/messageContent.tsx

@@ -105,9 +105,8 @@ export default (props: MessageContentProps) => {
     [props.notifyType],
   );
   useEffect(() => {
-    // console.log(props.template,'messageContent')
-    // console.log(props.triggerRef?.getTriggerData(),'triggerRef')
-    console.log(props.form.getFieldValue('actions'), 'message');
+    // console.log(props.form.getFieldValue('actions'), 'message');
+    console.log(props.form.getFieldsValue(), 'message');
   }, []);
   return (
     <>

+ 1 - 3
src/pages/rule-engine/Scene/Save/index.tsx

@@ -68,7 +68,7 @@ export default () => {
         setIsEdit(true);
         const _data: any = resp.result;
         FormModel = _data;
-        console.log(_data.actions, 'initdata');
+        console.log(_data);
 
         form.setFieldsValue(_data);
         // debugger;
@@ -85,7 +85,6 @@ export default () => {
         }
 
         if (_data.actions) {
-          console.log(_data.actions, 'detail');
           setActionsData(_data.actions);
         }
       }
@@ -229,7 +228,6 @@ export default () => {
               preserve={false}
               className={'scene-save'}
               onValuesChange={(changeValue, allValues) => {
-                console.log(changeValue);
                 if (changeValue.trigger) {
                   if (changeValue.trigger.device) {
                     if (

+ 46 - 0
src/pages/system/Apply/Save/index.less

@@ -0,0 +1,46 @@
+.apply {
+  .doc {
+    height: 1000px;
+    padding: 24px;
+    overflow-y: auto;
+    color: rgba(#000, 0.8);
+    font-size: 14px;
+    background-color: #fafafa;
+
+    .url {
+      padding: 8px 16px;
+      color: #2f54eb;
+      background-color: rgba(#a7bdf7, 0.2);
+    }
+
+    h1 {
+      margin: 16px 0;
+      color: rgba(#000, 0.85);
+      font-weight: bold;
+      font-size: 14px;
+
+      &:first-child {
+        margin-top: 0;
+      }
+    }
+
+    h2 {
+      margin: 6px 0;
+      color: rgba(0, 0, 0, 0.8);
+      font-size: 14px;
+    }
+
+    .image {
+      margin: 16px 0;
+    }
+  }
+}
+
+.form {
+  :global {
+    .ant-radio-button-wrapper {
+      height: 100%;
+      margin: 5px 20px 0 0;
+    }
+  }
+}

+ 174 - 0
src/pages/system/Apply/Save/index.tsx

@@ -0,0 +1,174 @@
+import { PermissionButton, TitleComponent } from '@/components';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Card, Col, Row } from 'antd';
+import styles from './index.less';
+import {
+  ArrayCollapse,
+  Form,
+  FormButtonGroup,
+  FormItem,
+  Input,
+  Select,
+  Radio,
+} from '@formily/antd';
+import { useEffect, useMemo, useState } from 'react';
+import { createSchemaField } from '@formily/react';
+import { createForm } from '@formily/core';
+import { useAsyncDataSource } from '@/utils/util';
+import { service } from '../index';
+
+const Save = () => {
+  const { permission } = PermissionButton.usePermission('system/Apply');
+  const [view, setView] = useState<boolean>(false);
+
+  const provider1 = require('/public/images/apply/provider1.png');
+  const provider2 = require('/public/images/apply/provider2.png');
+  const provider3 = require('/public/images/apply/provider3.png');
+  const provider4 = require('/public/images/apply/provider4.png');
+  const provider5 = require('/public/images/apply/provider5.png');
+
+  const providerType = new Map();
+  providerType.set('internal-standalone', provider1);
+  providerType.set('internal-integrated', provider2);
+  providerType.set('dingtalk-ent-app', provider3);
+  providerType.set('wechat-webapp', provider4);
+  providerType.set('third-party', provider5);
+
+  const createImageLabel = (image: string, text: string) => {
+    return (
+      <div
+        style={{ textAlign: 'center', marginTop: 10, fontSize: '14px', width: 115, height: 120 }}
+      >
+        <img height="64px" src={image} style={{ marginTop: 10 }} />
+        <div
+          style={{
+            color: '#000000',
+            marginTop: 5,
+          }}
+        >
+          {text}
+        </div>
+      </div>
+    );
+  };
+
+  const SchemaField = createSchemaField({
+    components: {
+      FormItem,
+      Input,
+      Select,
+      Radio,
+      ArrayCollapse,
+    },
+  });
+
+  const getProvidersAll = () => {
+    return service.getProvidersAll().then((res) => {
+      if (res.status === 200) {
+        return res.result.map((item: any) => ({
+          label: createImageLabel(providerType.get(item.provider), item.name),
+          value: item.provider,
+        }));
+      }
+    });
+  };
+
+  const form = useMemo(() => createForm({}), []);
+  const schema = {
+    type: 'object',
+    properties: {
+      name: {
+        type: 'string',
+        title: '名称',
+        required: true,
+        'x-decorator': 'FormItem',
+        'x-component': 'Input',
+        'x-component-props': {
+          placeholder: '请输入名称',
+        },
+        'x-validator': [
+          {
+            max: 64,
+            message: '最多可输入64个字符',
+          },
+          {
+            required: true,
+            message: '请输入名称',
+          },
+        ],
+      },
+      provider: {
+        title: '应用',
+        'x-decorator': 'FormItem',
+        'x-component': 'Radio.Group',
+        'x-component-props': {
+          optionType: 'button',
+          placeholder: '请选择应用',
+        },
+        required: true,
+        'x-reactions': '{{useAsyncDataSource(getProvidersAll)}}',
+        'x-decorator-props': {
+          gridSpan: 1,
+        },
+        'x-validator': [
+          {
+            required: true,
+            message: '请选择应用',
+          },
+        ],
+      },
+      description: {
+        title: '说明',
+        'x-component': 'Input.TextArea',
+        'x-decorator': 'FormItem',
+        'x-component-props': {
+          rows: 3,
+          showCount: true,
+          maxLength: 200,
+          placeholder: '请输入说明',
+        },
+      },
+    },
+  };
+
+  useEffect(() => {
+    setView(false);
+  }, []);
+  return (
+    <PageContainer>
+      <Card>
+        <Row gutter={24}>
+          <Col span={14}>
+            <TitleComponent data={'基本信息'} />
+            <Form form={form} layout="vertical" className={styles.form}>
+              <SchemaField
+                schema={schema}
+                scope={{
+                  useAsyncDataSource,
+                  getProvidersAll,
+                }}
+              />
+              <FormButtonGroup.Sticky>
+                <FormButtonGroup.FormItem>
+                  {!view && (
+                    <PermissionButton
+                      type="primary"
+                      isPermission={permission.add || permission.update || true}
+                      // onClick={() => handleSave()}
+                    >
+                      保存
+                    </PermissionButton>
+                  )}
+                </FormButtonGroup.FormItem>
+              </FormButtonGroup.Sticky>
+            </Form>
+          </Col>
+          <Col span={10} className={styles.apply}>
+            <div className={styles.doc}>文档</div>
+          </Col>
+        </Row>
+      </Card>
+    </PageContainer>
+  );
+};
+export default Save;

+ 323 - 0
src/pages/system/Apply/index.tsx

@@ -0,0 +1,323 @@
+import { PermissionButton, ProTableCard } from '@/components';
+import ApplyCard from '@/components/ProTableCard/CardItems/applyCard';
+import SearchComponent from '@/components/SearchComponent';
+import useHistory from '@/hooks/route/useHistory';
+import { getMenuPathByCode } from '@/utils/menu';
+import { onlyMessage } from '@/utils/util';
+import {
+  DeleteOutlined,
+  EditOutlined,
+  PlayCircleOutlined,
+  PlusOutlined,
+  StopOutlined,
+} from '@ant-design/icons';
+import { PageContainer } from '@ant-design/pro-layout';
+import { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { Badge } from 'antd';
+import { useRef, useState } from 'react';
+import { useIntl } from 'umi';
+import Service from './service';
+
+export const service = new Service('application');
+
+const Apply = () => {
+  const actionRef = useRef<ActionType>();
+  const history = useHistory();
+  const [searchParams, setSearchParams] = useState<any>({});
+  const { permission } = PermissionButton.usePermission('system/Apply');
+  const intl = useIntl();
+
+  const providerType = new Map();
+  providerType.set('internal-standalone', '内部独立应用');
+  providerType.set('wechat-webapp', '微信网站应用');
+  providerType.set('internal-integrated', '内部集成应用');
+  providerType.set('dingtalk-ent-app', '钉钉企业内部应用');
+  providerType.set('third-party', '第三方应用');
+
+  const _action = (id: string, data: any) => {
+    service.modify(id, data).then((res) => {
+      if (res.status === 200) {
+        onlyMessage('操作成功');
+        actionRef.current?.reload();
+      } else {
+        onlyMessage('操作失败', 'error');
+      }
+    });
+  };
+
+  const columns: ProColumns<any>[] = [
+    {
+      dataIndex: 'name',
+      ellipsis: true,
+      title: '名称',
+    },
+    {
+      dataIndex: 'provider',
+      title: '类型',
+      ellipsis: true,
+      valueType: 'select',
+      valueEnum: {
+        'internal-standalone': {
+          text: '内部独立应用',
+          status: 'internal-standalone',
+        },
+        'wechat-webapp': {
+          text: '微信网站应用',
+          status: 'wechat-webapp',
+        },
+        'internal-integrated': {
+          text: '内部集成应用',
+          status: 'internal-integrated',
+        },
+        'dingtalk-ent-app': {
+          text: '钉钉企业内部应用',
+          status: 'dingtalk-ent-app',
+        },
+        'third-party': {
+          text: '第三方应用',
+          status: 'third-party',
+        },
+      },
+      renderText: (provider) => <>{providerType.get(provider)}</>,
+    },
+    {
+      dataIndex: 'state',
+      title: '状态',
+      valueType: 'select',
+      renderText: (state) => (
+        <Badge
+          text={state === 'disabled' ? '禁用' : '正常'}
+          status={state === 'disabled' ? 'error' : 'success'}
+        />
+      ),
+      valueEnum: {
+        disabled: {
+          text: '禁用',
+          status: 'disabled',
+        },
+        enabled: {
+          text: '正常',
+          status: 'enabled',
+        },
+      },
+    },
+    {
+      dataIndex: 'description',
+      ellipsis: true,
+      title: '说明',
+    },
+    {
+      title: '操作',
+      valueType: 'option',
+      fixed: 'right',
+      render: (text, record) => [
+        <PermissionButton
+          isPermission={permission.update}
+          key="edit"
+          onClick={() => {
+            // setCurrent(record);
+            // setVisible(true);
+          }}
+          type={'link'}
+          style={{ padding: 0 }}
+          tooltip={{
+            title: intl.formatMessage({
+              id: 'pages.data.option.edit',
+              defaultMessage: '编辑',
+            }),
+          }}
+        >
+          <EditOutlined />
+        </PermissionButton>,
+        <PermissionButton
+          isPermission={permission.action}
+          key="action"
+          type={'link'}
+          style={{ padding: 0 }}
+          tooltip={{
+            title: record.state !== 'disabled' ? '禁用' : '启用',
+          }}
+          popConfirm={{
+            title: `确认${record.state === 'disabled' ? '禁用' : '启用'}`,
+            onConfirm: () => {
+              if (record.state === 'disabled') {
+                _action(record.id, {
+                  state: 'enabled',
+                });
+              } else {
+                _action(record.id, {
+                  state: 'disabled',
+                });
+              }
+            },
+          }}
+        >
+          {record.state !== 'disabled' ? <StopOutlined /> : <PlayCircleOutlined />}
+        </PermissionButton>,
+        <PermissionButton
+          isPermission={permission.delete}
+          tooltip={{
+            title: record.state !== 'disabled' ? '删除' : '请先禁用该应用,再删除',
+          }}
+          style={{ padding: 0 }}
+          disabled={record.state !== 'disabled'}
+          popConfirm={{
+            title: '确认删除',
+            disabled: record.state !== 'disabled',
+            onConfirm: async () => {
+              const resp: any = await service.remove(record.id);
+              if (resp.status === 200) {
+                onlyMessage(
+                  intl.formatMessage({
+                    id: 'pages.data.option.success',
+                    defaultMessage: '操作成功!',
+                  }),
+                );
+                actionRef.current?.reload();
+              } else {
+                onlyMessage(resp?.message || '操作失败', 'error');
+              }
+            },
+          }}
+          key="delete"
+          type="link"
+        >
+          <DeleteOutlined />
+        </PermissionButton>,
+      ],
+    },
+  ];
+
+  return (
+    <PageContainer>
+      <SearchComponent
+        field={columns}
+        target="Apply"
+        onSearch={(data) => {
+          actionRef.current?.reset?.();
+          setSearchParams(data);
+        }}
+      />
+      <ProTableCard
+        columns={columns}
+        actionRef={actionRef}
+        scroll={{ x: 1366 }}
+        params={searchParams}
+        columnEmptyText={''}
+        options={{ fullScreen: true }}
+        request={(params) =>
+          service.query({
+            ...params,
+            sorts: [
+              {
+                name: 'createTime',
+                order: 'desc',
+              },
+            ],
+          })
+        }
+        rowKey="id"
+        search={false}
+        pagination={{ pageSize: 10 }}
+        headerTitle={[
+          <PermissionButton
+            onClick={() => {
+              const url = getMenuPathByCode('system/Apply/Save');
+              history.push(url);
+            }}
+            style={{ marginRight: 12 }}
+            isPermission={permission.add}
+            key="button"
+            icon={<PlusOutlined />}
+            type="primary"
+          >
+            新增
+          </PermissionButton>,
+        ]}
+        gridColumn={3}
+        cardRender={(record) => (
+          <ApplyCard
+            {...record}
+            actions={[
+              <PermissionButton
+                isPermission={permission.update}
+                key="edit"
+                onClick={() => {
+                  // setCurrent(record);
+                  // setVisible(true);
+                }}
+                type={'link'}
+                style={{ padding: 0 }}
+                tooltip={{
+                  title: intl.formatMessage({
+                    id: 'pages.data.option.edit',
+                    defaultMessage: '编辑',
+                  }),
+                }}
+              >
+                <EditOutlined />
+                编辑
+              </PermissionButton>,
+              <PermissionButton
+                isPermission={permission.action}
+                key="action"
+                type={'link'}
+                style={{ padding: 0 }}
+                tooltip={{
+                  title: record.state !== 'disabled' ? '禁用' : '启用',
+                }}
+                popConfirm={{
+                  title: `确认${record.state !== 'disabled' ? '禁用' : '启用'}`,
+                  onConfirm: () => {
+                    if (record.state === 'disabled') {
+                      _action(record.id, {
+                        state: 'enabled',
+                      });
+                    } else {
+                      _action(record.id, {
+                        state: 'disabled',
+                      });
+                    }
+                  },
+                }}
+              >
+                {record.state !== 'disabled' ? <StopOutlined /> : <PlayCircleOutlined />}
+                {record.state !== 'disabled' ? '禁用' : '启用'}
+              </PermissionButton>,
+              <PermissionButton
+                isPermission={permission.delete}
+                tooltip={{
+                  title: record.state === 'disabled' ? '删除' : '请先禁用该应用,再删除',
+                }}
+                disabled={record.state !== 'disabled'}
+                popConfirm={{
+                  title: '确认删除',
+                  disabled: record.state !== 'disabled',
+                  onConfirm: async () => {
+                    // const resp: any = await service.remove(record.id);
+                    // if (resp.status === 200) {
+                    //     onlyMessage(
+                    //         intl.formatMessage({
+                    //             id: 'pages.data.option.success',
+                    //             defaultMessage: '操作成功!',
+                    //         }),
+                    //     );
+                    //     actionRef.current?.reload();
+                    // } else {
+                    //     onlyMessage(resp?.message || '操作失败', 'error');
+                    // }
+                  },
+                }}
+                key="delete"
+                type="link"
+              >
+                <DeleteOutlined />
+              </PermissionButton>,
+            ]}
+          />
+        )}
+      />
+    </PageContainer>
+  );
+};
+export default Apply;

+ 16 - 0
src/pages/system/Apply/service.ts

@@ -0,0 +1,16 @@
+import BaseService from '@/utils/BaseService';
+import { request } from 'umi';
+import SystemConst from '@/utils/const';
+
+class Service extends BaseService<ApplyItem> {
+  getAppInfo = (id: string) =>
+    request(`${SystemConst.API_BASE}/application/${id}/info`, {
+      method: 'GET',
+    });
+  getProvidersAll = () =>
+    request(`${SystemConst.API_BASE}/application/providers`, {
+      method: 'GET',
+    });
+}
+
+export default Service;

+ 13 - 0
src/pages/system/Apply/typings.d.ts

@@ -0,0 +1,13 @@
+type ApplyItem = {
+  id: string;
+  name: string;
+  description: string;
+  provider: string;
+  integrationModes: string[];
+  page?: Record<string, unknown>;
+  apiServer?: Record<string, unknown>;
+  sso?: Record<string, unknown>;
+  state: string;
+  creatorId: string;
+  createTime: number;
+};

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

@@ -79,6 +79,13 @@ const extraRouteObj = {
   'system/Menu': {
     children: [{ code: 'Setting', name: '菜单配置' }],
   },
+  'system/Apply': {
+    children: [
+      { code: 'Api', name: '赋权' },
+      { code: 'View', name: 'Api详情' },
+      { code: 'Save', name: '详情' },
+    ],
+  },
 };
 //额外路由
 export const extraRouteArr = [

+ 1 - 0
src/utils/menu/router.ts

@@ -130,6 +130,7 @@ export enum MENUS_CODE {
   'system/Platforms/Api' = 'system/Platforms/Api',
   'system/Platforms/View' = 'system/Platforms/View',
   'system/Platforms/Setting' = 'system/Platforms/Setting',
+  'system/Apply' = 'system/Apply',
 }
 
 export type MENUS_CODE_TYPE = keyof typeof MENUS_CODE | string;