LiuJiaNan 2025-11-03 08:38:38 +08:00
commit c94ab906c0
46 changed files with 4203 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");

48
eslint.config.js Normal file
View File

@ -0,0 +1,48 @@
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",
},
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: "开发环境后端地址",
},
production: {
// 应用后端分支名称,部署上线需要
javaGitBranch: "<branch-name>",
// 接口服务地址
API_HOST: "",
},
},
// 应用唯一标识符
appIdentifier: "basic_info",
// 应用上下文注入全局变量
contextInject: {
// 应用Key
appKey: "",
fileUrl: "附件地址",
},
// public/index.html注入全局变量
windowInject: {
// 应用标题
title: "微应用模板",
// 注入css链接集合
links: [],
element: {
root: {
// 挂载DOM元素ID
id: "root",
},
},
// 注入js链接集合
scripts: [
"https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OElqFYoKiAH8KFtph8ftLKF5NlNrbCUr",
],
},
// 开发服务
server: {
// 监听端口号
port: "8080",
// 服务地址
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"]
}

47
package.json Normal file
View File

@ -0,0 +1,47 @@
{
"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": "latest",
"@ant-design/pro-components": "^2.8.10",
"@cqsjjb/jjb-common-decorator": "latest",
"@cqsjjb/jjb-common-lib": "latest",
"@cqsjjb/jjb-dva-runtime": "latest",
"@cqsjjb/jjb-react-admin-component": "latest",
"ahooks": "^3.9.5",
"antd": "latest",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"zy-react-library": "latest"
},
"devDependencies": {
"@antfu/eslint-config": "^5.4.1",
"@babel/plugin-proposal-decorators": "^7.19.3",
"@cqsjjb/scripts": "latest",
"@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"></div>
</body>
</html>

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}",
// );

View File

@ -0,0 +1,147 @@
import { Input, Tree } from "antd";
import { useEffect, useState } from "react";
const { Search } = Input;
const LeftTree = (props) => {
const {
onClick,
expandedKeys: externalExpandedKeys,
} = props;
const [treeData, setTreeData] = useState([]);
const [expandedKeys, setExpandedKeys] = useState([]);
const [searchValue, setSearchValue] = useState("");
const [autoExpandParent, setAutoExpandParent] = useState(true);
const getData = () => {
setTreeData([
{
title: "parent 1",
key: "0-0",
children: [
{
title: "parent 1-0",
key: "0-0-0",
children: [
{
title: "leaf",
key: "0-0-0-0",
},
{
title: "leaf",
key: "0-0-0-1",
},
],
},
{
title: "parent 1-1",
key: "0-0-1",
},
],
},
]);
};
useEffect(() => {
getData();
}, []);
useEffect(() => {
setExpandedKeys(externalExpandedKeys);
}, [externalExpandedKeys]);
// 展开所有包含匹配项的父节点
const getAllExpandedKeys = (data, searchValue, keys = []) => {
data.forEach((node) => {
if (node.children) {
if (node.title.includes(searchValue)
|| node.children.some(child => child.title.includes(searchValue))) {
keys.push(node.key);
}
getAllExpandedKeys(node.children, searchValue, keys);
}
});
return keys;
};
const onExpand = (newExpandedKeys) => {
setExpandedKeys(newExpandedKeys);
setAutoExpandParent(false);
};
const onFilterTreeData = (value) => {
setSearchValue(value);
setAutoExpandParent(true);
if (!value) {
setExpandedKeys([]);
return;
}
const expandedKeys = getAllExpandedKeys(treeData, value);
setExpandedKeys(expandedKeys);
};
const onSearch = (value) => {
if (value === searchValue)
return;
onFilterTreeData(value);
};
// 渲染带高亮的标题
const renderTitle = (title) => {
if (!searchValue)
return title;
const index = title.indexOf(searchValue);
if (index === -1)
return title;
const beforeStr = title.substring(0, index);
const afterStr = title.substring(index + searchValue.length);
return (
<span>
{beforeStr}
<span style={{ color: "#f50" }}>{searchValue}</span>
{afterStr}
</span>
);
};
// 递归处理树节点标题显示
const processTreeData = (data) => {
return data.map(node => ({
...node,
title: renderTitle(node.title),
children: node.children ? processTreeData(node.children) : undefined,
}));
};
const processedTreeData = processTreeData(treeData);
const onSelect = (selectedKeys, event) => {
onClick?.(selectedKeys, event);
};
return (
<div style={{ width: 300 }}>
<Search
style={{ marginBottom: 8 }}
placeholder="输入关键字进行过滤"
onSearch={onSearch}
/>
<Tree
onExpand={onExpand}
onSelect={onSelect}
autoExpandParent={autoExpandParent}
expandedKeys={expandedKeys}
treeData={processedTreeData}
/>
</div>
);
};
export default LeftTree;

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

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

View File

@ -0,0 +1,5 @@
/**
* 全局常量定义
*/
export {};

View File

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

View File

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

47
src/main.js Normal file
View File

@ -0,0 +1,47 @@
import { setJJBCommonAntdMessage } from "@cqsjjb/jjb-common-lib";
import { setup } from "@cqsjjb/jjb-dva-runtime";
import { message } from "antd";
import dayjs from "dayjs";
import "dayjs/locale/zh-cn";
import "../blessed_by_buddha";
require("antd/dist/reset.css");
dayjs.locale("zh-cn");
setJJBCommonAntdMessage(message);
const app = setup();
// 非底座环境运行
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,75 @@
import { Button, Descriptions, Divider } from "antd";
function Info(props) {
return (
<div style={{ padding: 20 }}>
<Divider orientation="left">基本信息</Divider>
<Descriptions
labelStyle={{ width: 200 }}
column={1}
bordered
items={[
{ label: "企业名称", children: "Zhou" },
{ label: "统一社会信用代码", children: "Zhou" },
{ label: "所属区域", children: "Zhou" },
{ label: "邮政编码", children: "Zhou" },
{ label: "成立时间", children: "Zhou" },
{ label: "规模", children: "Zhou" },
{ label: "经度", children: "Zhou" },
{ label: "纬度", children: "Zhou" },
{ label: "职工人数", children: "Zhou" },
{ label: "占地面积(㎡)", children: "Zhou" },
{ label: "资产总额(万元)", children: "Zhou" },
{ label: "注册资金(万元)", children: "Zhou" },
{ label: "经济类型", children: "Zhou" },
{ label: "所属行业", children: "Zhou" },
{ label: "法定代表人", children: "Zhou" },
{ label: "法人手机号", children: "Zhou" },
{ label: "主要负责人", children: "Zhou" },
{ label: "主要负责人手机号", children: "Zhou" },
{ label: "安全负责人", children: "Zhou" },
{ label: "安全负责人手机号", children: "Zhou" },
{ label: "隶属关系", children: "Zhou" },
{ label: "是否规模以上", children: "Zhou" },
{ label: "企事业单位经营地址", children: "Zhou" },
{ label: "企业状态", children: "Zhou" },
{ label: "营业执照", children: "Zhou" },
]}
/>
<Divider orientation="left">企业相关属性</Divider>
<Descriptions
labelStyle={{ width: 200 }}
column={1}
bordered
items={[
{ label: "有无职业卫生信息", children: "Zhou" },
{ label: "有无重大危险源", children: "Zhou" },
{ label: "是否有稀缺大型应急物资和设施", children: "Zhou" },
{ label: "有无涉及危化品", children: "Zhou" },
{ label: "有无特种设备", children: "Zhou" },
{ label: "有无特种工作人员", children: "Zhou" },
{ label: "是否涉及煤气", children: "Zhou" },
{ label: "是否属于消防重点单位", children: "Zhou" },
{ label: "是否在有限空间作业", children: "Zhou" },
{ label: "是否存在涉爆粉尘作业", children: "Zhou" },
{ label: "是否涉及防雷防静电", children: "Zhou" },
{ label: "是否持有放射源", children: "Zhou" },
{ label: "是否涉及液氨制冷", children: "Zhou" },
{ label: "是否涉及危险品管道", children: "Zhou" },
]}
/>
<div style={{ marginTop: 10, textAlign: "center" }}>
<Button
type="primary"
onClick={() => {
props.history.push("./update");
}}
>
修改
</Button>
</div>
</div>
);
}
export default Info;

View File

@ -0,0 +1,242 @@
import { Form } from "antd";
import FormBuilder from "zy-react-library/components/FormBuilder";
import HeaderBack from "zy-react-library/components/HeaderBack";
import Map from "zy-react-library/components/Map";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import { PHONE, POSTAL_CODE, UNIFIED_SOCIAL_CREDIT_CODE } from "zy-react-library/regular";
const PRESENCE_OR_ABSENCE_ENUM = [
{ id: "1", name: "有" },
{ id: "0", name: "无" },
];
const WHETHER_ENUM = [
{ id: "1", name: "是" },
{ id: "0", name: "否" },
];
function Update() {
const [form] = Form.useForm();
const onSubmit = (values) => {
console.log(values);
};
return (
<>
<HeaderBack title="修改" />
<div style={{ paddingBottom: 10 }}>
<FormBuilder
form={form}
values={{ FOURTYPE: "1" }}
onFinish={onSubmit}
options={[
{ label: "基本信息", render: FORM_ITEM_RENDER_ENUM.DIVIDER },
{ label: "企业名称", name: "CORP_NAME", span: 24 },
{
label: "社会统一信用代码",
name: "CODE",
rules: [{ pattern: UNIFIED_SOCIAL_CREDIT_CODE, message: "请输入正确的社会统一信用代码" }],
},
{ label: "所属区域", name: "POSSESSION" },
{
label: "邮政编码",
name: "POSTAL_CODE",
required: false,
rules: [{ pattern: POSTAL_CODE, message: "请输入正确的邮政编码" }],
},
{
label: "规模",
name: "SCALE",
required: false,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1-10人", name: "1-10人" }],
},
{ label: "成立时间", name: "CREATE_DATE", required: false, render: FORM_ITEM_RENDER_ENUM.DATE },
{
label: "企业状态",
name: "CORP_STATE",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1-10人", name: "1-10人" }],
},
{ name: "map", customizeRender: true, render: Map, span: 24 },
{ label: "职工人数", name: "LR_NAME", required: false, render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ label: "占地面积(㎡)", name: "LR_NAME", required: false, render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ label: "注册资金(万元)", name: "REGCAPITAL", required: false, render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ label: "资产总额(万元)", name: "TOTALASSETS", required: false, render: FORM_ITEM_RENDER_ENUM.NUMBER },
{
label: "经济类型",
name: "ECO_TYPE",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1-10人", name: "1-10人" }],
},
{
label: "所属行业",
name: "INDUSTRYALL",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1-10人", name: "1-10人" }],
},
{ label: "法定代表人", name: "LR_NAME", required: false },
{
label: "法人手机号",
name: "LR_PHONE",
required: false,
rules: [{ pattern: PHONE, message: "请输入正确的手机号" }],
},
{ label: "主要负责人", name: "CONTACTS" },
{ label: "主要负责人手机号", name: "CONTACTS_PHONE", rules: [{ pattern: PHONE, message: "请输入正确的手机号" }] },
{ label: "安全负责人", name: "SAFETY_NAME", required: false },
{
label: "安全负责人电话手机号",
name: "SAFETY_PHONE",
required: false,
rules: [{ pattern: PHONE, message: "请输入正确的手机号" }],
},
{
label: "隶属关系",
name: "SUBORDINATION",
required: false,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1-10人", name: "1-10人" }],
},
{
label: "是否规模以上",
name: "SCALE_TYPE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{ label: "企事业单位经营地址", name: "ADDRESS_BUSINESS", span: 24 },
{
label: "四色图类型",
name: "FOURTYPE",
required: false,
span: 24,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: [{ id: "1", name: "平面四色图" }],
componentProps: {
onChange: () => {
form.setFieldValue("FOUR_IMAGES", undefined);
},
},
},
{
label: "四色图",
name: "FOUR_IMAGES",
required: false,
span: 24,
dependencies: ["FOURTYPE"],
hidden: formValues => !(formValues.FOURTYPE === "1"),
render: ({ value, onChange }) => <Upload ratio="1480*640" value={value} onChange={onChange} />,
},
{
label: "营业执照",
name: "BUS_IMAGES",
span: 24,
render: ({ value, onChange }) => <Upload maxCount={9} value={value} onChange={onChange} />,
},
{ label: "企业相关属性", render: FORM_ITEM_RENDER_ENUM.DIVIDER },
{
label: "有无职业卫生信息",
name: "WHETHER_HYGIENE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: PRESENCE_OR_ABSENCE_ENUM,
},
{
label: "有无重大污染源",
name: "WHETHER_HAZARDS",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: PRESENCE_OR_ABSENCE_ENUM,
},
{
label: "是否有稀缺大型应急物资或设施",
name: "WHETHER_SCARCE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否涉及危化品",
name: "WHETHER_CHEMICALS",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "有无特种设备",
name: "WHETHER_SPECIALEQUIPMENT",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: PRESENCE_OR_ABSENCE_ENUM,
},
{
label: "有无特种作业人员",
name: "WHETHER_SPECIALPEOPLE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: PRESENCE_OR_ABSENCE_ENUM,
},
{
label: "是否涉及煤气",
name: "WHETHER_COALGAS",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否属于消防重点单位",
name: "WHETHER_FIRE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否在受限空间作业",
name: "WHETHER_CONFINED",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否存在涉爆粉尘作业",
name: "WHETHER_POWDER",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否涉及防雷防静电",
name: "WHETHER_LIGHTNING",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否持有放射源",
name: "WHETHER_ACTINOGEN",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否涉及液氨制冷",
name: "WHETHER_LIQUIDAMMONIA",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
label: "是否涉及危化品管道",
name: "WHETHER_PIPELINE",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
]}
/>
</div>
</>
);
}
export default Update;

View File

@ -0,0 +1,9 @@
function CorpInfo(props) {
return (
<div>
{props.children}
</div>
);
}
export default CorpInfo;

View File

@ -0,0 +1,31 @@
import { tools } from "@cqsjjb/jjb-common-lib";
import FormBuilder from "zy-react-library/components/FormBuilder";
import HeaderBack from "zy-react-library/components/HeaderBack";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
const { query } = tools.router;
function Add() {
const onSubmit = (values) => {
console.log(values);
};
return (
<>
<HeaderBack title={query.id ? "修改" : "新增"} />
<FormBuilder
onFinish={onSubmit}
span={24}
options={[
{ name: "name", label: "证书名称" },
{ name: "name", label: "证书有效期", render: FORM_ITEM_RENDER_ENUM.DATE },
{ name: "name", label: "证书编号" },
{ name: "name", label: "备注", required: false, render: FORM_ITEM_RENDER_ENUM.TEXTAREA },
{ name: "name", label: "证书图片", render: ({ value, onChange }) => <Upload maxCount={9} value={value} onChange={onChange} /> },
]}
/>
</>
);
}
export default Add;

View File

@ -0,0 +1,52 @@
import { Button, Form, message, Modal, Space } from "antd";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import TooltipPreviewImg from "zy-react-library/components/TooltipPreviewImg";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
function List(props) {
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {}, { form });
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<Search
options={[
{ name: "name", label: "关键字", tip: "证书名称/证书编号" },
{ name: "name", label: "证书有效期", render: FORM_ITEM_RENDER_ENUM.DATE_RANGE },
]}
form={form}
/>
<Table
toolBarRender={() => (
<Button type="primary" onClick={() => props.history.push("./add")}>新增</Button>
)}
columns={[
{ title: "证书名称", dataIndex: "name" },
{ title: "证书有效期", dataIndex: "name" },
{ title: "证书编号", dataIndex: "name" },
{ title: "照片", dataIndex: "name", render: () => (<TooltipPreviewImg files={[]} />) },
{ title: "操作", width: 200, render: (_, record) => (
<Space>
<Button type="link" onClick={() => props.history.push(`./add?id=${record.id}`)}>修改</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
) },
]}
{...tableProps}
/>
</div>
);
}
export default List;

View File

@ -0,0 +1,9 @@
function IndustryQualification(props) {
return (
<div>
{props.children}
</div>
);
}
export default IndustryQualification;

View File

@ -0,0 +1,147 @@
import { Button, Form, message, Modal, Space, Tag } from "antd";
import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import { PHONE } from "zy-react-library/regular";
import LeftTree from "~/components/LeftTree";
const DEPARTMENT_LEVEL_ENUM = [
{ id: "departmentLevel0001", name: "分公司" },
{ id: "departmentLevel0002", name: "科/厂队" },
{ id: "departmentLevel0003", name: "班组" },
];
function OrganizationStructure() {
const [addModalOpen, setAddModalOpen] = useState(false);
const [currentId, setCurrentId] = useState("");
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {}, { form });
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<div style={{ display: "flex", gap: 20 }}>
<LeftTree />
<div style={{ flex: 1 }}>
<Search
options={[
{ name: "name", label: "名称" },
{
name: "name",
label: "部门级别",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: DEPARTMENT_LEVEL_ENUM,
},
]}
form={form}
/>
<Table
toolBarRender={() => (
<>
<Button
type="primary"
onClick={() => {
setAddModalOpen(true);
}}
>
新增
</Button>
<Button>返回</Button>
</>
)}
columns={[
{ title: "名称", dataIndex: "name" },
{ title: "部门级别", dataIndex: "name" },
{ title: "主管领导", dataIndex: "name" },
{
title: "操作",
width: 200,
render: (_, record) => (
<Space>
<Button
type="link"
onClick={() => {
setAddModalOpen(true);
setCurrentId(record.id);
}}
>
修改
</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
),
},
]}
{...tableProps}
/>
</div>
</div>
<AddModal
currentId={currentId}
open={addModalOpen}
onCancel={() => {
setAddModalOpen(false);
setCurrentId("");
}}
getData={getData}
/>
</div>
);
}
function AddModalComponent(props) {
const [form] = Form.useForm();
useEffect(() => {
if (props.currentId) {
console.log(props.currentId);
}
}, [props.currentId]);
const onCancel = () => {
form.resetFields();
props.onCancel();
};
const onSubmit = async (values) => {
console.log(values);
onCancel();
props.getData();
};
return (
<Modal
open={props.open}
onCancel={onCancel}
onOk={form.submit}
title={props.currentId ? "修改" : "新增"}
width={800}
>
<FormBuilder
form={form}
span={24}
labelCol={{ span: 10 }}
onFinish={onSubmit}
showActionButtons={false}
options={[
{ name: "name", label: "上级部门", render: () => (<Tag color="processing">111</Tag>) },
{ name: "name", label: "名称" },
{ name: "name", label: "部门级别", render: FORM_ITEM_RENDER_ENUM.SELECT, items: DEPARTMENT_LEVEL_ENUM },
{ name: "name", label: "安全监管部门", required: false, render: FORM_ITEM_RENDER_ENUM.RADIO, items: [{ id: "0", name: "是" }, { id: "2", name: "否" }], tip: "安全监管部门负责人在“安委会办公室副主任核实”菜单处理重大较大隐患" },
{ name: "name", label: "部门负责人", required: false, render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ id: "1-10人", name: "1-10人" }] },
{ name: "name", label: "部门负责人手机号", required: false, rules: [{ pattern: PHONE, message: "请输入正确的手机号" }] },
{ name: "name", label: "排序", render: FORM_ITEM_RENDER_ENUM.NUMBER },
]}
/>
</Modal>
);
}
const AddModal = AddModalComponent;
export default OrganizationStructure;

View File

@ -0,0 +1,161 @@
import { Button, Form, message, Modal, Space, Tag } from "antd";
import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import LeftTree from "~/components/LeftTree";
function Position() {
const [addModalOpen, setAddModalOpen] = useState(false);
const [currentId, setCurrentId] = useState("");
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {
}, { form });
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<div style={{ display: "flex", gap: 20 }}>
<LeftTree />
<div style={{ flex: 1 }}>
<Search
options={[
{ name: "name", label: "名称" },
{
name: "name",
label: "部门级别",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
]}
form={form}
/>
<Table
toolBarRender={() => (
<>
<Button
type="primary"
onClick={() => {
setAddModalOpen(true);
}}
>
新增
</Button>
<Button>返回</Button>
</>
)}
columns={[
{ title: "部门名称", dataIndex: "name" },
{ title: "岗位名称", dataIndex: "name" },
{ title: "状态", dataIndex: "name", width: 100 },
{
title: "操作",
width: 200,
render: (_, record) => (
<Space>
<Button
type="link"
onClick={() => {
setAddModalOpen(true);
setCurrentId(record.id);
}}
>
修改
</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
),
},
]}
{...tableProps}
/>
</div>
</div>
<AddModal
currentId={currentId}
open={addModalOpen}
onCancel={() => {
setAddModalOpen(false);
setCurrentId("");
}}
getData={getData}
/>
</div>
);
}
function AddModalComponent(props) {
const [form] = Form.useForm();
useEffect(() => {
if (props.currentId) {
console.log(props.currentId);
}
}, [props.currentId]);
const onCancel = () => {
form.resetFields();
props.onCancel();
};
const onSubmit = async (values) => {
console.log(values);
onCancel();
props.getData();
};
return (
<Modal
open={props.open}
onCancel={onCancel}
onOk={form.submit}
title={props.currentId ? "修改" : "新增"}
width={800}
>
<FormBuilder
form={form}
span={24}
labelCol={{ span: 10 }}
onFinish={onSubmit}
showActionButtons={false}
options={[
{ name: "name", label: "上级部门", render: () => (<Tag color="processing">111</Tag>) },
{ name: "name", label: "岗位名称" },
{ name: "name", label: "岗位职责" },
{
name: "name",
label: "状态",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "0", name: "启用" }, { id: "1", name: "禁用" }],
},
{
name: "regPost",
label: "是否监管岗位",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "1", name: "是" }, { id: "2", name: "否" }],
componentProps: {
onChange: () => {
form.setFieldValue("name", undefined);
},
},
},
{
name: "name",
label: "数据权限",
dependencies: ["regPost"],
hidden: formValues => !(formValues.regPost === "1"),
},
]}
/>
</Modal>
);
}
const AddModal = AddModalComponent;
export default Position;

View File

@ -0,0 +1,298 @@
import { tools } from "@cqsjjb/jjb-common-lib";
import { Button, Col, Form, Row, Select, Switch } from "antd";
import { useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import HeaderBack from "zy-react-library/components/HeaderBack";
import SelectCreate from "zy-react-library/components/SelectCreate";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import { ID_NUMBER } from "zy-react-library/regular";
import Scheduling from "~/pages/Container/Enterprise/User/components/Scheduling";
const { query } = tools.router;
const WHETHER_ENUM = [
{ id: "1", name: "是" },
{ id: "0", name: "否" },
];
function Add() {
const [form] = Form.useForm();
const [schedulingOpen, setSchedulingOpen] = useState(false);
const onSubmit = (values) => {
console.log(values);
};
return (
<>
<HeaderBack title={query.id ? "修改" : "新增"} />
<div style={{ paddingBottom: 10 }}>
<FormBuilder
form={form}
values={{
isHazardconfirmer: "0",
facePermissions: "0",
mkmjVehicleReviewer: "0",
isAccessauditor: "0",
}}
onFinish={onSubmit}
labelCol={{ span: 6 }}
options={[
{ name: "roleId", label: "角色", render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "一级部门", id: "1" }] },
{ name: "departmentId", label: "部门" },
{
name: "postId",
label: "岗位",
required: false,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{ name: "username", label: "用户名", tip: "* 如果修改手机号登录密码则会变成初始密码“Aa@123456789”" },
{ name: "name", label: "姓名" },
{
name: "personType",
label: "人员类型",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "userIdCard",
label: "身份证号",
dependencies: ["facePermissions"],
required: formValues => formValues.facePermissions === "1",
rules: [{ pattern: ID_NUMBER, message: "请输入正确的身份证号" }],
},
{
name: "nation",
label: "民族",
required: false,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "sex",
label: "性别",
required: false,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "inHrUser",
label: "是否对接人资系统",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: { disabled: true },
},
{
name: "isHazardconfirmer",
label: "是否为隐患确认人",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "facePermissions",
label: "是否具备人脸权限",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "mkmjVehicleReviewer",
label: "是否为口门门禁车辆审核人",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "isAccessauditor",
label: "是否为临时访客审核人",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "faceFile",
label: "上传人脸照片",
span: 24,
dependencies: ["facePermissions"],
required: formValues => formValues.facePermissions === "1",
render: ({ value, onChange }) => (
<Upload
size={4}
value={value}
onChange={onChange}
tipContent={(
<div style={{ lineHeight: 1.6, color: "red", fontSize: 12 }}>
<div>* 图像格式JPGJPEGPNG</div>
<div>* 图像大小不超过4M</div>
<div>* 照片大小: 推荐 500*500</div>
<div>* 人脸无遮挡如戴帽子口罩眼镜等无修图</div>
<div>* 人脸需双眼睁开表情自然露额头发不要遮挡</div>
</div>
)}
/>
),
},
{ name: "sort", label: "部门排序", required: false, render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ name: "email", label: "邮箱", required: false, rules: [{ type: "email", message: "请输入正确的邮箱" }] },
{
name: "scheduling",
label: "排班",
span: 24,
customizeRender: true,
render: () => (
<>
<Row>
<Col span={12}>
<Form.Item label="排班" name="shiftdutyone">
<Select>
{
[{ name: "一级部门", id: "1" }].map(item => (
<Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>
))
}
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label=" " labelCol={{ span: 1 }} name="shiftdutytwo" colon={false}>
<div style={{ display: "flex", gap: 10 }}>
<Select>
{
[{ name: "一级部门", id: "1" }].map(item => (
<Select.Option value={item.id} key={item.id}>{item.name}</Select.Option>
))
}
</Select>
<Button
type="primary"
onClick={() => {
setSchedulingOpen(true);
}}
>
当前班状
</Button>
</div>
</Form.Item>
</Col>
</Row>
</>
),
},
{ name: "bz", label: "备注", span: 24, required: false, render: FORM_ITEM_RENDER_ENUM.TEXTAREA },
{
name: "isStudent",
label: "是否在线学习人员",
span: 24,
required: false,
render: Switch,
componentProps: {
onChange: () => {
form.setFieldValue("politicalOutlook", undefined);
form.setFieldValue("dateOfBirth", undefined);
form.setFieldValue("incumbency", undefined);
form.setFieldValue("duties", undefined);
form.setFieldValue("title", undefined);
form.setFieldValue("typeOfWork", undefined);
form.setFieldValue("entryDate", undefined);
form.setFieldValue("workingDate", undefined);
form.setFieldValue("userCerFile", undefined);
},
},
},
{
name: "politicalOutlook",
label: "政治面貌",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "dateOfBirth",
label: "出生年月",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: FORM_ITEM_RENDER_ENUM.DATE,
},
{
name: "incumbency",
label: "在职情况",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "duties",
label: "职务",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: () => (
<SelectCreate
items={[{ name: "一级部门", id: "1" }]}
label="职务"
onDelete={(option) => {
console.log(option);
}}
/>
),
},
{
name: "title",
label: "职称",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: () => (
<SelectCreate
items={[{ name: "一级部门", id: "1" }]}
label="职务"
onDelete={(option) => {
console.log(option);
}}
/>
),
},
{
name: "typeOfWork",
label: "工种",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: () => (
<SelectCreate
items={[{ name: "一级部门", id: "1" }]}
label="职务"
onDelete={(option) => {
console.log(option);
}}
/>
),
},
{
name: "entryDate",
label: "入职日期",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: FORM_ITEM_RENDER_ENUM.DATE,
},
{
name: "workingDate",
label: "参加工作日期",
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: FORM_ITEM_RENDER_ENUM.DATE,
},
{
name: "userCerFile",
label: "证书信息",
span: 24,
required: false,
dependencies: ["isStudent"],
hidden: formValues => !formValues.isStudent,
render: ({ value, onChange }) => <Upload maxCount={9} value={value} onChange={onChange} />,
},
]}
/>
</div>
<Scheduling open={schedulingOpen} onCancel={() => setSchedulingOpen(false)} />
</>
);
}
export default Add;

View File

@ -0,0 +1,154 @@
import { Button, Form, message, Modal, Space } from "antd";
import { useState } from "react";
import ImportFile from "zy-react-library/components/ImportFile";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import LeftTree from "~/components/LeftTree";
import Scheduling from "~/pages/Container/Enterprise/User/components/Scheduling";
function List(props) {
const [importOpen, setImportOpen] = useState(false);
const [schedulingOpen, setSchedulingOpen] = useState(false);
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {}, { form });
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
const onExportExcel = () => {
Modal.confirm({
title: "提示",
content: "确定要导出到excel吗",
onOk: () => {
},
});
};
const onResetPassword = () => {
Modal.confirm({
title: "提示",
content: "确定要重置密码为Aa@123456789吗",
onOk: () => {
message.success("重置密码成功");
},
});
};
const onUnlock = (id) => {
message.success("解锁成功");
};
const onImportFileConfirm = (values) => {
console.log(values);
message.success("导入成功");
};
return (
<div style={{ padding: 20 }}>
<div style={{ display: "flex", gap: 20 }}>
<LeftTree />
<div style={{ flex: 1 }}>
<Search
options={[
{ name: "name", label: "关键字", tip: "用户名/姓名" },
{
name: "name",
label: "排班",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "name",
label: " ",
labelCol: { span: 1 },
formItemProps: { colon: false },
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "name",
label: "是否为隐患确认人",
labelCol: { span: 8 },
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "是", id: "1" }, { name: "否", id: "0" }],
},
]}
form={form}
/>
<Table
toolBarRender={() => (
<>
<Button
type="primary"
onClick={() => {
props.history.push("./add");
}}
>
新增
</Button>
<Button
type="primary"
onClick={() => {
setImportOpen(true);
}}
>
导入
</Button>
<Button type="primary" onClick={() => onExportExcel()}>导出Excel</Button>
</>
)}
columns={[
{ title: "用户名", dataIndex: "name" },
{ title: "姓名", dataIndex: "name" },
{ title: "部门", dataIndex: "name" },
{ title: "岗位", dataIndex: "name" },
{ title: "排班类型", dataIndex: "name" },
{
title: "操作",
width: 300,
render: (_, record) => (
<Space>
<Button type="link" onClick={() => onResetPassword(record.id)}>重置密码</Button>
<Button
type="link"
onClick={() => {
setSchedulingOpen(true);
}}
>
排班表
</Button>
<Button
type="link"
onClick={() => {
props.history.push(`./add?id=${record.id}`);
}}
>
编辑
</Button>
<Button type="link" onClick={() => onUnlock(record.id)}>解锁</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
),
},
]}
{...tableProps}
/>
</div>
</div>
<ImportFile
visible={importOpen}
templateUrl=""
onConfirm={onImportFileConfirm}
onCancel={() => { setImportOpen(false); }}
/>
<Scheduling open={schedulingOpen} onCancel={() => setSchedulingOpen(false)} />
</div>
);
}
export default List;

View File

@ -0,0 +1,122 @@
import { DoubleLeftOutlined, DoubleRightOutlined, LeftOutlined, RightOutlined } from "@ant-design/icons";
import { Button, Calendar, Modal } from "antd";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
function Scheduling(props) {
const [workDateList, setWorkDateList] = useState([]);
useEffect(() => {
setWorkDateList([
{ DATE: "2025-10-01", STATE: "2" },
{ DATE: "2025-10-02", STATE: "1" },
{ DATE: "2025-10-03", STATE: "1" },
{ DATE: "2025-10-04", STATE: "2" },
{ DATE: "2025-10-05", STATE: "1" },
{ DATE: "2025-10-06", STATE: "1" },
{ DATE: "2025-10-07", STATE: "2" },
{ DATE: "2025-10-08", STATE: "1" },
{ DATE: "2025-10-09", STATE: "1" },
{ DATE: "2025-10-10", STATE: "2" },
{ DATE: "2025-10-11", STATE: "1" },
{ DATE: "2025-10-12", STATE: "1" },
{ DATE: "2025-10-13", STATE: "2" },
{ DATE: "2025-10-14", STATE: "1" },
{ DATE: "2025-10-15", STATE: "1" },
{ DATE: "2025-10-16", STATE: "2" },
{ DATE: "2025-10-17", STATE: "1" },
{ DATE: "2025-10-18", STATE: "1" },
{ DATE: "2025-10-19", STATE: "2" },
{ DATE: "2025-10-20", STATE: "1" },
{ DATE: "2025-10-21", STATE: "1" },
{ DATE: "2025-10-22", STATE: "2" },
{ DATE: "2025-10-23", STATE: "1" },
{ DATE: "2025-10-24", STATE: "1" },
{ DATE: "2025-10-25", STATE: "2" },
{ DATE: "2025-10-26", STATE: "1" },
{ DATE: "2025-10-27", STATE: "1" },
{ DATE: "2025-10-28", STATE: "2" },
{ DATE: "2025-10-29", STATE: "1" },
{ DATE: "2025-10-30", STATE: "1" },
{ DATE: "2025-10-31", STATE: "2" },
]);
}, []);
const cellRender = (current) => {
return (
workDateList.map((item) => {
if (item.DATE === dayjs(current).format("YYYY-MM-DD")) {
return (
<span key={item.DATE}>
{item.STATE === "1"
? <span style={{ color: "#0bb20c" }}>上班</span>
: item.STATE === "2"
? <span style={{ color: "red" }}>休班</span>
: null}
</span>
);
}
return null;
})
);
};
const headerRender = ({ value, onChange }) => {
const year = value.year();
const month = value.month() + 1;
const onNextYear = () => {
const nextValue = value.add(1, "year");
onChange(nextValue);
};
const onPrevYear = () => {
const prevValue = value.subtract(1, "year");
onChange(prevValue);
};
const onNextMonth = () => {
const nextValue = value.add(1, "month");
onChange(nextValue);
};
const onPrevMonth = () => {
const prevValue = value.subtract(1, "month");
onChange(prevValue);
};
return (
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "10px 0" }}>
<div>
<Button onClick={onPrevYear} icon={<DoubleLeftOutlined style={{ fontSize: 12 }} />} iconPosition="start">前一年</Button>
<Button onClick={onPrevMonth} style={{ marginLeft: 8 }} icon={<LeftOutlined style={{ fontSize: 12 }} />} iconPosition="start">前一月</Button>
</div>
<div style={{ fontSize: "16px", fontWeight: "bold" }}>
{year}
{month}
</div>
<div>
<Button onClick={onNextMonth} icon={<RightOutlined style={{ fontSize: 12 }} />} iconPosition="end">后一月</Button>
<Button onClick={onNextYear} style={{ marginLeft: 8 }} icon={<DoubleRightOutlined style={{ fontSize: 12 }} />} iconPosition="end">后一年</Button>
</div>
</div>
);
};
return (
<Modal
open={props.open}
onCancel={props.onCancel}
title="排班表"
width={800}
footer={[
<Button key="cancel" onClick={props.onCancel}>
关闭
</Button>,
]}
>
<Calendar cellRender={cellRender} headerRender={headerRender} />
</Modal>
);
}
export default Scheduling;

View File

@ -0,0 +1,9 @@
function User(props) {
return (
<div>
{props.children}
</div>
);
}
export default User;

View File

@ -0,0 +1,9 @@
function Enterprise(props) {
return (
<div>
{props.children}
</div>
);
}
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,155 @@
import { Button, Form, Image, message, Modal, Space } from "antd";
import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Table from "zy-react-library/components/Table";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
function Qualification() {
const [addModalOpen, setAddModalOpen] = useState(false);
const [currentId, setCurrentId] = useState("");
const [previewSrc, setPreviewSrc] = useState("");
const [previewOpen, setPreviewOpen] = useState(false);
const { tableProps, getData } = useTable(() => {});
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<Table
disabledResizer={false}
toolBarRender={() => (
<Button
type="primary"
onClick={() => {
setAddModalOpen(true);
}}
>
新增
</Button>
)}
columns={[
{ title: "资质正式名称", dataIndex: "name" },
{ title: "证书有限期", dataIndex: "name" },
{ title: "证书编号", dataIndex: "name" },
{
title: "操作",
width: 200,
render: (_, record) => (
<Space>
<Button
type="link"
onClick={() => {
setPreviewSrc(record.id);
setPreviewOpen(true);
}}
>
预览
</Button>
<Button
type="link"
onClick={() => {
setAddModalOpen(true);
setCurrentId(record.id);
}}
>
修改
</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
),
},
]}
{...tableProps}
/>
<AddModal
currentId={currentId}
open={addModalOpen}
onCancel={() => {
setAddModalOpen(false);
setCurrentId("");
}}
getData={getData}
/>
<PreviewModal
src={previewSrc}
open={previewOpen}
onCancel={() => {
setPreviewOpen(false);
setPreviewSrc("");
}}
/>
</div>
);
}
function AddModalComponent(props) {
const [form] = Form.useForm();
useEffect(() => {
if (props.currentId) {
console.log(props.currentId);
}
}, [props.currentId]);
const onCancel = () => {
form.resetFields();
props.onCancel();
};
const onSubmit = async (values) => {
console.log(values);
onCancel();
props.getData();
};
return (
<Modal
open={props.open}
onCancel={onCancel}
onOk={form.submit}
title={props.currentId ? "修改" : "新增"}
width={800}
>
<FormBuilder
form={form}
span={24}
labelCol={{ span: 8 }}
onFinish={onSubmit}
showActionButtons={false}
options={[
{ name: "QUALIFICATION_NAME", label: "资质正式名称" },
{ name: "date", label: "证书有限期", render: FORM_ITEM_RENDER_ENUM.DATE_RANGE },
{ name: "CERTIFICATE_NO", label: "证书编号" },
{ name: "QUALIFICATION_PIC", label: "照片", render: ({ value, onChange }) => <Upload size={5} value={value} onChange={onChange} /> },
]}
/>
</Modal>
);
}
function PreviewModalComponent(props) {
return (
<Modal
open={props.open}
onCancel={props.onCancel}
title="预览"
footer={[
<Button key="cancel" onClick={props.onCancel}>
关闭
</Button>,
]}
>
<div style={{ display: "flex", justifyContent: "center" }}>
<Image width={200} src={props.src} />
</div>
</Modal>
);
}
const AddModal = AddModalComponent;
const PreviewModal = PreviewModalComponent;
export default Qualification;

View File

@ -0,0 +1,93 @@
import { Button, Modal, QRCode } from "antd";
import { useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Map from "zy-react-library/components/Map";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import { PHONE, UNIFIED_SOCIAL_CREDIT_CODE } from "zy-react-library/regular";
import Qualification from "./components/Qualification";
const xgfStateMap = {
0: "未填报",
1: "待审核",
2: "已审核",
3: <span style={{ color: "red" }}>已打回</span>,
4: "已填报",
};
function CorpInfo() {
const [corpInfoQrCodeOpen, setCorpInfoQrCodeOpen] = useState(false);
const onSubmit = (values) => {
console.log(values);
};
return (
<>
<div style={{ paddingBottom: 10 }}>
<FormBuilder
onFinish={onSubmit}
options={[
{ label: "相关方单位基础信息", render: FORM_ITEM_RENDER_ENUM.DIVIDER },
{ name: "corpName", label: "单位名称" },
{ name: "xgfState", label: "企业状态", required: false, render: ({ formValues }) => xgfStateMap[formValues?.xgfState] || "未填报" },
{ name: "managerDepIds", label: "股份监管部门", required: false },
{ name: "mainDepIds", label: "股份主管部门", required: false },
{ name: "competentDepIds", label: "基层单位监管部门", required: false },
{ name: "superviseDepIds", label: "基层单位主管部门", required: false },
{ name: "corpTypIds", label: "集团单位", required: false, render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "集团单位1", id: "1" }] },
{ name: "holderName", label: "开户人", required: false },
{ name: "code", label: "统一社会信用代码", rules: [{ pattern: UNIFIED_SOCIAL_CREDIT_CODE, message: "请输入正确的统一社会信用代码" }] },
{ name: "companyAreas", label: "属地" },
{ name: "industryNames", label: "所属行业" },
{ name: "ecoType", label: "经济类型", render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "集团单位1", id: "1" }] },
{ name: "map", customizeRender: true, render: () => <Map required={false} />, span: 24 },
{ name: "address", label: "单位经营地址" },
{ name: "scale", label: "企业规模", render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "集团单位1", id: "1" }] },
{ name: "lrName", label: "法人姓名" },
{ name: "lrPhone", label: "联系电话", rules: [{ pattern: PHONE, message: "请输入正确的手机号码" }] },
{ name: "contacts", label: "主要负责人" },
{ name: "contactsPhone", label: "主要负责人联系电话", rules: [{ pattern: PHONE, message: "请输入正确的手机号码" }] },
{ name: "createDate", label: "成立日期", render: FORM_ITEM_RENDER_ENUM.DATE },
{ name: "employees", label: "职工人数(人)", render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ name: "totalassets", label: "资产总额(万元)", render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ name: "regcapital", label: "注册资金(万元)", render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ name: "employmentForm", label: "用工形式", render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "集团单位1", id: "1" }] },
{ name: "selectForms", label: "选取形式", render: FORM_ITEM_RENDER_ENUM.SELECT, items: [{ name: "集团单位1", id: "1" }] },
{ name: "businessLicense", label: "营业执照", required: false, render: ({ value, onChange }) => <Upload maxCount={5} size={5} value={value} onChange={onChange} /> },
{ name: "businessLicenseDate", label: "营业执照有效期", render: FORM_ITEM_RENDER_ENUM.DATE },
{ name: "qrCode", label: "企业二维码", required: false, hidden: formValues => !(formValues.xgfState !== 2), render: () => (
<Button
type="link"
onClick={() => {
setCorpInfoQrCodeOpen(true);
}}
>
查看
</Button>
) },
{ label: "单位资质信息", render: FORM_ITEM_RENDER_ENUM.DIVIDER },
{ name: "qualification", customizeRender: true, span: 24, render: Qualification },
]}
/>
</div>
<CorpInfoQrCode open={corpInfoQrCodeOpen} onCancel={() => setCorpInfoQrCodeOpen(false)} />
</>
);
}
const CorpInfoQrCode = (props) => {
return (
<Modal
open={props.open}
onCancel={props.onCancel}
title="企业二维码"
footer={[
<Button key="cancel" onClick={props.onCancel}>
关闭
</Button>,
]}
>
<QRCode value="-" style={{ margin: "0 auto" }} />
</Modal>
);
};
export default CorpInfo;

View File

@ -0,0 +1,145 @@
import { Button, Form, message, Modal, Space, Tag } from "antd";
import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import { PHONE } from "zy-react-library/regular";
import LeftTree from "~/components/LeftTree";
const DEPARTMENT_LEVEL_ENUM = [
{ id: "1", name: "公司级" },
{ id: "2", name: "部门级" },
{ id: "3", name: "小组级" },
];
function Department() {
const [addModalOpen, setAddModalOpen] = useState(false);
const [currentId, setCurrentId] = useState("");
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {}, { form });
const onDelete = (id) => {
Modal.confirm({
title: "提示",
content: "确定删除吗?",
onOk: () => {
message.success("删除成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<div style={{ display: "flex", gap: 20 }}>
<LeftTree />
<div style={{ flex: 1 }}>
<Search
options={[
{ name: "name", label: "名称" },
{
name: "name",
label: "部门级别",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: DEPARTMENT_LEVEL_ENUM,
},
]}
form={form}
/>
<Table
toolBarRender={() => (
<>
<Button
type="primary"
onClick={() => {
setAddModalOpen(true);
}}
>
新增
</Button>
<Button>返回</Button>
</>
)}
columns={[
{ title: "部门名称", dataIndex: "name" },
{ title: "部门级别", dataIndex: "name" },
{ title: "主管领导", dataIndex: "name" },
{
title: "操作",
width: 200,
render: (_, record) => (
<Space>
<Button
type="link"
onClick={() => {
setAddModalOpen(true);
setCurrentId(record.id);
}}
>
修改
</Button>
<Button type="link" danger onClick={() => onDelete(record.id)}>删除</Button>
</Space>
),
},
]}
{...tableProps}
/>
</div>
</div>
<AddModal
currentId={currentId}
open={addModalOpen}
onCancel={() => {
setAddModalOpen(false);
setCurrentId("");
}}
getData={getData}
/>
</div>
);
}
function AddModalComponent(props) {
const [form] = Form.useForm();
useEffect(() => {
if (props.currentId) {
console.log(props.currentId);
}
}, [props.currentId]);
const onCancel = () => {
form.resetFields();
props.onCancel();
};
const onSubmit = async (values) => {
console.log(values);
onCancel();
props.getData();
};
return (
<Modal
open={props.open}
onCancel={onCancel}
onOk={form.submit}
title={props.currentId ? "修改" : "新增"}
width={800}
>
<FormBuilder
form={form}
span={24}
labelCol={{ span: 10 }}
onFinish={onSubmit}
showActionButtons={false}
options={[
{ name: "name", label: "上级部门", render: () => (<Tag color="processing">111</Tag>) },
{ name: "name", label: "部门级别", render: FORM_ITEM_RENDER_ENUM.SELECT, items: DEPARTMENT_LEVEL_ENUM },
{ name: "name", label: "部门负责人", required: false },
{ name: "name", label: "部门负责人手机号", required: false, rules: [{ pattern: PHONE, message: "请输入正确的手机号" }] },
{ name: "name", label: "排序", render: FORM_ITEM_RENDER_ENUM.NUMBER },
]}
/>
</Modal>
);
}
const AddModal = AddModalComponent;
export default Department;

View File

@ -0,0 +1,49 @@
import { Form } from "antd";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import TooltipPreviewImg from "zy-react-library/components/TooltipPreviewImg";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import { PERSONNEL_TYPE_ENUM } from "~/pages/Container/Stakeholder/User/List";
function SpecialOperationPersonnel() {
const [form] = Form.useForm();
const { tableProps } = useTable(() => {}, { form });
return (
<div style={{ padding: 20 }}>
<Search
options={[
{ name: "name", label: "姓名" },
{
name: "name",
label: "人员类型",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: PERSONNEL_TYPE_ENUM,
},
{
name: "name",
label: "证书类型",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "0", name: "证书类型" }],
},
]}
form={form}
/>
<Table
columns={[
{ title: "姓名", dataIndex: "name" },
{ title: "部门", dataIndex: "name" },
{ title: "人员类型", dataIndex: "name" },
{ title: "证书类型", dataIndex: "name" },
{ title: "证书编号", dataIndex: "name" },
{ title: "就职状态", dataIndex: "name" },
{ title: "图片", dataIndex: "name", render: text => <TooltipPreviewImg files={text} /> },
]}
{...tableProps}
/>
</div>
);
}
export default SpecialOperationPersonnel;

View File

@ -0,0 +1,51 @@
import { Form } from "antd";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import TooltipPreviewImg from "zy-react-library/components/TooltipPreviewImg";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import { PERSONNEL_TYPE_ENUM } from "~/pages/Container/Stakeholder/User/List";
function SpecialOperationPersonnel() {
const [form] = Form.useForm();
const { tableProps } = useTable(() => {}, { form });
return (
<div style={{ padding: 20 }}>
<Search
options={[
{ name: "name", label: "姓名" },
{
name: "name",
label: "人员类型",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: PERSONNEL_TYPE_ENUM,
},
{
name: "name",
label: "证书作业类别",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "0", name: "证书作业类别" }],
},
]}
form={form}
/>
<Table
columns={[
{ title: "姓名", dataIndex: "name" },
{ title: "部门", dataIndex: "name" },
{ title: "人员类型", dataIndex: "name" },
{ title: "证书名称", dataIndex: "name" },
{ title: "证书作业类别", dataIndex: "name" },
{ title: "操作项目", dataIndex: "name" },
{ title: "证书编号", dataIndex: "name" },
{ title: "就职状态", dataIndex: "name" },
{ title: "图片", dataIndex: "name", render: text => <TooltipPreviewImg files={text} /> },
]}
{...tableProps}
/>
</div>
);
}
export default SpecialOperationPersonnel;

View File

@ -0,0 +1,272 @@
import { tools } from "@cqsjjb/jjb-common-lib";
import { Alert, Form } from "antd";
import FormBuilder from "zy-react-library/components/FormBuilder";
import HeaderBack from "zy-react-library/components/HeaderBack";
import Upload from "zy-react-library/components/Upload";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import { ID_NUMBER } from "zy-react-library/regular";
const { query } = tools.router;
export const WHETHER_ENUM = [
{ name: "是", id: "1" },
{ name: "否", id: "0" },
];
export const SEX_ENUM = [
{ name: "男", id: "0" },
{ name: "女", id: "1" },
];
export const MARITAL_STATUS_ENUM = [
{ name: "已婚", id: "1" },
{ name: "未婚", id: "0" },
];
function Add() {
const [form] = Form.useForm();
const onSubmit = (values) => {
console.log(values);
};
return (
<>
<HeaderBack title={query.id ? "修改" : "新增"} />
<div style={{ paddingBottom: 10 }}>
<FormBuilder
form={form}
values={{ sex: "0" }}
onFinish={onSubmit}
options={[
{
label: "照片",
name: "userImg",
span: 24,
required: false,
render: ({ value, onChange }) => (
<Upload
size={4}
value={value}
onChange={onChange}
tipContent={(
<div style={{ lineHeight: 1.6, color: "red", fontSize: 12 }}>
<div>* 图像格式JPGJPEGPNG</div>
<div>* 图像大小不超过4M</div>
<div>* 照片大小: 推荐 500*500</div>
<div>* 人脸无遮挡如戴帽子口罩眼镜等无修图</div>
<div>* 人脸需双眼睁开表情自然露额头发不要遮挡</div>
</div>
)}
/>
),
},
{ name: "name", label: "姓名" },
{ name: "username", label: "用户名", componentProps: { disabled: query.id } },
{ name: "departmentId", label: "部门" },
{ name: "email", label: "电子邮箱", required: false, rules: [{ type: "email", message: "请输入正确的邮箱" }] },
{ name: "cardId", label: "身份证号", rules: [{ pattern: ID_NUMBER, message: "请输入正确的身份证号" }] },
{
name: "userCardFile",
label: "身份证照片",
render: ({ value, onChange }) => (
<Upload
maxCount={2}
value={value}
onChange={onChange}
tipContent={(
<div style={{ lineHeight: 1.6, color: "red", fontSize: 12 }}>
<div>温馨提示用户要上传身份证正反面身份证照片数量是2张, 才能进行人员培训</div>
</div>
)}
/>
),
},
{
name: "nationality",
label: "民族",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "sex",
label: "性别",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: SEX_ENUM,
componentProps: { disabled: true },
},
{ name: "dateOfBirth", label: "出生年月", render: FORM_ITEM_RENDER_ENUM.DATE },
{ name: "age", label: "年龄", render: FORM_ITEM_RENDER_ENUM.NUMBER },
{ name: "hklocal", label: "户口所在地" },
{ name: "address", label: "现住址" },
{
name: "degreeOfEducation",
label: "文化程度",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
},
{
name: "maritalstatus",
label: "婚姻状况",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: MARITAL_STATUS_ENUM,
},
{
name: "politicalStatus",
label: "政治面貌",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ name: "一级部门", id: "1" }],
componentProps: {
onChange: () => {
form.setFieldValue("politicalTime", undefined);
},
},
},
{
name: "politicalTime",
label: "入党时间",
render: FORM_ITEM_RENDER_ENUM.DATE,
dependencies: ["politicalStatus"],
hidden: formValues => !(formValues.politicalStatus === "zhonggongdangyuan"),
},
{ name: "postId", label: "岗位名称(工种)" },
{
name: "isSocial",
label: "是否缴纳社保",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: {
onChange: () => {
form.setFieldValue("socialNumber", undefined);
form.setFieldValue("socSecurity", undefined);
},
},
},
{
name: "socialNumber",
label: "社会保障号码",
dependencies: ["isSocial"],
hidden: formValues => !(formValues.isSocial === "1"),
},
{
name: "socSecurity",
label: "社保卡照片",
render: ({ value, onChange }) => <Upload value={value} onChange={onChange} maxCount={2} />,
dependencies: ["isSocial"],
hidden: formValues => !(formValues.isSocial === "1"),
},
{
name: "isBf",
label: "是否缴纳保险",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "isSignLabor",
label: "是否签订劳动合同",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: {
onChange: () => {
form.setFieldValue("contract", undefined);
},
},
},
{
name: "contract",
label: "合同图片",
render: ({ value, onChange }) => <Upload value={value} onChange={onChange} maxCount={4} />,
dependencies: ["isSignLabor"],
hidden: formValues => !(formValues.isSignLabor === "1"),
},
{
name: "ispay",
label: "是否缴纳商业保险",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: {
onChange: () => {
form.setFieldValue("ispayNumber", undefined);
form.setFieldValue("insurance", undefined);
},
},
},
{
name: "ispayNumber",
label: "商业保险单号",
dependencies: ["ispay"],
hidden: formValues => !(formValues.ispay === "1"),
},
{
name: "insurance",
label: "保险图片",
render: ({ value, onChange }) => <Upload value={value} onChange={onChange} maxCount={4} />,
dependencies: ["ispay"],
hidden: formValues => !(formValues.ispay === "1"),
},
{
name: "isInjuriesPay",
label: "是否按期缴纳工伤保险",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: {
onChange: () => {
form.setFieldValue("isInjuriesPayTime", undefined);
form.setFieldValue("empInsurance", undefined);
},
},
},
{
name: "isInjuriesPayTime",
label: "工伤保险有效期",
dependencies: ["isInjuriesPay"],
render: FORM_ITEM_RENDER_ENUM.DATE,
hidden: formValues => !(formValues.isInjuriesPay === "1"),
},
{
name: "empInsurance",
label: "工伤保险凭证",
render: ({ value, onChange }) => <Upload value={value} onChange={onChange} maxCount={4} />,
dependencies: ["isInjuriesPay"],
hidden: formValues => !(formValues.isInjuriesPay === "1"),
},
{
name: "isLevelThree",
label: "是否参加三级安全培训",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: {
onChange: () => {
form.setFieldValue("threeLevel", undefined);
},
},
},
{
name: "threeLevel",
label: "三级安全培训照片",
render: ({ value, onChange }) => <Upload value={value} onChange={onChange} maxCount={4} />,
dependencies: ["isLevelThree"],
hidden: formValues => !(formValues.isLevelThree === "1"),
},
{
name: "isflow",
label: "是否流动人员",
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
},
{
name: "IS_SPECIAL_JOB",
label: "是否特殊工种",
required: false,
render: FORM_ITEM_RENDER_ENUM.RADIO,
items: WHETHER_ENUM,
componentProps: { disabled: true },
},
{
name: "alert",
span: 24,
customizeRender: true,
render: () => (<Alert message="新增完成后请提示该用户去相关方app端完善特种证书信息,特种证书完善后用户的'是否特殊工种'将变为'是'" type="error" />),
},
]}
/>
</div>
</>
);
}
export default Add;

View File

@ -0,0 +1,112 @@
import { Button, Form, message, Modal } from "antd";
import { useState } from "react";
import AddIcon from "zy-react-library/components/Icon/AddIcon";
import ImportIcon from "zy-react-library/components/Icon/ImportIcon";
import ImportFile from "zy-react-library/components/ImportFile";
import Search from "zy-react-library/components/Search";
import Table from "zy-react-library/components/Table";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useTable from "zy-react-library/hooks/useTable";
import LeftTree from "~/components/LeftTree";
export const PERSONNEL_TYPE_ENUM = [
{ id: "0", name: "非流动人员" },
{ id: "1", name: "流动人员" },
];
function List(props) {
const [importOpen, setImportOpen] = useState(false);
const [form] = Form.useForm();
const { tableProps, getData } = useTable(() => {}, { form });
const onImportFileConfirm = (values) => {
console.log(values);
message.success("导入成功");
};
const onResignation = (id) => {
Modal.confirm({
title: "提示",
content: "确定离职吗?",
onOk: () => {
message.success("离职成功");
getData();
},
});
};
const onResetPassword = (id) => {
Modal.confirm({
title: "提示",
content: "是否重置密码为Bb@123456789",
onOk: () => {
message.success("重置密码成功");
getData();
},
});
};
return (
<div style={{ padding: 20 }}>
<div style={{ display: "flex", gap: 20 }}>
<LeftTree />
<div style={{ flex: 1 }}>
<Search
labelCol={{ span: 8 }}
options={[
{ name: "name", label: "姓名" },
{ name: "name", label: "身份证" },
{
name: "name",
label: "人员类型",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: PERSONNEL_TYPE_ENUM,
},
{
name: "name",
label: "基础信息填报状态",
render: FORM_ITEM_RENDER_ENUM.SELECT,
items: [{ id: "0", name: "未填报" }, { id: "1", name: "已填报" }],
},
]}
form={form}
/>
<Table
toolBarRender={() => (
<>
<Button type="primary" icon={<AddIcon />} onClick={() => props.history.push("./add")}>新增</Button>
<Button type="primary" icon={<ImportIcon />} onClick={() => setImportOpen(true)}>导入</Button>
</>
)}
columns={[
{ title: "用户名", dataIndex: "name" },
{ title: "姓名", dataIndex: "name" },
{ title: "部门", dataIndex: "name" },
{ title: "人员类型", dataIndex: "name" },
{ title: "培训状态", dataIndex: "name" },
{ title: "基础信息填报状态", dataIndex: "name" },
{
title: "操作",
width: 300,
render: (_, record) => (
<>
<Button type="link" onClick={() => props.history.push(`./view?id=${record.id}`)}>查看</Button>
<Button type="link" onClick={() => props.history.push(`./add?id=${record.id}`)}>修改</Button>
<Button type="link" onClick={() => onResignation(record.id)}>离职</Button>
<Button type="link" onClick={() => onResetPassword(record.id)}>重置密码</Button>
</>
),
},
]}
{...tableProps}
dataSource={[{}]}
/>
</div>
</div>
<ImportFile
visible={importOpen}
templateUrl=""
onConfirm={onImportFileConfirm}
onCancel={() => { setImportOpen(false); }}
/>
</div>
);
}
export default List;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
function User(props) {
return (
<div>
{props.children}
</div>
);
}
export default User;

View File

@ -0,0 +1,9 @@
function Stakeholder(props) {
return (
<div>
{props.children}
</div>
);
}
export default Stakeholder;

View File

@ -0,0 +1,9 @@
function Supervision(props) {
return (
<div>
{props.children}
</div>
);
}
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>
);
}

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/"),
},
},
};