Browse Source

Merge pull request #1151 from AprildreamMI/logs

Fix the bug that "Get Log Data Block" can't get the latest logs,
Ahmad Kholid 2 years ago
parent
commit
79f3d12dab

+ 10 - 0
jsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+      "@/*": ["src/*"],
+      "@business": ["business/dev/*"]
+    }
+  },
+  "include": ["src/**/*", "utils/**/*"]
+}

+ 1 - 8
src/components/newtab/logs/LogsHistory.vue

@@ -296,7 +296,7 @@ import Papa from 'papaparse';
 import objectPath from 'object-path';
 import { countDuration, fileSaver } from '@/utils/helper';
 import { getBlocks } from '@/utils/getSharedData';
-import { dataExportTypes } from '@/utils/shared';
+import { dataExportTypes, messageHasReferences } from '@/utils/shared';
 import dayjs from '@/lib/dayjs';
 
 const SharedCodemirror = defineAsyncComponent(() =>
@@ -363,13 +363,6 @@ const tabs = [
   { id: 'referenceData.prevBlockData', name: 'Previous block data' },
   { id: 'replacedValue', name: 'Replaced value' },
 ];
-const messageHasReferences = [
-  'no-tab',
-  'invalid-active-tab',
-  'no-match-tab',
-  'invalid-body',
-  'element-not-found',
-];
 
 const { t, te } = useI18n();
 

+ 9 - 0
src/utils/dataExporter.js

@@ -54,6 +54,15 @@ export default function (
     const extractObj = (obj) => {
       if (typeof obj !== 'object') return [obj];
 
+      // 需要处理深层对象 不然会返回:[object Object]
+      const kes = Object.keys(obj);
+      kes.forEach((key) => {
+        const itemValue = obj[key];
+        if (typeof itemValue === 'object') {
+          obj[key] = JSON.stringify(itemValue);
+        }
+      });
+
       return Object.values(obj);
     };
 

+ 142 - 0
src/utils/getTranslateLog.js

@@ -0,0 +1,142 @@
+import { getBlocks } from '@/utils/getSharedData';
+import dayjs from '@/lib/dayjs';
+import vueI18n from '@/lib/vueI18n';
+import { countDuration } from '@/utils/helper';
+import { messageHasReferences } from '@/utils/shared';
+
+const blocks = getBlocks();
+
+/**
+ * 转换日志
+ * @param {*} log
+ * @returns
+ */
+function translateLog(log) {
+  const copyLog = { ...log };
+  const getTranslatation = (path, def) => {
+    const params = typeof path === 'string' ? { path } : path;
+
+    return vueI18n.global.te(params.path)
+      ? vueI18n.global.t(params.path, params.params)
+      : def;
+  };
+
+  if (['finish', 'stop'].includes(log.type)) {
+    copyLog.name = vueI18n.global.t(`log.types.${log.type}`);
+  } else {
+    copyLog.name = getTranslatation(
+      `workflow.blocks.${log.name}.name`,
+      blocks[log.name].name
+    );
+  }
+
+  if (copyLog.message && messageHasReferences.includes(copyLog.message)) {
+    copyLog.messageId = `${copyLog.message}`;
+  }
+
+  copyLog.message = getTranslatation(
+    { path: `log.messages.${log.message}`, params: log },
+    log.message
+  );
+
+  return copyLog;
+}
+
+function getDataSnapshot(propsCtxData, refData) {
+  if (!propsCtxData?.dataSnapshot) return;
+
+  const data = propsCtxData.dataSnapshot;
+  const getData = (key) => {
+    const currentData = refData[key];
+    if (typeof currentData !== 'string') return currentData;
+
+    return data[currentData] ?? {};
+  };
+
+  refData.loopData = getData('loopData');
+  refData.variables = getData('variables');
+}
+
+/**
+ * 获取日志
+ * @param {*} dataType 日志数据类型
+ * @param {*} translatedLog 转换后的日志
+ * @returns
+ */
+function getLogs(dataType, translatedLog, curStateCtxData) {
+  let data = dataType === 'plain-text' ? '' : [];
+  const getItemData = {
+    'plain-text': ([
+      timestamp,
+      duration,
+      status,
+      name,
+      description,
+      message,
+      ctxData,
+    ]) => {
+      data += `${timestamp}(${countDuration(
+        0,
+        duration || 0
+      ).trim()}) - ${status} - ${name} - ${description} - ${message} - ${JSON.stringify(
+        ctxData
+      )} \n`;
+    },
+    json: ([
+      timestamp,
+      duration,
+      status,
+      name,
+      description,
+      message,
+      ctxData,
+    ]) => {
+      data.push({
+        timestamp,
+        duration: countDuration(0, duration || 0).trim(),
+        status,
+        name,
+        description,
+        message,
+        data: ctxData,
+      });
+    },
+  };
+  translatedLog.forEach((item, index) => {
+    let logData = curStateCtxData;
+    if (logData.ctxData) logData = logData.ctxData;
+
+    const itemData = logData[item.id] || null;
+    if (itemData) getDataSnapshot(curStateCtxData, itemData.referenceData);
+
+    getItemData[dataType](
+      [
+        dayjs(item.timestamp || Date.now()).format('YYYY-MM-DD HH:mm:ss'),
+        item.duration,
+        item.type.toUpperCase(),
+        item.name,
+        item.description || 'NULL',
+        item.message || 'NULL',
+        itemData,
+      ],
+      index
+    );
+  });
+  return data;
+}
+
+/**
+ * 获取日志数据
+ * @param {*} curState 当前工作流状态
+ * @param {*} dataType 日志数据类型 plain-text 和 json
+ * @returns
+ */
+export default function (curState, dataType = 'plain-text') {
+  const { logs: curStateHistory, ctxData: curStateCtxData } = curState;
+  // 经过转换后的日志
+  const translatedLog = curStateHistory.map(translateLog);
+  // 获取日志
+  const logs = getLogs(dataType, translatedLog, curStateCtxData);
+  // 获取日志
+  return logs;
+}

+ 8 - 0
src/utils/shared.js

@@ -1736,3 +1736,11 @@ export const conditionBuilder = {
     },
   },
 };
+
+export const messageHasReferences = [
+  'no-tab',
+  'invalid-active-tab',
+  'no-match-tab',
+  'invalid-body',
+  'element-not-found',
+];

+ 5 - 1
src/workflowEngine/WorkflowEngine.js

@@ -555,7 +555,11 @@ class WorkflowEngine {
       tabIds: [],
       currentBlock: [],
       name: this.workflow.name,
-      logs: this.history.slice(-5),
+      logs: this.history,
+      ctxData: {
+        ctxData: this.historyCtxData,
+        dataSnapshot: this.refDataSnapshots,
+      },
       startedTimestamp: this.startedTimestamp,
     };
 

+ 22 - 17
src/workflowEngine/blocksHandler/handlerLogData.js

@@ -1,32 +1,37 @@
-import dbLogs from '@/db/logs';
+import getTranslateLog from '@/utils/getTranslateLog';
+import { workflowState } from '../index';
 
 export async function logData({ id, data }) {
   if (!data.workflowId) {
     throw new Error('No workflow is selected');
   }
 
-  const [workflowLog] = await dbLogs.items
-    .where('workflowId')
-    .equals(data.workflowId)
-    .reverse()
-    .sortBy('endedAt');
-  let workflowLogData = null;
+  // 工作流状态数组
+  const { states } = workflowState;
+  let logs = [];
+  if (states) {
+    // 转换为数组
+    const stateValues = Object.values(Object.fromEntries(states));
+    // 当前工作流状态
+    const curWorkflowState = stateValues.find(
+      (item) => item.workflowId === data.workflowId
+    )?.state;
 
-  if (workflowLog) {
-    workflowLogData = (
-      await dbLogs.logsData.where('logId').equals(workflowLog.id).first()
-    ).data;
+    if (curWorkflowState) {
+      // 当前工作流最新日志
+      logs = getTranslateLog(curWorkflowState, 'json');
 
-    if (data.assignVariable) {
-      this.setVariable(data.variableName, workflowLogData);
-    }
-    if (data.saveData) {
-      this.addDataToColumn(data.dataColumn, workflowLogData);
+      if (data.assignVariable) {
+        this.setVariable(data.variableName, logs);
+      }
+      if (data.saveData) {
+        this.addDataToColumn(data.dataColumn, logs);
+      }
     }
   }
 
   return {
-    data: workflowLogData,
+    data: logs,
     nextBlockId: this.getBlockConnections(id),
   };
 }