master
LiuJiaNan 2026-03-20 09:48:21 +08:00
commit 7a793bd472
48 changed files with 1673 additions and 0 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
# production
/dist
/demo
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
yarn.lock

47
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,47 @@
{
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
"eslint.rules.customizations": [
{ "rule": "style/*", "severity": "off", "fixable": true },
{ "rule": "format/*", "severity": "off", "fixable": true },
{ "rule": "*-indent", "severity": "off", "fixable": true },
{ "rule": "*-spacing", "severity": "off", "fixable": true },
{ "rule": "*-spaces", "severity": "off", "fixable": true },
{ "rule": "*-order", "severity": "off", "fixable": true },
{ "rule": "*-dangle", "severity": "off", "fixable": true },
{ "rule": "*-newline", "severity": "off", "fixable": true },
{ "rule": "*quotes", "severity": "off", "fixable": true },
{ "rule": "*semi", "severity": "off", "fixable": true }
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"json5",
"jsonc",
"yaml",
"toml",
"xml",
"gql",
"graphql",
"astro",
"svelte",
"css",
"less",
"scss",
"pcss",
"postcss"
]
}

75
README.md Normal file
View File

@ -0,0 +1,75 @@
# 微应用模板说明文档
## 在线文档
https://www.yuque.com/buhangjiecheshen-ymbtb/qc0093/gxdun1dphetcurko
## 安装依赖
项目依赖可通过 **yarn****npm** 进行安装:
```bash
# 使用 yarn
yarn
# 或使用 npm
npm i
```
## 开发服务&打包应用
```bash
# 启动开发服务
yarn serve:<env>
# 或
npm run serve:<env>
# 开发环境打包
yarn build:<env>
# 或
npm run build:<env>
```
## 路由配置&路由访问&自动化路由
所有页面必须放在`src/pages/container`目录下,启动访问页面请在浏览器地址栏输入`/<appIdentifier>/container/<你的路由页面文件名称>`
解释:
1. 所有页面组件命名为`index.js`或`index.jsx`,必须放在一个首字母大写的文件中。
2. `container`为固定路径访问格式
3. `<appIdentifier>`为应用的唯一标识符,也是应用路由的`basename`,在底座中用于区分其他应用。可在根目录 `jjb.config.js` 文件的 `appIdentifier` 节点中进行修改。
4. 自动化路由将根据`pages/container`中的路由页面文件自动生成路由树。
5. `id`匹配路由,文件夹命名`_id`
## 应用接口环境配置
应用接口环境相关配置在根目录 `jjb.config.js` 文件的 `environment` 节点中进行定义。
## 应用开发服务配置
应用开发服务相关配置在根目录 `jjb.config.js` 文件的 `server` 节点中进行定义。
## Babel 配置
应用的 `Babel` 配置在根目录 `jjb.babel.js` 文件中进行管理。
## 目录说明
1. `src/api/` 配置各个 store 模块的接口数据。
2. `src/components/` 全局公共组件。
3. `src/enumerate/` 全局各种枚举配置。
4. `src/pages/` 页面文件目录。
5. `src/main.js` 应用的入口文件。
## 核心依赖
1. `@cqsjjb/jjb-common-decorator`
1. 公共装饰器库,内部包含:
1. 按钮权限处理
2. antd/Table 控制
3. 文本重命名处理
4. 具体使用方式可参考各个模块的 `d.ts`
2. `@cqsjjb/jjb-common-lib`
1. 公共工具库,具体 API 使用请查看 `d.ts`
3. `@cqsjjb/jjb-dva-runtime`
1. 核心运行时,基于 `dvajs` 实现。
1. 应用核心依赖模块
2. 应用的自动化路由
3. `store` 模块接口数据处理
4. 均基于此依赖实现,具体使用方式请查看 `d.ts`
4. `@cqsjjb/jjb-react-admin-component`
1. 公共组件库,具体组件使用方式请查看 `d.ts`

66
blessed_by_buddha.js Normal file
View File

@ -0,0 +1,66 @@
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
. ' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
.............................................
佛祖保佑 永无BUG
佛曰:
写字楼里写字间写字间里程序员
程序人员写程序又拿程序换酒钱
酒醒只在网上坐酒醉还来网下眠
酒醉酒醒日复日网上网下年复年
但愿老死电脑间不愿鞠躬老板前
奔驰宝马贵者趣公交自行程序员
别人笑我忒疯癫我笑自己命太贱
不见满街漂亮妹哪个归得程序员
*/
const blessedByBuddha
= "%c _ooOoo_\n"
+ " o8888888o\n"
+ " 88\" . \"88\n"
+ " (| -_- |)\n"
+ " O\\ = /O\n"
+ " ____/`---'\\____\n"
+ " . ' \\\\| |// `.\n"
+ " / \\\\||| : |||// \\\n"
+ " / _||||| -:- |||||- \\\n"
+ " | | \\\\\\ - /// | |\n"
+ " | \\_| ''\\---/'' | |\n"
+ " \\ .-\\__ `-` ___/-. /\n"
+ " ___`. .' /--.--\\ `. . __\n"
+ " .\"\" '< `.___\\_<|>_/___.' >'\"\".\n"
+ " | | : `- \\`.;`\\ _ /`;.`/ - ` : | |\n"
+ " \\ \\ `-. \\_ __\\ /__ _/ .-` / /\n"
+ " ======`-.____`-.___\\_____/___.-`____.-'======\n"
+ " `=---='\n"
+ "\n"
+ "%c .............................................\n"
+ " 佛祖保佑 永无BUG\n"
+ "\n"
+ "%c 佛曰:\n"
+ " 写字楼里写字间,写字间里程序员;\n"
+ " 程序人员写程序,又拿程序换酒钱。\n"
+ " 酒醒只在网上坐,酒醉还来网下眠;\n"
+ " 酒醉酒醒日复日,网上网下年复年。\n"
+ " 但愿老死电脑间,不愿鞠躬老板前;\n"
+ " 奔驰宝马贵者趣,公交自行程序员。\n"
+ " 别人笑我忒疯癫,我笑自己命太贱;\n"
+ " 不见满街漂亮妹,哪个归得程序员?";
console.log(blessedByBuddha, "color:#ffd700", "color:red", "color:#1e80ff");

49
eslint.config.js Normal file
View File

@ -0,0 +1,49 @@
import antfu from "@antfu/eslint-config";
export default antfu({
formatters: {
html: false,
css: true,
},
test: false,
typescript: true,
react: true,
vue: false,
markdown: false,
stylistic: {
semi: true,
quotes: "double",
},
overrides: {
react: {
"react/no-comment-textnodes": "off",
"react-hooks-extra/no-unnecessary-use-prefix": "off",
"react-hooks-extra/prefer-use-state-lazy-initialization": "off",
"react-hooks/exhaustive-deps": "off",
"react/no-implicit-key": "off",
},
javascript: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "warn",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "warn",
"no-alert": process.env.NODE_ENV === "production" ? "error" : "warn",
"no-restricted-syntax": [
"error",
{
selector: "VariableDeclarator[id.name='pd']",
message: "不允许使用 pd请改用有语义化的变量名",
},
{
selector: "ObjectExpression > Property[key.name='pd']",
message: "不允许使用 pd请改用有语义化的变量名",
},
],
"no-unused-vars": ["error", { varsIgnorePattern: "^React$" }],
},
},
rules: {
"antfu/top-level-function": "off",
"node/prefer-global/process": "off",
"dot-notation": "off",
"linebreak-style": ["off", "windows"],
},
});

23
jjb.babel.js Normal file
View File

@ -0,0 +1,23 @@
module.exports = {
compact: false,
// 插件
plugins: [
[
"@babel/plugin-proposal-decorators",
{
legacy: true,
},
],
],
// 预设
presets: [
["@babel/preset-env", {
targets: {
browsers: ["ie >= 10"],
},
}],
["@babel/preset-react", {
runtime: "automatic",
}],
],
};

77
jjb.config.js Normal file
View File

@ -0,0 +1,77 @@
module.exports = {
// 应用后端git地址部署上线需要
javaGit: "<git-url>",
// 应用后端仓库名称,部署上线需要
javaGitName: "<git-name>",
// 环境配置
environment: {
development: {
// 应用后端分支名称,部署上线需要
javaGitBranch: "<branch-name>",
// 接口服务地址
API_HOST: "https://gbs-gateway.qhdsafety.com",
// API_HOST: "http://192.168.20.100:30140",
},
production: {
// 应用后端分支名称,部署上线需要
javaGitBranch: "<branch-name>",
// 接口服务地址
API_HOST: "",
},
},
// 应用唯一标识符
appIdentifier: "eightwork",
// 应用上下文注入全局变量
contextInject: {
// 应用Key
appKey: "",
// fileUrl: "http://192.168.20.240:9787/mnt/",
fileUrl: "https://jpfz.qhdsafety.com/gbsFileTest/",
},
// public/index.html注入全局变量
windowInject: {
// 应用标题
title: "微应用模板",
// 注入css链接集合
links: [],
element: {
root: {
// 挂载DOM元素ID
id: "root",
},
},
// 注入js链接集合
scripts: [],
},
// 开发服务
server: {
// 监听端口号
port: "8063",
// 服务地址
host: "127.0.0.1",
// 是否自动打开浏览器
open: true,
},
// 框架
framework: {
// ant-design
antd: {
// 全局antd-class-name前缀
"ant-prefix": "micro-temp",
// 全局字体
"fontFamily": "PingFangSC-Regular",
// 全局主题色
"colorPrimary": "#1677ff",
// 全局圆角
"borderRadius": 2,
},
},
// webpack
webpackConfig: {
// 单页面插件
htmlWebpackPluginOption: {
// 自动注入编译后的文件到public/index.html中
inject: true,
},
},
};

9
jsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"~/*": ["*"]
}
},
"include": ["src"]
}

50
package.json Normal file
View File

@ -0,0 +1,50 @@
{
"name": "micro-app",
"version": "2.0.0",
"description": "建教帮微应用模板",
"author": "JJB",
"license": "MIT",
"main": "index.js",
"scripts": {
"serve": "node node_modules/@cqsjjb/scripts/webpack.dev.server.js",
"build": "node node_modules/@cqsjjb/scripts/webpack.build.js",
"push": "jjb-cmd push java production",
"clean-cache": "rimraf node_modules/.cache/webpack",
"serve:development": "cross-env NODE_ENV=development npm run serve",
"serve:production": "cross-env NODE_ENV=production npm run serve",
"build:development": "cross-env NODE_ENV=development npm run build",
"build:production": "cross-env NODE_ENV=production npm run build",
"code-optimization": "node node_modules/@cqsjjb/scripts/code-optimization.js",
"lint": "eslint --ext .js,.jsx,.tsx --fix src"
},
"dependencies": {
"@ant-design/icons": "^5.6.1",
"@ant-design/pro-components": "^2.8.10",
"@ant-design/pro-flow": "^1.3.12",
"@cqsjjb/jjb-common-decorator": "latest",
"@cqsjjb/jjb-common-lib": "latest",
"@cqsjjb/jjb-dva-runtime": "latest",
"@cqsjjb/jjb-react-admin-component": "latest",
"@xyflow/react": "^12.10.1",
"ahooks": "^3.9.5",
"antd": "^5.27.6",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-to-print": "^3.3.0",
"zy-react-library": "1.2.6"
},
"devDependencies": {
"@antfu/eslint-config": "^5.4.1",
"@babel/plugin-proposal-decorators": "^7.19.3",
"@cqsjjb/scripts": "2.0.0-alpha-1",
"@eslint-react/eslint-plugin": "^2.2.2",
"cross-env": "^7.0.3",
"eslint": "^9.37.0",
"eslint-plugin-format": "^1.0.2",
"eslint-plugin-react-hooks": "^7.0.0",
"eslint-plugin-react-refresh": "^0.4.23",
"typescript": "^5.9.3"
}
}

54
public/index.html Normal file
View File

@ -0,0 +1,54 @@
<!--BEGIN-->
<!--<% var { env: $env, process: $process, mode: $mode, builtInfo: $builtInfo, links: $links, redirectLogin: $redirectLogin, framework: $framework, scripts: $scripts, element: $element } = htmlWebpackPlugin.options %>-->
<!--<% var { appKey: $appKey, antd: $antd, basename: $basename, API_HOST: $API_HOST } = $process %>-->
<!--<% var { ['ant-prefix']: $antPrefix, fontFamily: $fontFamily, colorPrimary: $colorPrimary, borderRadius: $borderRadius } = $antd %>-->
<!--NED-->
<!DOCTYPE html>
<html lang="zh">
<head data-built-info="<%= $builtInfo %>">
<meta charset="UTF-8"/>
<meta name="renderer" content="webkit"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,viewport-fit=cover">
<% for (const item of $links) { %>
<link type="text/css" rel="stylesheet" href="<%= item %>"></link>
<% } %>
<title>--</title>
<script>
(function () {
const APP_ENV = {
antd: {
'ant-prefix': '<%= $antPrefix %>',
fontFamily: '<%= $fontFamily %>',
colorPrimary: '<%= $colorPrimary %>',
borderRadius: parseInt('<%= $borderRadius %>')
},
appKey: '<%= $appKey %>',
basename: '<%= $basename %>',
API_HOST: '<%= $API_HOST %>'
};
APP_ENV.API_HOST = sessionStorage.API_HOST || APP_ENV.API_HOST || window.location.origin;
window.process = {
env: { app: APP_ENV },
NODE_ENV: '<%= $mode %>'
};
window.__JJB_ENVIRONMENT__ = {
API_HOST: APP_ENV.API_HOST,
redirect: '<%= $redirectLogin %>',
FRAMEWORK: APP_ENV.antd
};
})();
</script>
<!-- SCRIPTS -->
<% for (const item of $scripts) { %>
<script src="<%= item %>" type="text/javascript"></script>
<% } %>
</head>
<body>
<!-- NOSCRIPT -->
<noscript>此网页需要开启JavaScript功能。</noscript>
<!-- MAIN -->
<% const { root } = $element; %>
<div id="<%= root.id %>" style="width: 100%; height: 100%; position: relative;overflow-y: auto"></div>
</body>
</html>

19
router.md Normal file
View File

@ -0,0 +1,19 @@
### 企业端
- 动火作业/作业管理
`/eightwork/container/enterprise/hotWork/homework/list`
- 动火作业/归档管理
`/eightwork/container/enterprise/hotWork/archive/list`
- 动火作业/关闭管理
`/eightwork/container/enterprise/hotWork/forceClose/list`
### 相关方端
- 动火作业/作业管理
`/eightwork/container/stakeholder/hotWork/homework/list`
- 动火作业/归档管理
`/eightwork/container/stakeholder/hotWork/archive/list`
### 监管端
- 动火作业
`/eightwork/container/supervision/hotWork/list`

View File

@ -0,0 +1,18 @@
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
export const eightworkList = declareRequest(
"eightworkLoading",
`Post > @/eightwork/eightworkInfo/list`,
);
export const eightworkInfo = declareRequest(
"eightworkLoading",
`Get > /eightwork/eightworkInfo/{id}`,
);
export const eightworkType = declareRequest(
"eightworkLoading",
`Post > @/eightwork/eightworkTask/listByWorkType`,
);
export const eightworkRecordsList = declareRequest(
"eightworkLoading",
`Post > @/eightwork/eightworkInfo/list`,
);

11
src/api/global/index.js Normal file
View File

@ -0,0 +1,11 @@
export {};
// export const riskList = declareRequest(
// "loading",
// "Post > @/xxx",
// "dataSource: [] | res.data || [] & total: 0 | res.totalCount || 0 & pageIndex: 1 | res.pageIndex || 1 & pageSize: 10 | res.pageSize || 10",
// );
// export const riskDelete = declareRequest(
// "loading",
// "Delete > @/xxx/{id}",
// );

1
src/components/index.js Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,25 @@
/**
* 全局常量定义
*/
export {};
// HOT_WORK("hot_work", "DH","动火作业"),
// BLINDBOARD_WORK("blindboard_work", "MBCD","盲板抽堵作业"),
// BREAKGROUND_WORK("breakground_work", "DT","动土作业"),
// CONFINEDSPACE_WORK("confinedspace_work", "SXKJ","受限空间作业"),
// CUTROAD_WORK("cutroad_work", "DL","短路作业"),
// ELECTRICITY_WORK("electricity_work", "LSYD","临时用电作业"),
// HIGH_WORK("high_work", "GC","高处作业"),
// HOISTING("hoisting_work", "DZ","吊装作业");
export const STATUS_ENUM = [
{ name: "未开始", bianma: "0" },
{ name: "进行中", bianma: "1" },
{ name: "强制归档", bianma: "998" },
{ name: "归档", bianma: "999" },
];
export const WORK_TYPE_ENUM = [
{ name: "相关方", bianma: "1" },
{ name: "内部", bianma: "998" },
];

View File

@ -0,0 +1,8 @@
/**
* 全局上下文定义
*/
import React from "react";
// 获取antd全局静态方法
export const InjectContext = React.createContext({});

View File

@ -0,0 +1,8 @@
/**
* 全局数据状态管理模块定义
*/
import { defineNamespace } from "@cqsjjb/jjb-dva-runtime";
export const NS_GLOBAL = defineNamespace("global");
export const NS_EIGHTWORK = defineNamespace("eightwork");

49
src/main.js Normal file
View File

@ -0,0 +1,49 @@
import { setJJBCommonAntdMessage } from "@cqsjjb/jjb-common-lib";
import { setup } from "@cqsjjb/jjb-dva-runtime";
import { message } from "antd";
import dayjs from "dayjs";
import { getFileUrlFromServer } from "zy-react-library/utils";
import "dayjs/locale/zh-cn";
import "../blessed_by_buddha";
require("antd/dist/reset.css");
require("zy-react-library/css/common.less");
dayjs.locale("zh-cn");
setJJBCommonAntdMessage(message);
const app = setup();
getFileUrlFromServer();
// 非底座环境运行
if (!window.__POWERED_BY_QIANKUN__) {
// 云组件默认依赖
window.__coreLib = {};
window.__coreLib.React = require("react");
window.__coreLib.ReactDOM = require("react-dom");
window.__coreLib.jjbCommonLib = require("@cqsjjb/jjb-common-lib");
}
/**
* @description 挂载
* @param props {{ setGlobalState: ({ rendered: boolean }) => void }}
* @returns {Promise<*>} ''
*/
export const mount = async (props) => {
// 云组件默认依赖
window.__coreLib.React = require("react");
window.__coreLib.ReactDOM = require("react-dom");
window.__coreLib.jjbCommonLib = require("@cqsjjb/jjb-common-lib");
app.mount(props);
};
/**
* @description 卸载
* @param props {object}
* @returns {Promise<*>} ''
*/
export const unmount = async props => app.unmount(props);
/**
* @description 启动
* @param props
*/
export const bootstrap = async props => app.bootstrap(props);

View File

@ -0,0 +1,7 @@
import ListPage from "../../Homework/List";
function List(props) {
return (<ListPage status="999" {...props} />);
}
export default List;

View File

@ -0,0 +1,7 @@
import ViewPage from "../../Homework/View";
function View(props) {
return (<ViewPage {...props} />);
}
export default View;

View File

@ -0,0 +1,5 @@
function Archive(props) {
return props.children;
}
export default Archive;

View File

@ -0,0 +1,7 @@
import ListPage from "../../Homework/List";
function List(props) {
return (<ListPage status="998" {...props} />);
}
export default List;

View File

@ -0,0 +1,7 @@
import ViewPage from "../../Homework/View";
function View(props) {
return (<ViewPage {...props} />);
}
export default View;

View File

@ -0,0 +1,5 @@
function ForceClose(props) {
return props.children;
}
export default ForceClose;

View File

@ -0,0 +1,334 @@
import { FlowView, FlowViewProvider } from "@ant-design/pro-flow";
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { BaseEdge, EdgeLabelRenderer, getBezierPath } from "@xyflow/react";
import { Button, Modal, Space } from "antd";
import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Page from "zy-react-library/components/Page";
import Search from "zy-react-library/components/Search";
import DepartmentSelectTree from "zy-react-library/components/SelectTree/Department/Gwj";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
import useTable from "zy-react-library/hooks/useTable";
import { getLabelName } from "zy-react-library/utils";
import { STATUS_ENUM, WORK_TYPE_ENUM } from "~/enumerate/constant";
import { NS_EIGHTWORK } from "~/enumerate/namespace";
import { getFlowData } from "~/utils/flow";
function List(props) {
// status 默认不传是作业管理999 是归档管理998 是强制关闭管理
// entrance 默认不传是企业端stakeholder 是相关方端supervision 是监督端
const [form] = Search.useForm();
const query = useGetUrlQuery();
const [eightworkType, setEightworkType] = useState([]);
const [forceTerminationModalOpen, setForceTerminationModalOpen] = useState(false);
const [flowModalOpen, setFlowModalOpen] = useState(true);
const [currentId, setCurrentId] = useState("");
const { tableProps, getData } = useTable(props["eightworkList"], {
form,
params: { eqWorkType: "hot_work", corpinfoId: query.corpinfoId },
transform: formData => ({
geCreateTime: formData.createTime?.[0],
leCreateTime: formData.createTime?.[1],
eqStatus: props.status || formData.eqStatus,
}),
});
const getEightworkType = async () => {
const { data } = await props["eightworkType"]({ workType: "hot_work" });
setEightworkType(data);
};
useEffect(() => {
getEightworkType();
}, []);
return (
<Page isShowAllAction={false}>
<Search
options={[
{ name: "eqCheckNo", label: "编号" },
{ name: "likeCreateName", label: "申请人" },
{ name: "createTime", label: "申请时间", render: FORM_ITEM_RENDER_ENUM.DATE_RANGE },
{
name: "eqStatus",
label: "审核状态",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: STATUS_ENUM,
hidden: props.status,
},
{
name: "todo",
label: "动火等级",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: eightworkType,
itemsField: { labelKey: "taskName", valueKey: "workLevel" },
},
{ name: "eqXgfFlag", label: "作业类型", render: FORM_ITEM_RENDER_ENUM.SELECT, items: WORK_TYPE_ENUM },
{ name: "inDepartmentId", label: "申请单位", render: <DepartmentSelectTree multiple /> },
{
name: "todo",
label: "服务单位",
render: <DepartmentSelectTree searchType="inType" params={{ enterpriseType: [1, 2] }} />,
hidden: !(props.entrance === "stakeholder"),
},
]}
form={form}
onFinish={getData}
/>
<Table
columns={[
{ title: "服务单位", dataIndex: "todo", hidden: !(props.entrance === "stakeholder") },
{ title: "编号", dataIndex: "checkNo" },
{
title: "作业类型",
dataIndex: "xgfFlag",
render: (_, record) => getLabelName({ list: WORK_TYPE_ENUM, status: record.xgfFlag }),
},
{ title: "动火等级", dataIndex: "workLevel" },
{ title: "申请人", dataIndex: "createName" },
{ title: "申请单位", dataIndex: "todo" },
{ title: "申请时间", dataIndex: "createTime" },
{ title: "作业人", dataIndex: "todo" },
{ title: "作业单位", dataIndex: "todo" },
{ title: "作业时间", dataIndex: "todo" },
{ title: "作业内容", dataIndex: "todo" },
{
title: "审核状态",
dataIndex: "status",
render: (_, record) => getLabelName({ list: STATUS_ENUM, status: record.status }),
},
{ title: "强制关闭原因", dataIndex: "todo", hidden: !(props.status === "998") },
{
title: "操作",
fixed: "right",
width: 250,
render: (_, record) => (
<Space>
<Button
type="link"
onClick={() => {
setCurrentId(record.id);
setFlowModalOpen(true);
}}
>
流程图
</Button>
<Button
type="link"
onClick={() => {
props.history.push(`./view?id=${record.id}`);
}}
>
审批表详情
</Button>
{(!props.status && !props.entrance) && (
<Button
type="link"
danger
onClick={() => {
setCurrentId(record.id);
setForceTerminationModalOpen(true);
}}
>
强制结束
</Button>
)}
</Space>
),
},
]}
{...tableProps}
dataSource={[{}]}
loading={false}
/>
{
forceTerminationModalOpen && (
<ForceTerminationModal
id={currentId}
onCancel={() => {
setForceTerminationModalOpen(false);
setCurrentId("");
}}
getData={getData}
/>
)
}
{
flowModalOpen && (
<FlowModal
id={currentId}
onCancel={() => {
setFlowModalOpen(false);
setCurrentId("");
}}
/>
)
}
</Page>
);
}
const ForceTerminationModalComponent = (props) => {
const [form] = FormBuilder.useForm();
const onSubmit = async () => {
};
return (
<Modal
open
title="强制关闭"
maskClosable={false}
onCancel={props.onCancel}
onOk={form.submit}
width={600}
confirmLoading={props.eightwork.eightworkLoading}
>
<div>
<div>请确认是否强制关闭作业票</div>
<FormBuilder
style={{ width: "100%", marginTop: "10px" }}
span={24}
labelCol={{ span: 10 }}
options={[
{ name: "todo", label: "强制关闭原因", render: FORM_ITEM_RENDER_ENUM.TEXTAREA },
]}
form={form}
showActionButtons={false}
onFinish={onSubmit}
/>
</div>
</Modal>
);
};
const CustomFlowNode = ({ data }) => {
const { title, backgroundColor, width, height } = data;
return (
<div
style={{
backgroundColor,
width,
height,
color: "#fff",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{title}
</div>
);
};
const CustomFlowEdge = (edge) => {
console.log(111);
const {
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style = {},
markerEnd,
} = edge;
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
});
console.log(edgePath);
console.log(labelX);
console.log(labelY);
return (
<>
<BaseEdge
className={edge.data.className}
path={edgePath}
markerEnd={markerEnd}
style={style}
/>
<EdgeLabelRenderer>
<div
style={{
position: "absolute",
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
fontSize: 12,
// everything inside EdgeLabelRenderer has no pointer events by default
// if you have an interactive element, set pointer-events: all
pointerEvents: "all",
}}
className="nodrag nopan"
>
123123123
</div>
</EdgeLabelRenderer>
</>
);
};
function FlowModalComponent(props) {
const [flowNodes, setFlowNodes] = useState([]);
const [flowEdges, setFlowEdges] = useState([]);
const getData = async () => {
const data = {
flowCOList: [
{ status: 1, flowList: ["申请人提报", "张三", "2024-01-15 09:30"] },
{ status: 2, flowList: ["部门审批", "李四"], type: 1, thisFlow: 1 },
{ status: 2, flowList: ["安全部门审批", "王五"] },
{ status: 2, flowList: ["审批通过", "系统"] },
],
thisFlow: 1,
};
const { nodes, edges } = getFlowData(data.flowCOList, data.thisFlow);
setFlowNodes(nodes);
setFlowEdges(edges);
};
useEffect(() => {
getData();
}, []);
return (
<Modal
title="查看流程图"
width={1000}
open
maskClosable={false}
onCancel={props.onCancel}
footer={[
<Button key="cancel" onClick={props.onCancel}>取消</Button>,
]}
>
<div style={{ width: "100%", height: 500 }}>
<FlowViewProvider>
<FlowView
nodes={flowNodes}
edges={flowEdges}
miniMap={false}
nodeTypes={{ customNode: CustomFlowNode }}
// edgeTypes={{ buttonEdge: CustomFlowEdge }}
/>
</FlowViewProvider>
</div>
</Modal>
);
}
const ForceTerminationModal = Connect([NS_EIGHTWORK], true)(ForceTerminationModalComponent);
const FlowModal = Connect([NS_EIGHTWORK], true)(FlowModalComponent);
export default Connect([NS_EIGHTWORK], true)(List);

View File

@ -0,0 +1,264 @@
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { Button, Divider, Image } from "antd";
import { useEffect, useRef, useState } from "react";
import { useReactToPrint } from "react-to-print";
import Page from "zy-react-library/components/Page";
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
import { NS_EIGHTWORK } from "~/enumerate/namespace";
import "./index.less";
function View(props) {
const query = useGetUrlQuery();
const contentRef = useRef(null);
const handlePrint = useReactToPrint({
contentRef,
pageStyle: `@page {
size: landscape;
margin: 0mm;
}
@media print {
body {
margin: 10px;
padding: 10px;
}
}
`,
documentTitle: "",
});
const [info, setInfo] = useState({});
const [safetyMeasures, setSafetyMeasures] = useState([
{ content: "动火操作人(焊工)、参与人(电工)及其他特种作业人员须持有效证书方可作业;动火相关设备、必须符合国家、行业标准;", status: "1" },
{ content: "在动火部位配备2具以上适合现场灭火的相应介质合格灭火器 及(1)桶水", status: "1" },
{ content: "动火前须设置警戒线,清理现场易燃物,对无法清理的要用水浇湿或进行有效隔离,对于有油污等易燃物或狭窄危险部位须铺垫方防火石棉布;", status: "1" },
{ content: "动火前,现场管辖单位人员须检查确认动火安全措施落实到位;", status: "1" },
{ content: "动火中,现场人员须严格遵守消防相关规章制度和操作规程;", status: "1" },
{ content: "动火中,监火人不得离开动火现场;", status: "1" },
{ content: "动火中,发现事故隐患须立即停止动火,待事故隐患排除后方可继续动火;", status: "0" },
{ content: "动火结束,现场管辖单位人员与动火现场负责人共同对动火现场检查,确认现场清理完毕,无遗留火种,有延时监火要求的,现场管辖单位指定人员延时监火。", status: "1" },
]);
const [otherSafetyMeasures, setOtherSafetyMeasures] = useState([
{ content: "监火人不得离开动火现场;", preparedBy: "张三" },
{ content: "动火前,现场管辖单位人员须检查确认动火安全措施落实到位;", preparedBy: "张三" },
{ content: "动火中,现场人员须严格遵守消防相关规章制度和操作规程;", preparedBy: "张三" },
]);
const [delayedFireMonitoringRecord, setDelayedFireMonitoringRecord] = useState([
{ time: "2023-04-01 10:00:00", monitor: "张三", signature: "https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" },
{ time: "2023-04-01 10:00:00", monitor: "张三", signature: "https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" },
{ time: "2023-04-01 10:00:00", monitor: "张三", signature: "https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" },
{ time: "2023-04-01 10:00:00", monitor: "张三", signature: "https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" },
]);
const getData = async () => {
const { data } = await props["eightworkInfo"]({ id: query.id });
setInfo(data);
};
useEffect(() => {
getData();
}, []);
return (
<Page
headerTitle="审批表详情"
contentPadding="0 20px 20px 20px"
extraActionButtons={(
<Button type="primary" onClick={handlePrint}>打印</Button>
)}
>
<div className="work_ticket_details" ref={contentRef}>
<table>
<thead>
<tr>
<td colSpan={4} style={{ border: "none" }}>
<Divider orientation="left">动火申请审批许可证</Divider>
</td>
</tr>
<tr>
<td colSpan={4} style={{ border: "none" }}>
<span>编号</span>
<span>{info.xx}</span>
</td>
</tr>
</thead>
<tbody>
{props.entrance === "stakeholder" && (
<tr>
<td className="title">服务单位</td>
<td colSpan={3}>{info.xx}</td>
</tr>
)}
<tr>
<td className="title">申请单位</td>
<td>{info.xx}</td>
<td className="title">申请时间</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title">动火部位</td>
<td>{info.xx}</td>
<td className="title">动火方法</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title">动火等级</td>
<td>{info.xx}</td>
<td className="title">作业内容</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title">动火时间</td>
<td colSpan={3}>{info.xx}</td>
</tr>
<tr>
<td className="title">现场管辖人</td>
<td>{info.xx}</td>
<td className="title">动火操作人</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title">动火监火人</td>
<td colSpan={3}>{info.xx}</td>
</tr>
<tr>
<td className="title center" colSpan={4}>可燃气体分析运行的生产装置罐区和具有火灾爆炸危险场所</td>
</tr>
<tr>
<td className="title">分析时间</td>
<td>{info.xx}</td>
<td className="title">分析点</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title">可燃气体检测结果</td>
<td>{info.xx}</td>
<td className="title">分析人</td>
<td>{info.xx}</td>
</tr>
<tr>
<td className="title center" colSpan={4}>动火要求安全措施安全提示</td>
</tr>
<tr>
<td colSpan={4} style={{ border: "none", padding: 0 }}>
<table>
<tbody>
<tr>
<td className="center" width={80}>序号</td>
<td className="center">安全措施</td>
<td className="center" width={100}>是否涉及</td>
<td className="center" width={100}>确认人</td>
</tr>
{safetyMeasures.map((item, index) => (
<tr key={index}>
<td className="center">{index + 1}</td>
<td>{item.content}</td>
<td className="center">{item.status === "1" ? "是" : "否"}</td>
<td className="center">
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</td>
</tr>
))}
<tr>
<td className="center">{safetyMeasures.length + 1}</td>
<td colSpan={3}>
{
otherSafetyMeasures.map((item, index) => (
<div key={index} style={{ display: "flex", justifyContent: "space-between" }}>
<div>
<span>其他安全措施</span>
<span>{item.content}</span>
</div>
<div>
<span>编制人</span>
<span>{item.preparedBy}</span>
</div>
</div>
))
}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td className="title">动火单位(部门)负责人意见</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
<td className="title">项目发包单位(部门)人员意见</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
</tr>
<tr>
<td className="title">现场管辖单位(部门)负责人意见</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
<td className="title">动火许可证签发单位意见</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
</tr>
<tr>
<td className="title">动火前管辖单位现场人员许可</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
<td className="title">动火后管辖单位现场人员验收</td>
<td className="right">
<div>
<Image src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" width={50} height={50} />
</div>
<div>{info.xx}</div>
</td>
</tr>
<tr>
<td className="title center" colSpan={4}>延时监火记录</td>
</tr>
<tr>
<td colSpan={4} style={{ border: "none", padding: 0 }}>
<table>
<tbody>
<tr>
<td className="title center">监火人</td>
<td className="title center">时间</td>
<td className="title center">签字照片</td>
</tr>
{delayedFireMonitoringRecord.map((item, index) => (
<tr key={index}>
<td className="center">{item.monitor}</td>
<td className="center">{item.time}</td>
<td className="center">
<Image src={item.signature} width={50} height={50} />
</td>
</tr>
))}
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</Page>
);
}
export default Connect([NS_EIGHTWORK], true)(View);

View File

@ -0,0 +1,27 @@
.work_ticket_details {
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
th, td {
border: 1px solid #ddd;
padding: 8px;
&.title{
font-weight: 600;
color: #333;
background-color: #f2f2f2;
width: 200px;
}
&.center {
text-align: center;
}
&.right {
text-align: right;
}
}
}
}

View File

@ -0,0 +1,5 @@
function Homework(props) {
return props.children;
}
export default Homework;

View File

@ -0,0 +1,5 @@
function HotWork(props) {
return props.children;
}
export default HotWork;

View File

@ -0,0 +1,5 @@
function Enterprise(props) {
return props.children;
}
export default Enterprise;

View File

@ -0,0 +1,31 @@
import { ImportCore } from "@cqsjjb/jjb-common-decorator/module";
import React from "react";
export default class Entry extends React.Component {
state = {
Component: undefined,
};
componentDidMount() {
if (process.env.app.appKey) {
ImportCore({
name: "$",
from: "https://cdn.cqjjb.cn/jcloud/use/plugin/b31c9840a57f11ef91cf7f3cabbb7484/latest",
}).then((res) => {
if (res.status) {
this.setState({ Component: res.module?.default });
}
});
}
}
render() {
const { Component } = this.state;
return (Component && process.env.app.appKey) && (
<Component
detail={{ componentKey: process.env.app.appKey }}
appKey={process.env.app.appKey}
/>
);
}
}

View File

@ -0,0 +1,7 @@
import ListPage from "~/pages/Container/Enterprise/HotWork/Homework/List";
function List(props) {
return (<ListPage status="999" entrance="stakeholder" {...props} />);
}
export default List;

View File

@ -0,0 +1,7 @@
import ViewPage from "~/pages/Container/Enterprise/HotWork/Homework/View";
function View(props) {
return (<ViewPage entrance="stakeholder" {...props} />);
}
export default View;

View File

@ -0,0 +1,5 @@
function Archive(props) {
return props.children;
}
export default Archive;

View File

@ -0,0 +1,7 @@
import ListPage from "~/pages/Container/Enterprise/HotWork/Homework/List";
function List(props) {
return (<ListPage entrance="stakeholder" {...props} />);
}
export default List;

View File

@ -0,0 +1,7 @@
import ViewPage from "~/pages/Container/Enterprise/HotWork/Homework/View";
function View(props) {
return (<ViewPage entrance="stakeholder" {...props} />);
}
export default View;

View File

@ -0,0 +1,5 @@
function Homework(props) {
return props.children;
}
export default Homework;

View File

@ -0,0 +1,5 @@
function HotWork(props) {
return props.children;
}
export default HotWork;

View File

@ -0,0 +1,5 @@
function Stakeholder(props) {
return props.children;
}
export default Stakeholder;

View File

@ -0,0 +1,92 @@
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { Button } from "antd";
import Page from "zy-react-library/components/Page";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import useTable from "zy-react-library/hooks/useTable";
import { NS_EIGHTWORK } from "~/enumerate/namespace";
function List(props) {
const [form] = Search.useForm();
const { tableProps, getData } = useTable(props["eightworkRecordsList"], {
form,
params: { eqWorkType: "hot_work" },
});
return (
<Page isShowAllAction={false}>
<Search
options={[
{ name: "todo", label: "公司名称" },
]}
form={form}
onFinish={getData}
/>
<Table
columns={[
{ title: "公司名称", dataIndex: "todo" },
{
title: "申请总数",
dataIndex: "todo",
render: (_, record) => (
<Button
type="link"
onClick={() => {
props.history.push(`./recordsList?corpinfoId=${record.id}`);
}}
>
{record.todo || 0}
</Button>
),
},
{
title: "完成数",
dataIndex: "todo",
render: (_, record) => (
<Button
type="link"
onClick={() => {
props.history.push(`./recordsList?corpinfoId=${record.id}&status=999`);
}}
>
{record.todo || 0}
</Button>
),
},
{
title: "进行数",
dataIndex: "todo",
render: (_, record) => (
<Button
type="link"
onClick={() => {
props.history.push(`./recordsList?corpinfoId=${record.id}&status=1`);
}}
>
{record.todo || 0}
</Button>
),
},
{
title: "废除数",
dataIndex: "todo",
render: (_, record) => (
<Button
type="link"
onClick={() => {
props.history.push(`./recordsList?corpinfoId=${record.id}&status=998`);
}}
>
{record.todo || 0}
</Button>
),
},
]}
{...tableProps}
/>
</Page>
);
}
export default Connect([NS_EIGHTWORK], true)(List);

View File

@ -0,0 +1,10 @@
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
import ListPage from "~/pages/Container/Enterprise/HotWork/Homework/List";
function RecordsList(props) {
const query = useGetUrlQuery();
return (<ListPage status={query.status} entrance="supervision" {...props} />);
}
export default RecordsList;

View File

@ -0,0 +1,5 @@
function HotWork(props) {
return props.children;
}
export default HotWork;

View File

@ -0,0 +1,5 @@
function Supervision(props) {
return props.children;
}
export default Supervision;

View File

@ -0,0 +1,101 @@
import { ImportCore } from "@cqsjjb/jjb-common-decorator/module";
import { theme as antdTheme, App, ConfigProvider } from "antd";
import language from "antd/locale/zh_CN";
import React from "react";
import { InjectContext } from "~/enumerate/context";
export default class Container extends React.Component {
state = window?.base?.themeConfig || {
algorithm: window.process.env.app.antd.algorithm,
borderRadius: window.process.env.app.antd.borderRadius,
colorPrimary: window.process.env.app.antd.colorPrimary,
};
get token() {
const {
colorPrimary,
borderRadius,
} = this.state;
return {
fontFamily: window.process.env.app.antd.fontFamily,
colorPrimary,
borderRadius,
};
}
get algorithm() {
return antdTheme[this.state.algorithm];
}
componentDidMount() {
if (window.__IN_BASE__) {
// eslint-disable-next-line react-web-api/no-leaked-event-listener
window.base.addEventListener("EVENT_THEME_CONTROL", (e) => {
const config = e.data;
this.setState({ [config.field]: config.value });
});
}
}
render() {
return (
<ConfigProvider
theme={{
token: this.token,
algorithm: this.algorithm,
}}
locale={language}
prefixCls={window.process.env.app.antd["ant-prefix"]}
>
<App style={{ height: "100%" }}>
<AppMiddle {...this.props} />
</App>
</ConfigProvider>
);
}
}
function AppMiddle(props) {
return (
<InjectContext.Provider value={App.useApp()}>
{process.env.NODE_ENV === "development"
? props.children
: (
<Interceptor>
{props.children}
</Interceptor>
)}
</InjectContext.Provider>
);
}
class Interceptor extends React.Component {
state = {
Component: undefined,
};
componentDidMount() {
if (process.env.app.appKey) {
ImportCore({
name: "$",
from: "https://cdn.cqjjb.cn/jcloud/use/plugin/b31c9840a57f11ef91cf7f3cabbb7484/latest",
}).then(async (res) => {
if (res.status) {
this.setState({ Component: res.module?.PageCover });
}
});
}
}
render() {
const { Component } = this.state;
return (Component && process.env.app.appKey && process.env.NODE_ENV === "development")
? (
<Component appKey={process.env.app.appKey}>
{this.props.children}
</Component>
)
: this.props.children;
}
}

8
src/pages/index.js Normal file
View File

@ -0,0 +1,8 @@
export default function () {
return (
<h1>
底座微应用模板技术文档
<a rel="noreferrer noopener" target="_blank" href="https://www.yuque.com/buhangjiecheshen-ymbtb/qc0093/gxdun1dphetcurko">https://www.yuque.com/buhangjiecheshen-ymbtb/qc0093/gxdun1dphetcurko</a>
</h1>
);
}

63
src/utils/flow.js Normal file
View File

@ -0,0 +1,63 @@
// 根据状态获取颜色
export const getStatusColor = (status, type, thisFlow) => {
// 进行中节点(当前待审批节点)显示红色
if (thisFlow && type === thisFlow) {
return "#ff4d4f"; // 红色(进行中)
}
// 已完成节点显示绿色
if (status === 1) {
return "#52c41a"; // 绿色(已完成)
}
// 未进行节点显示灰色
return "#9c9c9c"; // 灰色(未进行)
};
// 获取节点标签
export const getNodeLabel = (flowItem) => {
return (
<div style={{ padding: "10px", textAlign: "center" }}>
<div style={{ fontSize: "16px" }}>{flowItem.flowList[0]}</div>
{flowItem.flowList.slice(1).map((item, index) => (
<div key={index} style={{ fontSize: "16px", marginTop: "5px" }}>{item}</div>
))}
</div>
);
};
export const getFlowData = (list, thisFlow) => {
const nodes = [];
const edges = [];
const nodeWidth = 300;
const nodeHeight = 200;
list.forEach((flowItem, index) => {
nodes.push({
id: `node-${index}`,
type: "customNode",
width: nodeWidth,
height: nodeHeight,
data: {
backgroundColor: getStatusColor(flowItem.status, flowItem.type, thisFlow),
title: getNodeLabel(flowItem),
width: nodeWidth,
height: nodeHeight,
},
});
});
// 创建连接线
for (let i = 0; i < list.length - 1; i++) {
edges.push({
id: `edge-${i}`,
source: `node-${i}`,
target: `node-${i + 1}`,
type: "smoothstep",
animated: true,
});
}
return { nodes, edges };
};

16
webstorm.config.js Normal file
View File

@ -0,0 +1,16 @@
"use strict";
const path = require("node:path");
function resolve(dir) {
return path.join(__dirname, ".", dir);
}
module.exports = {
context: path.resolve(__dirname, "./"),
resolve: {
extensions: [".js"],
alias: {
"~": resolve("src/"),
},
},
};