Explorar o código

fix: 修改通知模板

100011797 %!s(int64=3) %!d(string=hai) anos
pai
achega
f4e3621598

+ 8 - 9
src/app.tsx

@@ -15,7 +15,6 @@ import SystemConst from '@/utils/const';
 import { service as MenuService } from '@/pages/system/Menu';
 import getRoutes, {
   extraRouteArr,
-  getMenuPathByCode,
   getMenus,
   handleRoutes,
   saveMenusCache,
@@ -315,20 +314,20 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
       // content: initialState?.currentUser?.name,
     },
     itemRender: (route, _, routes) => {
-      const isToParentUrl = getMenuPathByCode('notice');
+      // const isToParentUrl = getMenuPathByCode('notice');
       const chilck = routes.indexOf(route) !== 0;
-      const goto = routes.some((item) => {
+      const goto = routes.some(() => {
         if (!route.path.includes('iot')) {
           return routes.indexOf(route) <= 1;
         } else {
-          if (route.path.includes('notice')) {
-            return item.path.indexOf(isToParentUrl) > -1;
-          } else {
-            return routes.indexOf(route) > 1;
-          }
+          // if (route.path.includes('notice')) {
+          //   return item.path.indexOf(isToParentUrl) > -1;
+          // } else {
+          return routes.indexOf(route) > 1;
+          // }
         }
       });
-      return chilck && goto && route.path !== '/iot/link/Channel' ? (
+      return chilck && goto ? (
         <Link to={route.path}>{route.breadcrumbName}</Link>
       ) : (
         <span>{route.breadcrumbName}</span>

+ 20 - 10
src/components/ProTableCard/CardItems/Scene/index.less

@@ -20,9 +20,12 @@
       transform: skewX(45deg);
     }
   }
+  // 卡片样式
   .card-item-content-box {
+    // 触发条件
     .card-item-content-trigger {
       display: flex;
+      overflow: hidden;
       .card-item-content-trigger-item {
         width: max-content;
         color: rgba(0, 0, 0, 0.85);
@@ -38,6 +41,7 @@
         font-size: 15px;
       }
     }
+    // 执行动作
     .card-item-content-action-item {
       display: flex;
       margin-top: 5px;
@@ -48,22 +52,20 @@
         font-weight: bold;
         font-size: 18px;
       }
+      // 执行动作
       .card-item-content-action-item-right {
-        width: calc(100% - 48px);
         padding: 5px 16px;
         border: 1px solid rgba(0, 0, 0, 0.08);
         .card-item-content-action-item-right-item {
           display: flex;
           width: 100%;
-          .trigger-contents {
-            color: rgba(0, 0, 0, 0.85);
-            font-weight: bold;
-          }
+          overflow: hidden;
+          // 触发条件 当。。。。。
           .right-item-left {
             display: flex;
             flex-direction: column;
             justify-content: center;
-            width: 15%;
+            width: max-content;
             .trigger-conditions {
               color: #fab247;
             }
@@ -71,12 +73,13 @@
               color: rgba(0, 0, 0, 0.55);
             }
           }
+          // 执行动作
           .right-item-right {
-            width: 85%;
+            width: max-content;
             .right-item-right-item {
               display: flex;
-              width: 100%;
-              overflow: hidden;
+              //overflow: hidden;
+              // 执行方式
               .trigger-ways {
                 width: 70px;
                 margin-right: 18px;
@@ -84,17 +87,22 @@
                 font-size: 16px;
                 white-space: nowrap;
               }
+              // 执行动作
               .right-item-right-item-contents {
                 display: flex;
                 align-items: center;
+                width: max-content;
                 min-width: calc(100% - 88px);
                 max-width: 100%;
+                // 执行动作内容
                 .right-item-right-item-contents-text {
                   display: flex;
+                  width: 100%;
+                  // 每个执行动作
                   .right-item-right-item-contents-item {
                     display: flex;
+                    flex-grow: 1;
                     align-items: center;
-                    width: max-content;
                     overflow: hidden;
                     white-space: nowrap;
                     text-overflow: ellipsis;
@@ -102,6 +110,7 @@
                       color: rgba(0, 0, 0, 0.85);
                       font-weight: bold;
                     }
+                    // 过滤条件
                     .right-item-right-item-contents-item-filter {
                       color: rgba(0, 0, 0, 0.65);
                     }
@@ -114,6 +123,7 @@
                     }
                   }
                 }
+                // 等***个执行动作
                 .right-item-right-item-contents-extra {
                   min-width: 100px;
                   color: #fab247;

+ 481 - 217
src/components/ProTableCard/CardItems/Scene/index.tsx

@@ -7,10 +7,11 @@ import styles from './index.less';
 import type { SceneItem } from '@/pages/rule-engine/Scene/typings';
 import { CheckOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
 import classNames from 'classnames';
-import { ActionsType, BranchesThen } from '@/pages/rule-engine/Scene/typings';
+import { ActionsType, BranchesThen, Executor } from '@/pages/rule-engine/Scene/typings';
 import MyTooltip from './MyTooltip';
 import { handleOptionsLabel } from '@/pages/rule-engine/Scene/Save/terms/paramsItem';
 import { isArray } from 'lodash';
+import TriggerAlarm from '@/pages/rule-engine/Scene/Save/action/TriggerAlarm';
 
 const imageMap = new Map();
 imageMap.set('timer', require('/public/images/scene/scene-timer.png'));
@@ -51,29 +52,99 @@ const notifyRender = (data: ActionsType | undefined) => {
   switch (data?.notify?.notifyType) {
     case 'dingTalk':
       if (data?.options?.provider === 'dingTalkRobotWebHook') {
-        return `通过群机器人消息发送${data?.options?.templateName || data?.notify?.templateId}`;
+        return (
+          <span>通过群机器人消息发送{data?.options?.templateName || data?.notify?.templateId}</span>
+        );
       }
-      return `通过钉钉向${data?.options?.notifierName || data?.notify?.notifierId}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过钉钉向{data?.options?.notifierName || data?.notify?.notifierId}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'weixin':
-      return `通过微信向${data?.options?.sendTo || ''}${data?.options?.orgName || ''}${
-        data?.options?.tagName || ''
-      }发送${data?.options?.templateName || data?.notify?.templateId}`;
+      return (
+        <span>
+          通过微信向{data?.options?.sendTo || ''}
+          {data?.options?.orgName || ''}
+          {data?.options?.tagName || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'email':
-      return `通过邮件向${data?.options?.sendTo || ''}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过邮件向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'voice':
-      return `通过语音向${data?.options?.sendTo || ''}发送 ${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过语音向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'sms':
-      return `通过短信向${data?.options?.sendTo || ''}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过短信向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'webhook':
-      return `通过webhook发送${data?.options?.templateName || data?.notify?.templateId}`;
+      return <span>通过webhook发送{data?.options?.templateName || data?.notify?.templateId}</span>;
+    default:
+      return null;
+  }
+};
+
+const notifyTextRender = (data: ActionsType | undefined) => {
+  switch (data?.notify?.notifyType) {
+    case 'dingTalk':
+      if (data?.options?.provider === 'dingTalkRobotWebHook') {
+        return (
+          <span>通过群机器人消息发送{data?.options?.templateName || data?.notify?.templateId}</span>
+        );
+      }
+      return (
+        <span>
+          通过钉钉向{data?.options?.notifierName || data?.notify?.notifierId}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'weixin':
+      return (
+        <span>
+          通过微信向{data?.options?.sendTo || ''}
+          {data?.options?.orgName || ''}
+          {data?.options?.tagName || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'email':
+      return (
+        <span>
+          通过邮件向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'voice':
+      return (
+        <span>
+          通过语音向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'sms':
+      return (
+        <span>
+          通过短信向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'webhook':
+      return <span>通过webhook发送{data?.options?.templateName || data?.notify?.templateId}</span>;
     default:
       return null;
   }
@@ -82,30 +153,107 @@ const notifyRender = (data: ActionsType | undefined) => {
 const deviceRender = (data: ActionsType | undefined) => {
   switch (data?.device?.selector) {
     case 'fixed':
-      return `${data?.options?.type}${data?.options?.name}${data?.options?.properties}`;
+      return (
+        <span>
+          {data?.options?.type}
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.name}
+          </a>
+          {data?.options?.properties}
+        </span>
+      );
+    case 'tag':
+      let tags: string = '';
+      data.options?.taglist?.map((item: any) => {
+        tags += item.type || '' + item.name || '' + item.value || '';
+      });
+      return (
+        <span>
+          {data?.options?.type}
+          {tags}
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.productName}
+          </a>
+          {data?.options?.properties}
+        </span>
+      );
+    case 'relation':
+      return (
+        <span>
+          {data?.options?.type}与
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.triggerName}
+          </a>
+          具有相同{data?.options?.relationName}的
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.productName}
+          </a>
+          设备的{data?.options?.properties}
+        </span>
+      );
+    default:
+      return null;
+  }
+};
+const deviceTextRender = (data: ActionsType | undefined) => {
+  switch (data?.device?.selector) {
+    case 'fixed':
+      return (
+        <span>
+          {data?.options?.type}
+          {data?.options?.name}
+          {data?.options?.properties}
+        </span>
+      );
     case 'tag':
       let tags: string = '';
       data.options?.taglist?.map((item: any) => {
         tags += item.type || '' + item.name || '' + item.value || '';
       });
-      return `${
-        data?.options?.type + tags + data?.options?.productName + data?.options?.properties
-      }`;
+      return (
+        <span>
+          {data?.options?.type}
+          {tags}
+          {data?.options?.productName}
+          {data?.options?.properties}
+        </span>
+      );
     case 'relation':
-      return `${data?.options?.type}与${data?.options?.triggerName}具有相同${data?.options?.relationName}的${data?.options?.productName}设备的${data?.options?.properties}`;
+      return (
+        <span>
+          {data?.options?.type}与{data?.options?.triggerName}具有相同{data?.options?.relationName}的
+          {data?.options?.productName}设备的{data?.options?.properties}
+        </span>
+      );
     default:
       return null;
   }
 };
 
-const actionRender = (action: ActionsType) => {
+const actionTextRender = (action: ActionsType) => {
   switch (action?.executor) {
     case 'notify':
-      return notifyRender(action);
+      return notifyTextRender(action);
     case 'delay':
       return `${action?.delay?.time}${UnitEnum[action?.delay?.unit || '']}后执行后续动作`;
     case 'device':
-      return deviceRender(action);
+      return deviceTextRender(action);
     case 'alarm':
       if (action?.alarm?.mode === 'relieve') {
         return '满足条件后将解除关联此场景的告警';
@@ -115,6 +263,58 @@ const actionRender = (action: ActionsType) => {
       return null;
   }
 };
+
+interface ActionComponentProps {
+  action: ActionsType;
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+
+const ActionComponentRender = (props: ActionComponentProps) => {
+  const { action, triggerChange } = props;
+  // TODO 执行动作跳转
+  switch (action?.executor) {
+    case 'notify':
+      return notifyRender(action);
+    case 'delay':
+      return (
+        <span>{`${action?.delay?.time}${UnitEnum[action?.delay?.unit || '']}后执行后续动作`}</span>
+      );
+    case 'device':
+      return deviceRender(action);
+    case 'alarm':
+      return (
+        <span>
+          {action?.alarm?.mode === 'relieve' ? (
+            <>
+              满足条件后将解除
+              <a
+                onClick={(e) => {
+                  e.stopPropagation();
+                  triggerChange(action?.executor);
+                }}
+              >
+                关联此场景的告警
+              </a>
+            </>
+          ) : (
+            <>
+              满足条件后将触发
+              <a
+                onClick={(e) => {
+                  e.stopPropagation();
+                  triggerChange(action?.executor);
+                }}
+              >
+                关联此场景的告警
+              </a>
+            </>
+          )}
+        </span>
+      );
+    default:
+      return null;
+  }
+};
 // 过滤器
 const actionFilter = (terms: any, isLast: boolean, index: number) => {
   if (!Array.isArray(terms)) return '';
@@ -162,223 +362,259 @@ const conditionsRender = (when: any[], index: number) => {
   return whenStr;
 };
 
-const branchesActionRender = (actions: any[]) => {
+interface BranchesActionProps {
+  actions: any[];
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+const BranchesActionRender = (props: BranchesActionProps) => {
+  const { actions, triggerChange } = props;
   if (actions && actions?.length) {
     const list = actions.slice(0, 3);
-    return list.map((item, index) => {
-      const isLast = index < actions.length - 1;
-      return (
-        <div
-          className={styles['right-item-right-item-contents-item']}
-          style={{ maxWidth: `(${100 / list.length})%` }}
-        >
-          <MyTooltip placement={'topLeft'} title={actionRender(item)}>
-            <div
-              className={classNames(
-                styles['right-item-right-item-contents-item-action'],
-                styles['item-ellipsis'],
-              )}
-            >
-              {actionRender(item)}
+    return (
+      <div className={classNames(styles['right-item-right-item-contents-text'])}>
+        {list.map((item, index) => {
+          const isLast = index < actions.length - 1;
+          return (
+            <div className={styles['right-item-right-item-contents-item']}>
+              <MyTooltip placement={'topLeft'} title={actionTextRender(item)}>
+                <div
+                  className={classNames(
+                    styles['right-item-right-item-contents-item-action'],
+                    styles['item-ellipsis'],
+                  )}
+                >
+                  <ActionComponentRender action={item} triggerChange={triggerChange} />
+                </div>
+              </MyTooltip>
+              <MyTooltip
+                placement={'topLeft'}
+                title={actionFilter(actions[index]?.options?.terms, isLast, index)}
+              >
+                <div
+                  className={classNames(
+                    styles['right-item-right-item-contents-item-filter'],
+                    styles['item-ellipsis'],
+                  )}
+                >
+                  {actionFilter(actions[index]?.options?.terms, isLast, index)}
+                </div>
+              </MyTooltip>
             </div>
-          </MyTooltip>
-          <MyTooltip
-            placement={'topLeft'}
-            title={actionFilter(actions[index]?.options?.terms, isLast, index)}
+          );
+        })}
+      </div>
+    );
+  } else {
+    return null;
+  }
+};
+
+const TriggerRender = (data: SceneCardProps) => {
+  const trigger = data?.options?.trigger;
+  return (
+    <div className={classNames(styles['card-item-content-trigger'])}>
+      {trigger?.name && (
+        <MyTooltip placement="topLeft" title={trigger?.name || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)', cursor: 'pointer' }}
+            onClick={(e) => {
+              e.stopPropagation();
+              // TODO 触发条件跳转
+              if (data.triggerType === 'device') {
+                if (data.trigger?.device?.selector === 'fixed') {
+                  // 自定义
+                  //selectorValues
+                } else if (data.trigger?.device?.selector === 'org') {
+                  // 组织
+                } else if (data.trigger?.device?.selector === 'all') {
+                  // 产品
+                }
+              }
+            }}
           >
-            <div
-              className={classNames(
-                styles['right-item-right-item-contents-item-filter'],
-                styles['item-ellipsis'],
-              )}
-            >
-              {actionFilter(actions[index]?.options?.terms, isLast, index)}
-            </div>
-          </MyTooltip>
+            {trigger?.name || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.productName && (
+        <MyTooltip placement="topLeft" title={trigger?.productName || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
+          >
+            {trigger?.productName || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.when && (
+        <MyTooltip placement="topLeft" title={trigger?.when || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '30%' }}
+          >
+            {trigger?.when || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.time && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.time || ''}
         </div>
-      );
-    });
-  }
-  return '';
+      )}
+      {trigger?.extraTime && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.extraTime || ''}
+        </div>
+      )}
+      {trigger?.action && (
+        <MyTooltip placement="topLeft" title={trigger?.action || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '20%' }}
+          >
+            {trigger?.action || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.type && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.type || ''}
+        </div>
+      )}
+    </div>
+  );
 };
 
-const ContentRender = (data: SceneCardProps) => {
+export interface ActionRenderProps extends SceneCardProps {
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+const ActionRender = (data: ActionRenderProps) => {
   const [visible, setVisible] = useState<boolean>(false);
   const type = data.triggerType;
 
-  if (!!type && (data.branches || [])?.length) {
-    const trigger = data?.options?.trigger;
-    return (
-      <div className={styles['card-item-content-box']}>
-        <div className={classNames(styles['card-item-content-trigger'])}>
-          {trigger?.name && (
-            <MyTooltip placement="topLeft" title={trigger?.name || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
-              >
-                {trigger?.name || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.productName && (
-            <MyTooltip placement="topLeft" title={trigger?.productName || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
-              >
-                {trigger?.productName || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.when && (
-            <MyTooltip placement="topLeft" title={trigger?.when || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '16%' }}
-              >
-                {trigger?.when || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.time && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.time || ''}
-            </div>
-          )}
-          {trigger?.extraTime && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.extraTime || ''}
-            </div>
-          )}
-          {trigger?.action && (
-            <MyTooltip placement="topLeft" title={trigger?.action || ''}>
+  return (
+    <div className={styles['card-item-content-action']}>
+      {(visible ? data.branches || [] : (data?.branches || []).slice(0, 2)).map(
+        (item: any, index) => {
+          return (
+            <div className={styles['card-item-content-action-item']} key={item?.key || index}>
+              {type === 'device' && (
+                <div className={styles['card-item-content-action-item-left']}>
+                  {index === 0 ? '当' : '否则'}
+                </div>
+              )}
               <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%' }}
+                style={{ width: type === 'device' ? 'calc(100% - 48px)' : '100%' }}
+                className={styles['card-item-content-action-item-right']}
               >
-                {trigger?.action || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.type && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.type || ''}
-            </div>
-          )}
-        </div>
-        <div className={styles['card-item-content-action']}>
-          {(visible ? data.branches || [] : (data?.branches || []).slice(0, 2)).map(
-            (item: any, index) => {
-              return (
-                <div className={styles['card-item-content-action-item']} key={item?.key || index}>
-                  {type === 'device' && (
-                    <div className={styles['card-item-content-action-item-left']}>
-                      {index === 0 ? '当' : '否则'}
+                <div className={styles['card-item-content-action-item-right-item']}>
+                  {/*触发条件*/}
+                  {type === 'device' && (item.shakeLimit?.enabled || data.options?.when?.[index]) && (
+                    <div
+                      className={styles['right-item-left']}
+                      style={{
+                        maxWidth: Array.isArray(item.then) && item?.then.length ? '15%' : '100%',
+                      }}
+                    >
+                      <MyTooltip
+                        placement={'topLeft'}
+                        title={conditionsRender(data.options?.when || [], index)}
+                      >
+                        <div className={classNames(styles['trigger-conditions'], 'ellipsis')}>
+                          {conditionsRender(data.options?.when || [], index)}
+                        </div>
+                      </MyTooltip>
+                      {item.shakeLimit?.enabled && (
+                        <MyTooltip
+                          title={`(${item.shakeLimit?.time}秒内发生${item.shakeLimit?.threshold}
+                            次以上时执行一次)`}
+                        >
+                          <div className={classNames(styles['trigger-shake'], 'ellipsis')}>
+                            ({item.shakeLimit?.time}秒内发生{item.shakeLimit?.threshold}
+                            次以上时执行一次)
+                          </div>
+                        </MyTooltip>
+                      )}
                     </div>
                   )}
-                  <div
-                    style={{ width: type === 'device' ? 'calc(100% - 48px)' : '100%' }}
-                    className={styles['card-item-content-action-item-right']}
-                  >
-                    <div className={styles['card-item-content-action-item-right-item']}>
-                      {type === 'device' &&
-                        (item.shakeLimit?.enabled || data.options?.when?.[index]) && (
-                          <div
-                            className={styles['right-item-left']}
-                            style={{
-                              width: Array.isArray(item.then) && item?.then.length ? '15%' : '100%',
-                            }}
-                          >
-                            <MyTooltip
-                              placement={'topLeft'}
-                              title={conditionsRender(data.options?.when || [], index)}
-                            >
-                              <div className={classNames(styles['trigger-conditions'], 'ellipsis')}>
-                                {conditionsRender(data.options?.when || [], index)}
-                              </div>
-                            </MyTooltip>
-                            {item.shakeLimit?.enabled && (
-                              <MyTooltip
-                                title={`(${item.shakeLimit?.time}秒内发生${item.shakeLimit?.threshold}
-                            次以上时执行一次)`}
-                              >
-                                <div className={classNames(styles['trigger-shake'], 'ellipsis')}>
-                                  ({item.shakeLimit?.time}秒内发生{item.shakeLimit?.threshold}
-                                  次以上时执行一次)
+                  {/*执行动作*/}
+                  {Array.isArray(item.then) && item?.then.length ? (
+                    <div
+                      className={styles['right-item-right']}
+                      style={{ maxWidth: type === 'device' ? '85%' : '100%' }}
+                    >
+                      {(item?.then || []).map((i: BranchesThen, _index: number) => {
+                        if (Array.isArray(i?.actions) && i?.actions.length) {
+                          return (
+                            <div key={i?.key || _index} className={styles['right-item-right-item']}>
+                              {item?.then?.length > 1 && (
+                                <div className={styles['trigger-ways']}>
+                                  {i ? (i.parallel ? '并行执行' : '串行执行') : ''}
                                 </div>
-                              </MyTooltip>
-                            )}
-                          </div>
-                        )}
-                      {Array.isArray(item.then) && item?.then.length ? (
-                        <div
-                          className={styles['right-item-right']}
-                          style={{ width: type === 'device' ? '85%' : '100%' }}
-                        >
-                          {(item?.then || []).map((i: BranchesThen, _index: number) => {
-                            if (Array.isArray(i?.actions) && i?.actions.length) {
-                              return (
+                              )}
+                              {Array.isArray(i?.actions) && (
                                 <div
-                                  key={i?.key || _index}
-                                  className={styles['right-item-right-item']}
+                                  className={classNames(styles['right-item-right-item-contents'])}
                                 >
-                                  {item?.then?.length > 1 && (
-                                    <div className={styles['trigger-ways']}>
-                                      {i ? (i.parallel ? '并行执行' : '串行执行') : ''}
-                                    </div>
-                                  )}
-                                  {Array.isArray(i?.actions) && (
+                                  <div
+                                    className={classNames(
+                                      styles['right-item-right-item-contents-text'],
+                                    )}
+                                  >
+                                    <BranchesActionRender
+                                      actions={i?.actions}
+                                      triggerChange={data.triggerChange}
+                                    />
+                                  </div>
+                                  {i?.actions.length > 3 && (
                                     <div
                                       className={classNames(
-                                        styles['right-item-right-item-contents'],
+                                        styles['right-item-right-item-contents-extra'],
                                       )}
                                     >
-                                      <div
-                                        className={classNames(
-                                          styles['right-item-right-item-contents-text'],
-                                        )}
-                                      >
-                                        {branchesActionRender(i?.actions)}
-                                      </div>
-                                      {i?.actions.length > 3 && (
-                                        <div
-                                          className={classNames(
-                                            styles['right-item-right-item-contents-extra'],
-                                          )}
-                                        >
-                                          等{i?.actions.length}个执行动作
-                                        </div>
-                                      )}
+                                      等{i?.actions.length}个执行动作
                                     </div>
                                   )}
                                 </div>
-                              );
-                            }
-                            return null;
-                          })}
-                        </div>
-                      ) : (
-                        ''
-                      )}
+                              )}
+                            </div>
+                          );
+                        }
+                        return null;
+                      })}
                     </div>
-                  </div>
+                  ) : (
+                    ''
+                  )}
                 </div>
-              );
-            },
-          )}
-          {(data?.branches || []).length > 2 && (
-            <div
-              className={styles['trigger-actions-more']}
-              onClick={(e) => {
-                e.stopPropagation();
-                setVisible(!visible);
-              }}
-            >
-              展开更多{!visible ? <DownOutlined /> : <UpOutlined />}
+              </div>
             </div>
-          )}
+          );
+        },
+      )}
+      {(data?.branches || []).length > 2 && (
+        <div
+          className={styles['trigger-actions-more']}
+          onClick={(e) => {
+            e.stopPropagation();
+            setVisible(!visible);
+          }}
+        >
+          展开更多{!visible ? <DownOutlined /> : <UpOutlined />}
         </div>
+      )}
+    </div>
+  );
+};
+
+const ContentRender = (data: ActionRenderProps) => {
+  const type = data.triggerType;
+  if (!!type && (data.branches || [])?.length) {
+    return (
+      <div className={styles['card-item-content-box']}>
+        <TriggerRender {...data} />
+        <ActionRender {...data} triggerChange={data.triggerChange} />
       </div>
     );
   } else {
@@ -387,6 +623,7 @@ const ContentRender = (data: SceneCardProps) => {
 };
 
 export const ExtraSceneCard = (props: SceneCardProps) => {
+  const [triggerVisible, setTriggerVisible] = useState<boolean>(false);
   return (
     <TableCard
       status={props.state.value}
@@ -422,7 +659,12 @@ export const ExtraSceneCard = (props: SceneCardProps) => {
               />
             </div>
           </div>
-          <ContentRender {...props} />
+          <ContentRender
+            {...props}
+            triggerChange={() => {
+              setTriggerVisible(true);
+            }}
+          />
         </div>
       </div>
       <div className={styles['card-item-trigger-type']}>
@@ -436,11 +678,20 @@ export const ExtraSceneCard = (props: SceneCardProps) => {
           <CheckOutlined />
         </div>
       </div>
+      {triggerVisible && (
+        <TriggerAlarm
+          id={props.id}
+          close={() => {
+            setTriggerVisible(false);
+          }}
+        />
+      )}
     </TableCard>
   );
 };
 
 export default (props: SceneCardProps) => {
+  const [triggerVisible, setTriggerVisible] = useState<boolean>(false);
   return (
     <TableCard
       showMask={false}
@@ -475,7 +726,12 @@ export default (props: SceneCardProps) => {
               />
             </div>
           </div>
-          <ContentRender {...props} />
+          <ContentRender
+            {...props}
+            triggerChange={() => {
+              setTriggerVisible(true);
+            }}
+          />
         </div>
       </div>
       <div className={styles['card-item-trigger-type']}>
@@ -484,6 +740,14 @@ export default (props: SceneCardProps) => {
           {TriggerWayType[props.triggerType]}
         </div>
       </div>
+      {triggerVisible && (
+        <TriggerAlarm
+          id={props.id}
+          close={() => {
+            setTriggerVisible(false);
+          }}
+        />
+      )}
     </TableCard>
   );
 };

+ 6 - 4
src/pages/DataCollect/Collector/components/Point/Save/modbus.tsx

@@ -81,10 +81,12 @@ export default (props: Props) => {
     field.loading = true;
     services(field).then(
       action.bound!((resp: any) => {
-        field.dataSource = (resp?.result || []).map((item: any) => ({
-          label: item.name,
-          value: item.id,
-        }));
+        field.dataSource = (resp?.result || [])
+          .filter((i: any) => i?.id !== 'property')
+          .map((item: any) => ({
+            label: item.name,
+            value: item.id,
+          }));
         field.loading = false;
       }),
     );

+ 6 - 5
src/pages/DataCollect/Collector/components/Point/index.tsx

@@ -236,10 +236,10 @@ const PointCard = observer((props: PointCardProps) => {
         loading={loading}
         bordered={false}
         className={'data-collect-point'}
-        style={{ position: 'relative', minHeight: 600 }}
+        style={{ position: 'relative', overflowY: 'auto' }}
         bodyStyle={{ paddingTop: 4 }}
       >
-        <div>
+        <div style={{ height: 620 }}>
           <div style={{ height: '100%', paddingBottom: 48 }}>
             {props.data?.id !== '*' && props.data?.id && (
               <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}>
@@ -345,10 +345,11 @@ const PointCard = observer((props: PointCardProps) => {
                   style={{
                     display: 'flex',
                     justifyContent: 'flex-end',
-                    position: 'absolute',
+                    // position: 'absolute',
                     width: '100%',
-                    bottom: 10,
-                    right: '2%',
+                    // bottom: 10,
+                    // right: '2%',
+                    marginTop: 20,
                   }}
                 >
                   <Pagination

+ 5 - 0
src/pages/Northbound/AliCloud/Detail/index.tsx

@@ -431,7 +431,12 @@ const Detail = observer(() => {
         document.title = '阿里云';
       }
     }, 0);
+    return () => {
+      Store.set('datalist', []);
+      Store.set('productList', []);
+    };
   }, []);
+
   useEffect(() => {
     if (location && location.state) {
       setView(location.state.view);

+ 258 - 0
src/pages/device/Firmware/Task/Save/SelectDevices.tsx

@@ -0,0 +1,258 @@
+import { Badge, Checkbox, Input, Modal } from 'antd';
+import { EditOutlined } from '@ant-design/icons';
+import type { Key } from 'react';
+import { useEffect, useRef } from 'react';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import ProTable from '@jetlinks/pro-table';
+import type { DeviceInstance } from '@/pages/device/Instance/typings';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import Service from '@/pages/device/Instance/service';
+import { observer } from '@formily/react';
+import { model } from '@formily/reactive';
+import moment from 'moment';
+import SearchComponent from '@/components/SearchComponent';
+
+interface Props {
+  id?: string;
+  value?: Partial<DeviceInstance>[];
+  onChange?: (data: Partial<DeviceInstance>[]) => void;
+  productId?: string;
+  disabled?: boolean;
+}
+
+const deviceStatus = new Map();
+deviceStatus.set('online', <Badge status="success" text={'在线'} />);
+deviceStatus.set('offline', <Badge status="error" text={'离线'} />);
+deviceStatus.set('notActive', <Badge status="processing" text={'禁用'} />);
+
+const service = new Service('device/instance');
+const State = model<{
+  visible: boolean;
+  data: Partial<DeviceInstance>[];
+  dataList: Partial<DeviceInstance>[];
+  searchParam: any;
+}>({
+  visible: false,
+  data: [],
+  dataList: [],
+  searchParam: { terms: [] },
+});
+
+const SelectDevices = observer((props: Props) => {
+  const intl = useIntl();
+  const actionRef1 = useRef<ActionType>();
+  // const [searchParam, setSearchParam] = useState<any>({terms: []});
+  const columns: ProColumns<DeviceInstance>[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      ellipsis: true,
+    },
+    {
+      title: intl.formatMessage({
+        id: 'pages.table.deviceName',
+        defaultMessage: '设备名称',
+      }),
+      dataIndex: 'name',
+      ellipsis: true,
+    },
+    {
+      title: '固件版本',
+      dataIndex: 'firmwareInfo',
+      ellipsis: true,
+      render: (text: any, record: any) => record?.version || '',
+    },
+    {
+      title: intl.formatMessage({
+        id: 'pages.device.instance.registrationTime',
+        defaultMessage: '注册时间',
+      }),
+      dataIndex: 'registryTime',
+      width: '200px',
+      valueType: 'dateTime',
+      render: (text: any, record: any) =>
+        record?.registerTime ? moment(record?.registerTime).format('YYYY-MM-DD HH:mm:ss') : '',
+    },
+    {
+      title: '状态',
+      dataIndex: 'state',
+      render: (text: any, record: any) =>
+        record?.state?.value ? deviceStatus.get(record?.state?.value) : '',
+      ellipsis: true,
+    },
+  ];
+
+  // const [data, setData] = useState<Partial<DeviceInstance>[]>(props?.value || []);
+  // const [dataList, setDataList] = useState<Partial<DeviceInstance>[]>(props?.value || []);
+
+  const rowSelection = {
+    onSelect: (selectedRow: any, selected: any) => {
+      let newSelectKeys = [...State.data];
+      if (selected) {
+        newSelectKeys.push({ ...selectedRow });
+      } else {
+        newSelectKeys = newSelectKeys.filter((item) => item.id !== selectedRow.id);
+      }
+      State.data = newSelectKeys;
+    },
+    onSelectAll: (selected: boolean, _: any, changeRows: any) => {
+      let newSelectKeys = [...State.data];
+      if (selected) {
+        changeRows.forEach((item: any) => {
+          newSelectKeys.push({ ...item });
+        });
+      } else {
+        newSelectKeys = newSelectKeys.filter((a) => {
+          return !changeRows.some((b: any) => b.id === a.id);
+        });
+      }
+      State.data = newSelectKeys;
+    },
+    selectedRowKeys: State.data?.map((item) => item.id) as Key[],
+  };
+
+  const CheckAllData = () => {
+    service
+      .queryDetailListNoPaging({
+        context: {
+          includeTags: false,
+          includeBind: false,
+          includeRelations: false,
+        },
+        ...State.searchParam,
+        terms: [
+          ...(State.searchParam?.terms || []),
+          {
+            terms: [
+              {
+                column: 'productId',
+                value: props?.productId,
+              },
+            ],
+            type: 'and',
+          },
+        ],
+        paging: false,
+        sorts: [{ name: 'createTime', order: 'desc' }],
+      })
+      .then((resp) => {
+        if (resp.status === 200) {
+          State.dataList = resp.result;
+        }
+      });
+  };
+
+  useEffect(() => {
+    State.searchParam = { terms: [] };
+    State.data = props?.value || [];
+    CheckAllData();
+  }, [props?.value]);
+
+  return (
+    <>
+      <Input
+        disabled
+        value={props.value?.map((item) => item.name).join(',')}
+        id={props?.id}
+        addonAfter={
+          <EditOutlined
+            onClick={() => {
+              if (props.disabled) {
+                State.visible = false;
+              } else {
+                State.visible = true;
+              }
+            }}
+          />
+        }
+      />
+      {State.visible && (
+        <Modal
+          maskClosable={false}
+          visible
+          title="选择设备"
+          width="80vw"
+          onCancel={() => {
+            State.visible = false;
+          }}
+          destroyOnClose={true}
+          onOk={() => {
+            State.visible = false;
+            if (props.onChange) {
+              props.onChange(State.data);
+            }
+          }}
+        >
+          <SearchComponent<DeviceInstance>
+            field={columns}
+            enableSave={false}
+            model="simple"
+            onSearch={(data1: any) => {
+              actionRef1.current?.reset?.();
+              State.searchParam = data1;
+              State.data = [];
+              State.dataList = [];
+              CheckAllData();
+            }}
+            target="choose-devices"
+          />
+          <ProTable<DeviceInstance>
+            tableAlertRender={false}
+            rowSelection={{
+              type: 'checkbox',
+              ...rowSelection,
+            }}
+            headerTitle={[
+              <Checkbox
+                indeterminate={State.dataList.length > State.data.length && State.data.length > 0}
+                style={{ marginLeft: 8 }}
+                disabled={!State.dataList.length}
+                checked={State.dataList.length === State.data.length && State.dataList.length > 0}
+                onChange={async (e) => {
+                  if (e.target.checked) {
+                    State.data = State.dataList;
+                  } else {
+                    State.data = [];
+                  }
+                }}
+              >
+                全选
+              </Checkbox>,
+            ]}
+            search={false}
+            columnEmptyText={''}
+            rowKey="id"
+            params={State.searchParam}
+            columns={columns}
+            actionRef={actionRef1}
+            request={async (params) => {
+              return service.queryDetailList({
+                context: {
+                  includeTags: false,
+                  includeBind: false,
+                  includeRelations: false,
+                },
+                ...params,
+                terms: [
+                  ...(params?.terms || []),
+                  {
+                    terms: [
+                      {
+                        column: 'productId',
+                        value: props?.productId,
+                      },
+                    ],
+                    type: 'and',
+                  },
+                ],
+                sorts: [{ name: 'createTime', order: 'desc' }],
+              });
+            }}
+          />
+        </Modal>
+      )}
+    </>
+  );
+});
+
+export default SelectDevices;

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

@@ -1,10 +1,10 @@
 import { Col, Form, Input, InputNumber, message, Modal, Radio, Row, Select } from 'antd';
 import type { FirmwareItem } from '@/pages/device/Firmware/typings';
-import FSelectDevices from '@/components/FSelectDevices';
 import { useEffect, useRef, useState } from 'react';
 import type { DeviceInstance } from '@/pages/device/Instance/typings';
 import { service } from '@/pages/device/Firmware';
 import { onlyMessage } from '@/utils/util';
+import SelectDevices from '@/pages/device/Firmware/Task/Save/SelectDevices';
 
 interface Props {
   ids: { id: string; productId: string };
@@ -249,7 +249,7 @@ const Save = (props: Props) => {
                       },
                     ]}
                   >
-                    <FSelectDevices productId={ids?.productId || ''} disabled={!!data?.id} />
+                    <SelectDevices productId={ids?.productId || ''} disabled={!!data?.id} />
                   </Form.Item>
                 </Col>
               )}

+ 62 - 39
src/pages/device/Firmware/Task/index.tsx

@@ -1,7 +1,7 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import { message, Tooltip } from 'antd';
+import { message } from 'antd';
 import { useRef, useState } from 'react';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import {
@@ -24,44 +24,6 @@ import SearchComponent from '@/components/SearchComponent';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { service } from '@/pages/device/Firmware';
 
-const UpgradeBtn = (props: { data: any; actions: any }) => {
-  const { data, actions } = props;
-  if (data.waiting > 0 && data?.state?.value === 'processing') {
-    return (
-      <a>
-        <Tooltip title={'停止'}>
-          <StopOutlined
-            onClick={async () => {
-              const resp = await service.stopTask(data.id);
-              if (resp.status === 200) {
-                message.success('操作成功!');
-                actions?.reload();
-              }
-            }}
-          />
-        </Tooltip>
-      </a>
-    );
-  } else if (data?.state?.value === 'canceled') {
-    return (
-      <a>
-        <Tooltip title={'继续升级'}>
-          <ControlOutlined
-            onClick={async () => {
-              const resp = await service.startTask(data.id, ['canceled']);
-              if (resp.status === 200) {
-                message.success('操作成功!');
-                actions?.reload();
-              }
-            }}
-          />
-        </Tooltip>
-      </a>
-    );
-  }
-  return null;
-};
-
 export const state = model<{
   current?: FirmwareItem;
   visible: boolean;
@@ -79,6 +41,67 @@ const Task = observer(() => {
   const id = (location as any).query?.id || localStorage.getItem('TaskId');
   const productId = (location as any).query?.productId || localStorage.getItem('TaskProductId');
 
+  const UpgradeBtn = (props: { data: any; actions: any }) => {
+    const { data, actions } = props;
+    if (data.waiting > 0 && data?.state?.value === 'processing') {
+      return (
+        <PermissionButton
+          key={'stop'}
+          type={'link'}
+          style={{ padding: 0 }}
+          isPermission={permission.update}
+          tooltip={{
+            title: '停止',
+          }}
+          onClick={async () => {
+            const resp = await service.stopTask(data.id);
+            if (resp.status === 200) {
+              message.success('操作成功!');
+              actions?.reload();
+            }
+          }}
+        >
+          <StopOutlined />
+        </PermissionButton>
+      );
+    } else if (data?.state?.value === 'canceled') {
+      return (
+        // <a>
+        //   <Tooltip title={'继续升级'}>
+        //     <ControlOutlined
+        //       onClick={async () => {
+        //         const resp = await service.startTask(data.id, ['canceled']);
+        //         if (resp.status === 200) {
+        //           message.success('操作成功!');
+        //           actions?.reload();
+        //         }
+        //       }}
+        //     />
+        //   </Tooltip>
+        // </a>
+        <PermissionButton
+          key={'stop'}
+          type={'link'}
+          style={{ padding: 0 }}
+          isPermission={permission.update}
+          tooltip={{
+            title: '继续升级',
+          }}
+          onClick={async () => {
+            const resp = await service.startTask(data.id, ['canceled']);
+            if (resp.status === 200) {
+              message.success('操作成功!');
+              actions?.reload();
+            }
+          }}
+        >
+          <ControlOutlined />
+        </PermissionButton>
+      );
+    }
+    return null;
+  };
+
   const columns: ProColumns<any>[] = [
     {
       title: '任务名称',

+ 21 - 21
src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx

@@ -74,27 +74,27 @@ const Property = (props: Props) => {
             ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(
               data.valueType?.type || '',
             ) && (
-              <Tooltip placement="top" title="指标">
-                <ClockCircleOutlined
-                  onClick={() => {
-                    setIndicatorVisible(true);
-                  }}
-                />
-              </Tooltip>
-              // <PermissionButton
-              //   key={'metrics'}
-              //   onClick={() => {
-              //     setIndicatorVisible(true);
-              //   }}
-              //   tooltip={{
-              //     placement: "top",
-              //     title: devicePermission.update ? "指标" : '暂无权限,请联系管理员'
-              //   }}
-              //   style={{ padding: 0, border: "none", backgroundColor: 'inherit' }}
-              //   isPermission={devicePermission.update}
-              // >
-              //   <ClockCircleOutlined  />
-              // </PermissionButton>
+              // <Tooltip placement="top" title="指标">
+              //   <ClockCircleOutlined
+              //     onClick={() => {
+              //       setIndicatorVisible(true);
+              //     }}
+              //   />
+              // </Tooltip>
+              <PermissionButton
+                key={'metrics'}
+                onClick={() => {
+                  setIndicatorVisible(true);
+                }}
+                tooltip={{
+                  placement: 'top',
+                  title: devicePermission.update ? '指标' : '暂无权限,请联系管理员',
+                }}
+                style={{ padding: 0, border: 'none', backgroundColor: 'inherit' }}
+                isPermission={devicePermission.update}
+              >
+                <ClockCircleOutlined />
+              </PermissionButton>
             )}
           {data.expands?.type?.includes('read') && (
             <Tooltip placement="top" title="获取最新属性值">

+ 26 - 26
src/pages/device/Instance/Detail/Running/Property/index.tsx

@@ -117,32 +117,32 @@ const Property = (props: Props) => {
             ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(
               record.valueType?.type || '',
             ) && (
-              <Tooltip placement="top" title="指标">
-                <a
-                  onClick={() => {
-                    setIndicatorVisible(true);
-                    setCurrentInfo(record);
-                  }}
-                >
-                  <ClockCircleOutlined />
-                </a>
-              </Tooltip>
-              // <PermissionButton
-              //   type={'link'}
-              //   onClick={() => {
-              //     setVisible(true);
-              //     setCurrentInfo(record);
-              //   }}
-              //   tooltip={{
-              //     placement: "top",
-              //     title: devicePermission.update ? "指标" : '暂无权限,请联系管理员'
-              //   }}
-              //   style={{ padding: 0 }}
-              //   key={'edit'}
-              //   isPermission={devicePermission.update}
-              // >
-              //   <ClockCircleOutlined />
-              // </PermissionButton>
+              // <Tooltip placement="top" title="指标">
+              //   <a
+              //     onClick={() => {
+              //       setIndicatorVisible(true);
+              //       setCurrentInfo(record);
+              //     }}
+              //   >
+              //     <ClockCircleOutlined />
+              //   </a>
+              // </Tooltip>
+              <PermissionButton
+                type={'link'}
+                onClick={() => {
+                  setVisible(true);
+                  setCurrentInfo(record);
+                }}
+                tooltip={{
+                  placement: 'top',
+                  title: devicePermission.update ? '指标' : '暂无权限,请联系管理员',
+                }}
+                style={{ padding: 0 }}
+                key={'edit'}
+                isPermission={devicePermission.update}
+              >
+                <ClockCircleOutlined />
+              </PermissionButton>
             )}
           {record.expands?.type?.includes('read') && (
             <Tooltip placement="top" title="获取最新属性值">

+ 5 - 0
src/pages/device/Instance/service.ts

@@ -375,6 +375,11 @@ class Service extends BaseService<DeviceInstance> {
       method: 'POST',
       data,
     });
+  public queryDetailListNoPaging = (data: any) =>
+    request(`/${SystemConst.API_BASE}/device-instance/detail/_query/no-paging`, {
+      method: 'POST',
+      data,
+    });
   public saveMetadata = (id: string, data: any) =>
     request(`/${SystemConst.API_BASE}/device/instance/${id}/metadata`, {
       method: 'PUT',

+ 12 - 12
src/pages/notice/Config/Detail/index.tsx

@@ -2,7 +2,7 @@ import { PageContainer } from '@ant-design/pro-layout';
 import { createForm, onFieldValueChange, onFormInit } from '@formily/core';
 import { Card, Col, Input, Row } from 'antd';
 import { ISchema } from '@formily/json-schema';
-import { useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { createSchemaField, observer } from '@formily/react';
 import {
   ArrayTable,
@@ -35,7 +35,7 @@ import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
 import FAutoComplete from '@/components/FAutoComplete';
 import Webhook from './doc/Webhook';
-// import { useModel } from '@@/plugin-model/useModel';
+import { useModel } from '@@/plugin-model/useModel';
 import { typeArray } from '@/components/ProTableCard/CardItems/noticeTemplate';
 import RegionIdList from './regionId';
 
@@ -64,7 +64,7 @@ export const docMap = {
 
 const Detail = observer(() => {
   const { id } = useParams<{ id: string }>();
-  // const { initialState } = useModel('@@initialState');
+  const { initialState } = useModel('@@initialState');
   const [typeItem, setTypeItem] = useState<string>('email');
   const [providerItem, setProviderItem] = useState<string>('embedded');
   const [loading, setLoading] = useState<boolean>(false);
@@ -113,15 +113,15 @@ const Detail = observer(() => {
     [],
   );
 
-  // useEffect(() => {
-  //   setTimeout(() => {
-  //     if (initialState?.settings?.title) {
-  //       document.title = `通知配置 - ${initialState?.settings?.title}`;
-  //     } else {
-  //       document.title = '通知配置';
-  //     }
-  //   }, 0);
-  // }, []);
+  useEffect(() => {
+    setTimeout(() => {
+      if (initialState?.settings?.title) {
+        document.title = `通知配置 - ${initialState?.settings?.title}`;
+      } else {
+        document.title = '通知配置';
+      }
+    }, 0);
+  }, []);
 
   const SchemaField = createSchemaField({
     components: {

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

@@ -27,12 +27,11 @@ import {
 import { createSchemaField, observer } from '@formily/react';
 import type { ISchema } from '@formily/json-schema';
 import styles from './index.less';
-import { useMemo, useRef, useState } from 'react';
+import { useEffect, useMemo, useRef, useState } from 'react';
 import FUpload from '@/components/Upload';
 import { useParams } from 'umi';
 import { PageContainer } from '@ant-design/pro-layout';
 import { Card, Col, Row, Tooltip } from 'antd';
-import { typeList } from '@/pages/notice';
 import { configService, service } from '@/pages/notice/Template';
 import FBraftEditor from '@/components/FBraftEditor';
 import { onlyMessage, phoneRegEx, useAsyncDataSource } from '@/utils/util';
@@ -49,9 +48,10 @@ import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
 import FMonacoEditor from '@/components/FMonacoEditor';
 import Webhook from './doc/Webhook';
-// import { useModel } from '@@/plugin-model/useModel';
+import { useModel } from '@@/plugin-model/useModel';
 import { QuestionCircleOutlined } from '@ant-design/icons';
 import { typeArray } from '@/components/ProTableCard/CardItems/noticeTemplate';
+import { typeList } from '../..';
 
 export const docMap = {
   weixin: {
@@ -81,7 +81,7 @@ const Detail = observer(() => {
   const [typeItem, setTypeItem] = useState<string>('email');
   const [providerItem, setProviderItem] = useState<string>('embedded');
   const [loading, setLoading] = useState<boolean>(false);
-  // const { initialState } = useModel('@@initialState');
+  const { initialState } = useModel('@@initialState');
   // 正则提取${}里面的值
   const pattern = /(?<=\$\{).*?(?=\})/g;
 
@@ -474,18 +474,18 @@ const Detail = observer(() => {
     [id],
   );
 
-  // useEffect(() => {
-  //   setTimeout(() => {
-  //     if (initialState?.settings?.title) {
-  //       document.title = `通知模板 - ${initialState?.settings?.title}`;
-  //     } else {
-  //       document.title = '通知模板';
-  //     }
-  //   }, 0);
-  //   // if (state.current) {
-  //   //   form.setValues(state.current);
-  //   // }
-  // }, []);
+  useEffect(() => {
+    setTimeout(() => {
+      if (initialState?.settings?.title) {
+        document.title = `通知模板 - ${initialState?.settings?.title}`;
+      } else {
+        document.title = '通知模板';
+      }
+    }, 0);
+    // if (state.current) {
+    //   form.setValues(state.current);
+    // }
+  }, []);
 
   const SchemaField = createSchemaField({
     components: {
@@ -635,7 +635,7 @@ const Detail = observer(() => {
           dependencies: ['type'],
           fulfill: {
             state: {
-              visible: '{{!!$deps[0] && $deps[0] !== "email" && $deps[0] !== "webhook"}}',
+              hidden: '{{!(!!$deps[0] && $deps[0] !== "email" && $deps[0] !== "webhook")}}',
             },
           },
         },

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

@@ -137,7 +137,7 @@ export default () => {
             key="button"
             icon={<PlusOutlined />}
             type="primary"
-            isPermission={permission.update}
+            isPermission={permission.add}
             onClick={() => {
               setVisible(true);
             }}

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

@@ -548,6 +548,7 @@ export default (props: ItemProps) => {
       )}
       {triggerVisible && (
         <TriggerAlarm
+          id={FormModel.current?.id || ''}
           close={() => {
             setTriggerVisible(false);
           }}

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

@@ -5,10 +5,10 @@ import { Store } from 'jetlinks-store';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { queryDefaultLevel, queryAlarmList, queryAlarmCount } from '../service';
 import encodeQuery from '@/utils/encodeQuery';
-import { FormModel } from '@/pages/rule-engine/Scene/Save';
 
 interface Props {
   close: () => void;
+  id: string;
 }
 
 export default (props: Props) => {
@@ -20,7 +20,7 @@ export default (props: Props) => {
     queryAlarmCount(
       encodeQuery({
         terms: {
-          'id$rule-bind-alarm': FormModel.current.id,
+          'id$rule-bind-alarm': props.id, // FormModel.current.id,
         },
       }),
     ).then((resp) => {
@@ -162,7 +162,7 @@ export default (props: Props) => {
                 terms: [
                   {
                     column: 'id',
-                    value: FormModel.current.id,
+                    value: props.id,
                     termType: 'rule-bind-alarm',
                   },
                 ],

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

@@ -38,7 +38,9 @@ export default forwardRef((props: Props, ref) => {
       const rules: any[] = [];
       rules.push({
         validator: async (_: any, value: any) => {
-          if ((type === 'file' || type === 'link') && !value) {
+          if (type === 'file') {
+            return Promise.resolve();
+          } else if (type === 'link' && !value) {
             return Promise.reject(new Error('请输入' + item.name));
           } else if (type === 'tag' && !value) {
             return Promise.reject(new Error('请选择' + item.name));

+ 1 - 1
src/pages/system/DataSource/Save/index.tsx

@@ -128,7 +128,7 @@ const Save = (props: Props) => {
                       resolve('');
                     } else {
                       const arr = value.split(':');
-                      if ((arr?.[0] === 'jdbc' || arr?.[0] === 'r2dbc') && arr?.[1] === 'mysql') {
+                      if (arr?.[0] === 'jdbc' || arr?.[0] === 'r2dbc') {
                         resolve('');
                       } else {
                         resolve('请输入正确的URL');