Commit 75150ad7 authored by rocosen's avatar rocosen

Merge branch 'feat-permissions' into staging

parents c0db760c aadd57cf
......@@ -11,4 +11,4 @@ RUN \
chmod 777 /var/log/nginx/nginx.pid
EXPOSE 10005
ENTRYPOINT ["nginx","-g","daemon off;"]
\ No newline at end of file
ENTRYPOINT ["nginx","-g","daemon off;"]
......@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"proxy": "",
"homepage": "/v3/",
"dependencies": {
"@babel/core": "^7.16.0",
"@emotion/react": "^11.9.0",
......@@ -89,6 +90,11 @@
"start:release-cn": "set \"REACT_APP_ENV=release-cn\" && npm start",
"start:release-en": "set \"REACT_APP_ENV=release-en\" && npm start",
"start": "node scripts/start.js",
"build:master": "node --max-old-space-size=6144 scripts/build-master.js",
"build:dev-cn": "node --max-old-space-size=6144 scripts/build-dev-cn.js",
"build:dev-en": "node --max-old-space-size=6144 scripts/build-dev-en.js",
"build:release-cn": "node --max-old-space-size=6144 scripts/build-release-cn.js",
"build:release-en": "node --max-old-space-size=6144 scripts/build-release-en.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
},
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 15:21:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:24
* @FilePath: /bkunyun/scripts/build-dev-cn.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "dev-cn";
const build = require("./build");
build();
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 10:18:28
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:29
* @FilePath: /bkunyun/scripts/build-dev-en.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "dev-en";
const build = require("./build");
build();
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 15:21:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:39
* @FilePath: /bkunyun/scripts/build-global.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "global";
const build = require("./build");
build();
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 15:21:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:45
* @FilePath: /bkunyun/scripts/build-master.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "master";
const build = require("./build");
build();
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 10:18:28
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:49
* @FilePath: /bkunyun/scripts/build-release-cn.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "release-cn";
const build = require("./build");
build();
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 15:21:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 15:21:59
* @FilePath: /bkunyun/scripts/build-release-en.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
process.env.REACT_APP_ENV = "release-en";
const build = require("./build");
build();
This diff is collapsed.
......@@ -2,13 +2,25 @@ import { BACKEND_API_URI_PREFIX } from "./api_prefix";
const RESTAPI = {
API_USER_FETCH: `${BACKEND_API_URI_PREFIX}/accounts/current`, //获取账户信息
// API_PRIVILEGE_LIST: `${BACKEND_API_URI_PREFIX}/routes/privilege/list`, //
API_PRIVILEGE_LIST: `${BACKEND_API_URI_PREFIX}/uaa/routes/privilege/list`, // 获取当前用户路由
API_PROJECT_LIST: `${BACKEND_API_URI_PREFIX}/cpp/project/list`, //获取产品下的项目列表
API_PROJECT_ADD: `${BACKEND_API_URI_PREFIX}/cpp/project/add`, //新增项目
API_PROJECT_UPDATE: `${BACKEND_API_URI_PREFIX}/cpp/project/update`, //新增项目
API_PROJECT_DELETE: `${BACKEND_API_URI_PREFIX}/cpp/project/delete`, //删除项目
API_PROJECT_GET: `${BACKEND_API_URI_PREFIX}/cpp/project/get`, //获取项目信息
API_CPCE_HPCZONE: `${BACKEND_API_URI_PREFIX}/cpp/cpce/hpczone`, //获取计算区列表
};
API_USER_PERMISSION_LIST: `${BACKEND_API_URI_PREFIX}/uaa/routes/privilege/list`,//获取用户包含的权限列表
API_WORKBENCH_TEMPLATE_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`,//查询项目下工作流模板列表
API_WORKBENCH_DELETE_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`,//项目管理员-删除工作流模板
API_WORKBENCH_ADD_TEMPLATE_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec`,//项目管理员-添加工作流模板-模板列表
API_WORKBENCH_ADD_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`,//项目管理员-添加工作流模板-提交
}
export default RESTAPI;
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-01 16:57:23
* @LastEditTime: 2022-06-10 11:16:16
* @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -11,7 +11,7 @@
// const PRIVATIZATION_API_URI_PREFIX = process.env.NODE_ENV === 'development' ? "http://123.57.131.31" : "";
let BACKEND_API_URI_PREFIX = "";
console.log('process.env.REACT_APP_ENV: ', process.env.REACT_APP_ENV)
console.log('process.env.REACT_APP_ENV: 11313', process.env.REACT_APP_ENV)
switch (process.env.REACT_APP_ENV) {
case "dev-cn":
BACKEND_API_URI_PREFIX = "http://47.57.4.97";
......
......@@ -10,7 +10,7 @@ function current() {
function menu() {
return request({
url: "/accounts/menu-mock",
url: Api.API_USER_PERMISSION_LIST,
method: "get",
});
}
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-09 14:52:54
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-09 14:55:49
* @FilePath: /bkunyun/src/api/routes_api.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import request from "@/utils/axios/service";
import Api from "./api_manager";
export const menu = () => {
return request({
url: Api.API_PRIVILEGE_LIST,
method: "get",
});
}
import request from "@/utils/axios/service";
import Api from "./api_manager";
function current() {
return request({
url: Api.API_USER_FETCH,
method: "get",
});
}
function menu() {
return request({
url: "/accounts/menu-mock",
method: "get",
});
}
type workflowspecTemplateParams = {
projectId: string;
title?: string;
};
// 查询项目下工作流模板列表
const getWorkbenchTemplate = (params: workflowspecTemplateParams) => {
return request({
url: Api.API_WORKBENCH_TEMPLATE_LIST,
method: "get",
params,
});
};
type workflowspecDeleteTemplateParams = {
projectId: string;
workflowSpecId: string;
};
// 项目管理员-删除工作流模板
const deleteWorkbenchTemplate = (params: workflowspecDeleteTemplateParams) => {
return request({
url: Api.API_WORKBENCH_DELETE_TEMPLATE,
method: "delete",
params,
});
};
type workflowspecGetAddTemplateParams = {
projectId?: string;
productId: string;
title?: string;
};
// 项目管理员-添加工作流模板-模板列表
const getAddWorkbenchTemplate = (params: workflowspecGetAddTemplateParams) => {
return request({
url: Api.API_WORKBENCH_ADD_TEMPLATE_LIST,
method: "get",
params,
});
};
type workflowspecAddTemplateParams = {
projectId: string;
workflowSpecIds: string[];
};
// 项目管理员-添加工作流模板-提交
const addWorkbenchTemplate = (params: workflowspecAddTemplateParams) => {
return request({
url: Api.API_WORKBENCH_ADD_TEMPLATE,
method: "post",
data: params,
});
};
export {
current,
menu,
getWorkbenchTemplate,
deleteWorkbenchTemplate,
getAddWorkbenchTemplate,
addWorkbenchTemplate
};
<?xml version="1.0" encoding="UTF-8"?>
<svg width="83px" height="70px" viewBox="0 0 83 70" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>切片</title>
<defs>
<polygon id="path-1" points="0 0 65.7607024 0 65.7607024 46.987 0 46.987"></polygon>
<linearGradient x1="50%" y1="20.7300519%" x2="50%" y2="102.568465%" id="linearGradient-3">
<stop stop-color="#E3F0FF" offset="0%"></stop>
<stop stop-color="#8CBAFF" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-4">
<stop stop-color="#CEE2F9" offset="0%"></stop>
<stop stop-color="#9FC0F0" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-5">
<stop stop-color="#DBEAFC" offset="0%"></stop>
<stop stop-color="#8AAFE6" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-6">
<stop stop-color="#DBEAFC" offset="0%"></stop>
<stop stop-color="#8AAFE6" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-7">
<stop stop-color="#F2F7FF" offset="0%"></stop>
<stop stop-color="#E1EDFF" offset="100%"></stop>
</linearGradient>
<path d="M17.9695,0 C18.1602024,0 18.3370714,0.101 18.435881,0.267 L18.435881,0.267 L22.5265952,7.169 C22.6254048,7.335 22.8022738,7.436 22.9929762,7.436 L22.9929762,7.436 L42.7677262,7.436 C42.9584286,7.436 43.1352976,7.335 43.233119,7.169 L43.233119,7.169 L47.3258095,0.267 C47.423631,0.101 47.6005,0 47.7912024,0 L47.7912024,0 L65.21725,0 C65.517631,0 65.7607024,0.246 65.7607024,0.55 L65.7607024,0.55 L65.7607024,18.864 C65.7607024,19.534 65.2231786,20.078 64.5611548,20.078 L64.5611548,20.078 L1.19855952,20.078 C0.536535714,20.078 0,19.534 0,18.864 L0,18.864 L0,0.55 C0,0.246 0.243071429,0 0.542464286,0 L0.542464286,0 Z M41.7340798,12.3811 L24.0274131,12.3811 C23.5254607,12.3811 23.1193536,12.7931 23.1193536,13.3001 C23.1193536,13.8081 23.5254607,14.2191 24.0274131,14.2191 L24.0274131,14.2191 L41.7340798,14.2191 C42.235044,14.2191 42.6421393,13.8081 42.6421393,13.3001 C42.6421393,12.7931 42.235044,12.3811 41.7340798,12.3811 L41.7340798,12.3811 Z" id="path-8"></path>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工作台(子用户)" transform="translate(-789.000000, -511.000000)">
<g id="编组-6" transform="translate(788.000000, 511.000000)">
<g id="img_no-data" transform="translate(1.000000, 0.000000)">
<g transform="translate(8.645833, 6.999500)">
<g id="编组" transform="translate(0.000000, 8.970200)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<path d="M49.3205762,0 L32.8806476,0 L16.440719,0 L0.257695238,26.488 C0.0897190476,26.764 -0.000197619048,27.081 -0.000197619048,27.405 L-0.000197619048,45.323 C-0.000197619048,45.689 1.28235,46.987 1.64498095,46.987 L32.8806476,46.987 L64.1173024,46.987 C64.4789452,46.987 65.7614929,45.689 65.7614929,45.323 L65.7614929,27.405 C65.7614929,27.081 65.6725643,26.764 65.5036,26.488 L49.3205762,0 Z" id="Fill-1" fill="url(#linearGradient-3)" mask="url(#mask-2)"></path>
</g>
<polygon id="Fill-3" fill="url(#linearGradient-4)" points="32.880944 8.5034 16.4400274 8.5034 16.4400274 18.3434 32.880944 18.3434 49.3208726 18.3434 49.3208726 8.5034"></polygon>
<path d="M1.25705476,53.0815 L16.4401262,18.3435 L16.4401262,8.5035 L0.250185714,35.4635 C0.0861619048,35.7355 0.000197619048,36.0495 0.000197619048,36.3675 L0.000197619048,52.8125 C0.000197619048,53.5315 0.969519048,53.7385 1.25705476,53.0815" id="Fill-5" fill="url(#linearGradient-5)"></path>
<path d="M64.5048333,53.0815 L49.3207738,18.3435 L49.3207738,8.5035 L65.5117024,35.4635 C65.6747381,35.7355 65.7607024,36.0495 65.7607024,36.3675 L65.7607024,52.8125 C65.7607024,53.5315 64.791381,53.7385 64.5048333,53.0815" id="Fill-7" fill="url(#linearGradient-6)"></path>
<g id="编组" transform="translate(0.000198, 35.880000)">
<mask id="mask-9" fill="white">
<use xlink:href="#path-8"></use>
</mask>
<use id="形状结合" fill="url(#linearGradient-7)" xlink:href="#path-8"></use>
</g>
<line x1="13.3284167" y1="4.812" x2="10.3582024" y2="0" id="Stroke-13" stroke="#C2DAFE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></line>
<line x1="16.1112881" y1="4.5181" x2="17.7248476" y2="0.0531" id="Stroke-15" stroke="#C2DAFE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></line>
<line x1="11.8462738" y1="7.2143" x2="7.17357143" y2="6.7233" id="Stroke-17" stroke="#C2DAFE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></line>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -56,7 +56,7 @@ const MyRouter = observer(() => {
);
return (
<BrowserRouter>
<BrowserRouter basename={"/v3"}>
<Routes>{setRoutes(routes)}</Routes>
</BrowserRouter>
);
......
import { useStores } from "@/store/index";
import { elements } from "@/router";
import { current, menu } from "@/api/demo_api";
import { current, } from "@/api/demo_api";
import { product } from "@/api/project_api";
import localStorageKey from "@/utils/localStorageKey";
import NotFound from "@/views/404";
import useMyRequest from "@/hooks/useMyRequest";
import { useEffect } from "react";
import { menu } from "@/api/routes_api";
const useMyRouter = () => {
const { permissionStore, menuStore, currentProjectStore } = useStores();
......
......@@ -13,6 +13,7 @@ type ButtonTagProps = {
fontSize?: string;
dropValue?: boolean;
drop?: boolean;
color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning" | undefined,
}
......@@ -35,6 +36,7 @@ const ButtonComponent = (props: ButtonTagProps) => {
<>
<Button
variant={props.variant || 'contained'}
color={props.color || "primary"}
disableRipple={true}
disableFocusRipple={true}
classes={{
......
......@@ -2,33 +2,74 @@ import { operation, route } from "@/router";
import { useStores } from "@/store";
import { useCallback } from "react";
const roleList: any[] = [
{ VIEWER: 1 },
{ USER: 2 },
{ MANAGER: 3 },
{ OWNER: 4 }
]
const usePass = () => {
const { permissionStore } = useStores();
const { currentProjectStore } = useStores();
const isPass = useCallback(
(key: string, routes?: Array<route | operation>): boolean => {
if (routes) {
for (let item of routes) {
if (item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, item.children)
) {
return true;
(key: string, role?: "VIEWER" | "USER" | "MANAGER" | "OWNER", routes?: Array<route | operation>): boolean => {
let code = currentProjectStore && currentProjectStore.currentProjectInfo.projectRole
if (role) {
if (code && roleList.filter(e => e[role])[0][role] <= roleList.filter(e => e[code as string])[0][code]) {
if (routes) {
for (let item of routes) {
if (item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, role, item.children)
) {
return true;
}
}
} else {
for (let item of permissionStore.allRoutes) {
if (item.type !== "navigate" && item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, role, item.children)
) {
return true;
}
}
}
} else {
return false
}
} else {
for (let item of permissionStore.allRoutes) {
if (item.type !== "navigate" && item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, item.children)
) {
return true;
if (routes) {
for (let item of routes) {
if (item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, role, item.children)
) {
return true;
}
}
} else {
for (let item of permissionStore.allRoutes) {
if (item.type !== "navigate" && item.id === key) {
return true;
} else if (
item.type === "page" &&
item.children?.length &&
isPass(key, role, item.children)
) {
return true;
}
}
}
}
......
......@@ -8,19 +8,33 @@ import { stores } from "@/store/index";
import { MySnackbarProvider } from "@/components/MySnackbar";
import "@/mocks/index";
import './assets/style/public.css'
import { createTheme, ThemeProvider, styled } from '@mui/material/styles';
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
const theme = createTheme({
typography: {
fontFamily: ['Roboto', 'Helvetica', 'Tahoma', 'Arial', '"PingFang SC"', '"Hiragino Sans GB"', '"Heiti SC"', '"WenQuanYi Micro Hei"', 'sans-serif', '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"'].join(','),
},
palette: {
primary: { main: '#136EFA' },
secondary: { main: '#4EB9FB' }
}
});
root.render(
<React.StrictMode>
<Provider {...stores}>
<MySnackbarProvider
alertSx={{ boxShadow: "0px 2px 4px 0px rgb(0 0 0 / 8%)" }}
>
<MyRouter></MyRouter>
</MySnackbarProvider>
</Provider>
<ThemeProvider theme={theme}>
<Provider {...stores}>
<MySnackbarProvider
alertSx={{ boxShadow: "0px 2px 4px 0px rgb(0 0 0 / 8%)" }}
>
<MyRouter></MyRouter>
</MySnackbarProvider>
</Provider>
</ThemeProvider>
</React.StrictMode>
);
......
......@@ -14,6 +14,7 @@ import * as React from "react";
import NotFound from "@/views/404";
import Demo from "@/views/demo";
import ProjectSetting from "@/views/Project/ProjectSetting";
import ProjectWorkbench from "@/views/Project/ProjectWorkbench";
export type route = {
id?: string;
......@@ -47,6 +48,7 @@ export const elements: {
} = {
Demo: Demo,
ProjectSetting: ProjectSetting,
ProjectWorkbench:ProjectWorkbench
};
export const routes: Array<route | navigate> = [
......
......@@ -3,6 +3,7 @@ type projectInfo = {
id?: string;
name?: string;
desc?: string;
projectRole?: string;
};
type productInfo = {
......
/*
* @Author: rocosen
* @Date: 2022-06-12 10:05:13
* @LastEditors: rocosen
* @LastEditTime: 2022-06-07 20:23:02
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useState, useMemo, useEffect } from "react";
import { Box } from "@mui/system";
import { useStores } from "@/store/index";
import NoProject from "@/components/NoProject";
import { observer } from "mobx-react-lite";
import projectImg from "@/assets/project/projectIconSmall.svg";
import WorkbenchTemplate from "./workbenchTemplate";
import WorkbenchList from "./workbenchList";
import Tabs from "@/components/mui/Tabs";
import usePass from "@/hooks/usePass";
const ProjectWorkbench = observer(() => {
const { currentProjectStore } = useStores();
const isPass = usePass();
const [value, setValue] = useState("workbenchTemplate");
useEffect(() => {
console.log(isPass("PROJECT_WORKBENCH_FLOES_USE",'USER'), "11111111111");
}, [])
const tabList = useMemo(() => {
return [
{
label: "工作流模版",
value: "workbenchTemplate",
component: <WorkbenchTemplate />,
},
{
label: "任务列表",
value: "workbenchList",
component: <WorkbenchList />,
},
];
}, []);
const changeTabs = (val: string) => {
setValue(val);
};
return (
<div style={{ padding: 24 }}>
<div style={{ display: "flex", alignItems: "center" }}>
<img src={projectImg} alt="项目logo" />
<span style={{ marginLeft: 12 }}>
工作台
</span>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs value={value} onChange={changeTabs} tabList={tabList} />
</Box>
</div>
);
});
export default memo(ProjectWorkbench);
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-07 21:39:30
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import _ from "lodash";
import { IResponse, useHttp } from "@/api/http";
import { useStores } from "@/store";
const ProjectMembers = () => {
const http = useHttp();
const { currentProjectStore } = useStores();
useEffect(() => {
}, []);
return (
<>
99999
</>
);
};
export default memo(ProjectMembers);
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css";
import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button";
import Dialog from "@/components/mui/Dialog";
import OutlinedInput from "@mui/material/OutlinedInput";
import SearchIcon from "@mui/icons-material/Search";
import Checkbox from '@mui/material/Checkbox';
import CloseOutlinedIcon from '@mui/icons-material/CloseOutlined';
import _ from "lodash";
const AddTemplate = (props: any) => {
const { openAddTemplate, closeAddTemplateBlock, addTemplateList, templateSelectCallback, selectTemplateData, addTemplateCallback, searchTemplateNameCallback } = props;
return (
<Box className={styles.addTemplateMask} sx={{ display: openAddTemplate ? 'flex' : 'none' }} >
<Box sx={{ height: '50px', display: 'flex', alignItems: 'center' }} >
<CloseOutlinedIcon sx={{ color: "#ffffff", marginRight: "10px", cursor: "pointer" }} onClick={() => {
closeAddTemplateBlock()
}} />
</Box>
<Box className={styles.addTemplateBlock}>
<Box sx={{ padding: "24px 32px" }}>
<Typography sx={{ fontSize: '18px', fontWeight: '600', color: "#1E2633" }}>添加工作流模版</Typography>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: "20px" }}>
<OutlinedInput
onChange={(e: any) => {
_.debounce(() => {
searchTemplateNameCallback(e.target.value)
}, 200)();
}}
placeholder="输入关键词搜索"
size="small"
sx={{ width: 340, height: 32, marginTop: "20px" }}
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/>
<Button
style={{ backgroundColor: "#1370FF", marginLeft: "12px" }}
variant="contained"
onClick={addTemplateCallback}
size="small"
>
添加模版{selectTemplateData.length === 0 ? "" : `(${selectTemplateData.length})`}
</Button>
</Box>
<Box sx={{ display: "flex", flexWrap: 'wrap', overflowX: 'hidden', overflowY: 'overlay', marginLeft: '-8px' }} >
{
addTemplateList.map((item: any, key: any) => {
return (
<Box className={styles.addTemplateBox} onClick={() => {
templateSelectCallback(item.id)
}}
sx={{ border: selectTemplateData.includes(item.id) ? '1px solid #1370FF' : "1px solid #EBEDF0;" }}
>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', }}>
<Typography sx={{ fontSize: '14px', fontWeight: '600', color: '#1E2633', marginBottom: "4px", overflow: 'hidden', textOverflow: 'ellipsis' }}>{item.title}</Typography>
<Checkbox size="small" sx={{ padding: "0px" }} checked={selectTemplateData.includes(item.id)} />
</Box>
<Box sx={{ display: 'flex', marginBottom: "8px" }}>
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF', marginRight: "24px" }}>版本:{item.version}</Typography>
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF' }}>更新时间:{item.updateTime}</Typography>
</Box>
<Typography className={styles.templateDescText} >{item.description}</Typography>
</Box>
)
})
}
</Box>
</Box>
</Box>
</Box>
);
};
export default memo(AddTemplate);
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css";
import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button";
import Dialog from "@/components/mui/Dialog";
const SimpleDialog = (props: any) => {
const { openDialog, closeDialog, onConfirm, text, title } = props;
return (
< >
<Dialog
open={openDialog}
onClose={closeDialog}
onConfirm={onConfirm}
title={title}
>
<Box>
<Typography sx={{ fontSize: '14px', fontWeight: '400' }}>{text}</Typography>
</Box>
</Dialog>
</>
);
};
export default memo(SimpleDialog);
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css";
import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button";
import usePass from "@/hooks/usePass";
const TemplateBox = (props: any) => {
const info = props.data
const isPass = usePass();
return (
<Box className={styles.templateBlock} >
<Box>
<Typography sx={{ fontSize: '14px', fontWeight: '600', color: '#1E2633', marginBottom: "4px", overflow: 'hidden', textOverflow: 'ellipsis' }}>{info.title}</Typography>
<Box sx={{ display: 'flex', marginBottom: "8px" }} >
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF', marginRight: "24px" }}>版本:{info.version}</Typography>
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF' }}>更新时间:{info.updateTime}</Typography>
</Box>
<Typography className={styles.templateDescText} >{info.description}</Typography>
</Box>
<Box sx={{
display: 'flex', justifyContent: 'end'
}} >
{
isPass("PROJECT_WORKBENCH_FLOES_USE", 'MANAGER') && <Button
style={{ backgroundColor: "#F0F2F5", color: "#565C66" }}
variant="contained"
onClick={() => { props.startDialog(info.id) }}
size="small"
>
删除模版
</Button>
}
{
isPass("PROJECT_WORKBENCH_FLOES_USE", 'USER') && <Button
style={{ backgroundColor: "#1370FF", marginLeft: "12px" }}
variant="contained"
// onClick={addTemplateBlock}
size="small"
>
使用模版
</Button>
}
</Box>
</Box>
);
};
export default memo(TemplateBox);
.headerBox {
/* display: flex;
justify-content: space-between;
align-items: center; */
margin-bottom: 20px;
}
.removeItemBox {
color: #ff4e4e;
margin-left: 32px;
cursor: pointer;
}
.tabBox {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24px;
}
.templateBlock {
width: 21.4876%;
height: 160px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #EBEDF0;
padding: 16px 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 8px;
}
.addTemplateMask {
background: rgb(56, 56, 56, 0.7);
position: absolute;
z-index: 800;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
display: flex;
align-items: end;
flex-direction: column;
}
.addTemplateBlock {
background: #FFFFFF;
z-index: 900;
border-radius: 16px 0px 0px 0px;
height: 100%;
width: 100%;
}
.addTemplateBox {
width: 16.8751%;
height: 114px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #F0F2F5;
padding: 16px 20px;
margin: 8px;
cursor: pointer;
}
.addTemplateBox:hover {
box-shadow: 6px 8px 22px 0px rgba(0, 24, 57, 0.08);
}
.templateDescText {
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
display: -webkit-box;
height: 54px;
font-size: 12px !important;
font-weight: 400 !important;
color: #8A9099 !important;
}
.addNewTemplate {
width: 380px;
height: 194px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #EBEDF0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
cursor: pointer;
}
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-07 21:39:30
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import { Box, Typography } from "@mui/material";
import styles from "./index.module.css";
import OutlinedInput from "@mui/material/OutlinedInput";
import SearchIcon from "@mui/icons-material/Search";
// import Button from "@/components/mui/Button";
import Button from "@mui/material/Button";
import Add from "@mui/icons-material/Add";
import useMyRequest from "@/hooks/useMyRequest";
import TemplateBox from "./components/templateBox"
import SimpleDialog from "./components/simpleDialog"
import AddTemplate from "./components/addTemplate"
import noData from '../../../../assets/project/noTemplate.svg'
import {
getWorkbenchTemplate,
deleteWorkbenchTemplate,
getAddWorkbenchTemplate,
addWorkbenchTemplate
} from "@/api/workbench_api";
import _ from "lodash";
import { IResponse, useHttp } from "@/api/http";
import { useStores } from "@/store";
import usePass from "@/hooks/usePass";
const ProjectMembers = () => {
const { currentProjectStore } = useStores();
const isPass = usePass();
/** 搜索模板名称 */
const [templateName, setTemplateName] = useState("");
/** 模板列表 */
const [templateList, setTemplateList] = useState([]);
/** 选中的模板id */
const [templateId, setTemplateId] = useState('');
/** 简单弹窗(删除模板) */
const [openDialog, setOpenDialog] = useState(false);
/** 增加模板 */
const [openAddTemplate, setOpenAddTemplate] = useState(false);
/** 可增加模板列表 */
const [addTemplateList, setAddTemplateList] = useState([]);
/** 已选择增加的模板列表 */
const [selectTemplateData, setSelectTemplateData] = useState<string[]>([]);
// 获取模板列表
const { run: getTemplateInfo } = useMyRequest(getWorkbenchTemplate, {
onSuccess: (result: any) => {
setTemplateList(result.data);
},
});
// 删除模板
const { run: delTemplate } = useMyRequest(deleteWorkbenchTemplate, {
onSuccess: (result: any) => {
setOpenDialog(false);
getTemplateInfo({
projectId: currentProjectStore.currentProjectInfo.id as string,
title: templateName
});
},
});
// 添加工作流模板-获取模板列表
const { run: getAddTemplateList } = useMyRequest(getAddWorkbenchTemplate, {
onSuccess: (result: any) => {
setAddTemplateList(result.data)
setOpenAddTemplate(true);
},
});
// 项目管理员-添加工作流模板-提交
const { run: addTemplate } = useMyRequest(addWorkbenchTemplate, {
onSuccess: (result: any) => {
setOpenAddTemplate(false)
getTemplateInfo({
projectId: currentProjectStore.currentProjectInfo.id as string,
});
setSelectTemplateData([])
},
});
useEffect(() => {
getTemplateInfo({
projectId: currentProjectStore.currentProjectInfo.id as string,
});
}, [currentProjectStore.currentProjectInfo.id, getTemplateInfo]);
/** 点击添加工作流模版 */
const onAddMember = () => {
// setAddMemberDialog(true);
};
/** 删除模板 */
const deleteTemplate = () => {
delTemplate({
projectId: currentProjectStore.currentProjectInfo.id as string,
workflowSpecId: templateId,
})
};
/** 打开弹窗 */
const startDialog = (id: string) => {
setTemplateId(id)
setOpenDialog(true);
};
/** 关闭弹窗 */
const closeDialog = () => {
setOpenDialog(false);
};
/** 增加模板 */
const addTemplateBlock = () => {
getAddTemplateList({
projectId: currentProjectStore.currentProjectInfo.id as string,
productId: 'cadd',
})
};
/** 关闭增加模板 */
const closeAddTemplateBlock = () => {
setOpenAddTemplate(false);
setSelectTemplateData([])
};
/** 增加模板操作 */
const addTemplateCallback = () => {
addTemplate({
projectId: currentProjectStore.currentProjectInfo.id as string,
workflowSpecIds: selectTemplateData
})
}
/** 搜索模板 */
const searchTemplateNameCallback = (data: any) => {
getAddTemplateList({
projectId: currentProjectStore.currentProjectInfo.id as string,
productId: 'cadd',
title: data
})
}
const templateSelectCallback = (data: string) => {
let list: string[] = [...selectTemplateData]
if (selectTemplateData.filter(e => e === data).length > 0) {
list = list.filter(e => e !== data)
setSelectTemplateData(list)
} else {
list.push(data)
setSelectTemplateData(list)
}
}
useEffect(() => {
getTemplateInfo({
projectId: currentProjectStore.currentProjectInfo.id as string,
title: templateName
});
}, [templateName]);
return (
<Box className={styles.headerBox}>
<Box className={styles.tabBox} >
<OutlinedInput
onChange={(e: any) => {
_.debounce(() => {
setTemplateName(e.target.value);
}, 200)();
}}
placeholder="输入关键词搜索"
size="small"
sx={{ width: 340, height: 32 }}
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/>
{
templateList.length > 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && <Button
style={{ backgroundColor: "#1370FF " }}
variant="contained"
onClick={addTemplateBlock}
startIcon={<Add />}
size="small"
>
添加工作流模版
</Button>
}
</Box>
{
templateList.length === 0 && !isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') &&
<Box sx={{
display: 'flex', alignItems: 'center', flexDirection: 'column', minHeight: 'calc(100vh - 376px)',
justifyContent: 'center'
}}>
<img alt="" src={noData} />
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#8A9099' }}>暂未开启模版</Typography>
</Box>
}
{
templateList.length > 0 && <Box sx={{ display: "flex", flexWrap: 'wrap', marginLeft: "-8px" }} >
{
templateList && templateList.length > 0 && templateList.map((item, key) => {
return <TemplateBox data={item} startDialog={startDialog} />
})
}
</Box>
}
{
templateList.length === 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && <Box className={styles.addNewTemplate}
onClick={addTemplateBlock}
>
<Add sx={{ color: "#565C66", fontSize: "20px", width: "30px", height: '30px' }} />
<Typography sx={{ fontSize: '14px', fontWeight: '400', color: '#8A9099', marginTop: "15px" }}>添加工作流模版</Typography>
</Box>
}
<AddTemplate
openAddTemplate={openAddTemplate}
closeAddTemplateBlock={closeAddTemplateBlock}
addTemplateList={addTemplateList}
templateSelectCallback={templateSelectCallback}
selectTemplateData={selectTemplateData}
addTemplateCallback={addTemplateCallback}
searchTemplateNameCallback={searchTemplateNameCallback}
/>
<SimpleDialog
text={'确认移除该模板吗?'}
title={'删除模板'}
openDialog={openDialog}
closeDialog={closeDialog}
onConfirm={deleteTemplate}
/>
</Box>
);
};
export default memo(ProjectMembers);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment