Commit 5a2792a8 authored by wuyongsheng's avatar wuyongsheng

Merge branch 'feat-jobList' into 'staging'

Feat job list

See merge request !69
parents bbda7197 a76e2c1e
...@@ -11838,7 +11838,7 @@ ...@@ -11838,7 +11838,7 @@
}, },
"webpack-dev-server": { "webpack-dev-server": {
"version": "4.9.0", "version": "4.9.0",
"resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-4.9.0.tgz", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.0.tgz",
"integrity": "sha512-+Nlb39iQSOSsFv0lWUuUTim3jDQO8nhK3E68f//J2r5rIcp4lULHXz2oZ0UVdEeWXEh5lSzYUlzarZhDAeAVQw==", "integrity": "sha512-+Nlb39iQSOSsFv0lWUuUTim3jDQO8nhK3E68f//J2r5rIcp4lULHXz2oZ0UVdEeWXEh5lSzYUlzarZhDAeAVQw==",
"requires": { "requires": {
"@types/bonjour": "^3.5.9", "@types/bonjour": "^3.5.9",
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"homepage": "/v3/", "homepage": "/v3/",
"dependencies": { "dependencies": {
"@babel/core": "^7.16.0", "@babel/core": "^7.16.0",
"@emotion/react": "^11.9.0", "@emotion/react": "^11.9.3",
"@emotion/styled": "^11.8.1", "@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.6.2", "@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.84", "@mui/lab": "^5.0.0-alpha.84",
...@@ -77,14 +77,15 @@ ...@@ -77,14 +77,15 @@
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"tailwindcss": "^3.0.2", "tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5", "terser-webpack-plugin": "^5.2.5",
"tss-react": "^3.7.0",
"tus-js-client": "2.1.1",
"typescript": "^4.6.4", "typescript": "^4.6.4",
"use-immer": "^0.7.0", "use-immer": "^0.7.0",
"web-vitals": "^2.1.4", "web-vitals": "^2.1.4",
"webpack": "^5.64.4", "webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0", "webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2", "webpack-manifest-plugin": "^4.0.2",
"workbox-webpack-plugin": "^6.4.1", "workbox-webpack-plugin": "^6.4.1"
"tus-js-client": "2.1.1"
}, },
"scripts": { "scripts": {
"start:master": "set \"REACT_APP_ENV=master\" && npm start", "start:master": "set \"REACT_APP_ENV=master\" && npm start",
......
...@@ -21,12 +21,25 @@ const RESTAPI = { ...@@ -21,12 +21,25 @@ const RESTAPI = {
API_DATA_FIND: `${BACKEND_API_URI_PREFIX}/cpp/data/find`, //查询某路径下数据集 API_DATA_FIND: `${BACKEND_API_URI_PREFIX}/cpp/data/find`, //查询某路径下数据集
API_DATA_SEARCH: `${BACKEND_API_URI_PREFIX}/cpp/data/search`, //搜索项目中某路径下的数据集 API_DATA_SEARCH: `${BACKEND_API_URI_PREFIX}/cpp/data/search`, //搜索项目中某路径下的数据集
API_DATA_MOVE: `${BACKEND_API_URI_PREFIX}/cpp/data/move`, //移动到 API_DATA_MOVE: `${BACKEND_API_URI_PREFIX}/cpp/data/move`, //移动到
API_DATA_MOVE_PACKAGE: `${BACKEND_API_URI_PREFIX}/cpp/data/move/package`, //移动文件夹中的数据集
API_DATA_DEL: `${BACKEND_API_URI_PREFIX}/cpp/data/del`, //删除项目中的数据集 API_DATA_DEL: `${BACKEND_API_URI_PREFIX}/cpp/data/del`, //删除项目中的数据集
API_DATA_DEL_PACKAGE: `${BACKEND_API_URI_PREFIX}/cpp/data/del/package`, //删除文件夹中的数据集
API_USER_PERMISSION_LIST: `${BACKEND_API_URI_PREFIX}/uaa/routes/privilege/list`, //获取用户包含的权限列表 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_TEMPLATE_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //查询项目下工作流模板列表
API_WORKBENCH_DELETE_TEMPLATE: `${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_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec`, //项目管理员-添加工作流模板-模板列表
API_WORKBENCH_ADD_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`,//项目管理员-添加工作流模板-提交 API_WORKBENCH_ADD_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //项目管理员-添加工作流模板-提交
}
API_WORKBENCH_WORKFLOWJOB_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowjob`, //查询工作流任务
API_WORKBENCH_DEL_WORKFLOWJOB: `${BACKEND_API_URI_PREFIX}/cpp/workflow/job/`, //删除工作流任务
API_WORKBENCH_CANCEL_WORKFLOWJOB: `${BACKEND_API_URI_PREFIX}/cpp/workflow/cancel`, //取消工作流
};
export default RESTAPI; export default RESTAPI;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48 * @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-13 09:59:45 * @LastEditTime: 2022-06-16 20:22:37
* @FilePath: /bkunyun/src/api/api_prefix.ts * @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -32,7 +32,7 @@ switch (process.env.REACT_APP_ENV) { ...@@ -32,7 +32,7 @@ switch (process.env.REACT_APP_ENV) {
if (["www.bkunyun.com"].includes(window.location.host)) { if (["www.bkunyun.com"].includes(window.location.host)) {
BACKEND_API_URI_PREFIX = "https://www.bkunyun.com"; BACKEND_API_URI_PREFIX = "https://www.bkunyun.com";
} else { } else {
BACKEND_API_URI_PREFIX = "http://47.57.4.97"; BACKEND_API_URI_PREFIX = "http://47.75.104.171";
} }
break; break;
} }
......
...@@ -106,10 +106,12 @@ class CloudEController { ...@@ -106,10 +106,12 @@ class CloudEController {
if (getLoaclStorageOfKey("userinfo")) { if (getLoaclStorageOfKey("userinfo")) {
url = urlToken(filetoken, projectId) + "&q=" + url; url = urlToken(filetoken, projectId) + "&q=" + url;
} }
return axios return axios.get(
.get(APIOPTION() + "/search" + base + url + "&showhidden=" + showHide, { APIOPTION() + "/search" + base + url + "&showhidden=" + showHide,
headers: headers, {
}) headers: headers,
}
);
} }
} }
...@@ -170,5 +172,26 @@ class CloudEController { ...@@ -170,5 +172,26 @@ class CloudEController {
}); });
} }
} }
// 文件下载
static JobFileDownload(url: any, filetoken: string, projectId: string) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
url = url + urlToken(filetoken, projectId);
headers["Content-Type"] = "multipart/form-data";
const div = document.createElement("div");
const elink: any = document.createElement("a");
elink.style.display = "none";
elink.href = APIOPTION() + "/download" + url;
document.body.appendChild(div);
div.appendChild(elink);
div.addEventListener("click", (event) => {
event.stopPropagation();
});
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
div.removeChild(elink);
document.body.removeChild(div);
}
}
} }
export default CloudEController; export default CloudEController;
...@@ -2,29 +2,6 @@ ...@@ -2,29 +2,6 @@
// const APIOPTION = "https://fileserver.cloudam.cn" // const APIOPTION = "https://fileserver.cloudam.cn"
// const APIPORT = "39.105.230.38" // const APIPORT = "39.105.230.38"
import { getLoaclStorageOfKey } from "./utils"; import { getLoaclStorageOfKey } from "./utils";
// const raysyncAddr = {
// bandwidth: null
// capacity: 10485760
// enableLargeFileTransfer: true
// fileServerEndPoint: "https://fileserver.cloudam.cn"
// fileSystemType: "standard"
// jobLogServerEndPoint: "https://fileserver.cloudam.cn:6677"
// privateIp: "10.8.2.67"
// protocolType: "NFS"
// publicMountDir: "/public"
// publicMountUrl: "132594ad6e-atf93.cn-beijing.nas.aliyuncs.com"
// ramUserId: "61261f8a2a2aa4d72f752c3c"
// smbMountUrl: null
// srcAddr: "fileserver.cloudam.cn"
// srcIp: "47.94.198.50"
// sshServerEndPoint: "https://fileserver.cloudam.cn:8888"
// storageType: "Capacity"
// token: null
// userMountDir: "/public/data/"
// userMountUrl: "132594ad6e-uop2.cn-beijing.nas.aliyuncs.com"
// vncServerEndPoint: "https://fileserver.cloudam.cn:9090"
// zoneId: "cn-beijing-h"
// }
const API = function () { const API = function () {
const raysyncAddr = getLoaclStorageOfKey("raysyncAddr"); const raysyncAddr = getLoaclStorageOfKey("raysyncAddr");
...@@ -50,38 +27,6 @@ const APIPORT = function () { ...@@ -50,38 +27,6 @@ const APIPORT = function () {
return raysyncAddr.srcIp || ""; return raysyncAddr.srcIp || "";
}; };
// const currentRegion = {
// cloudProvider: "ALIYUN"
// description: "本计算区有丰富的CPU资源,并提供部分GPU资源,可以满足大部分计算作业需求。"
// enabled: true
// id: "CE-Z1"
// initialized: true
// location: "CLOUD"
// name: "通用计算区"
// primary: true
// storageConfig: {srcAddr: "fileserver.cloudam.cn", srcIp: "47.94.198.50", privateIp: "10.8.2.67",…}
// bandwidth: null
// capacity: 10485760
// enableLargeFileTransfer: true
// fileServerEndPoint: "https://fileserver.cloudam.cn"
// fileSystemType: "standard"
// jobLogServerEndPoint: "https://fileserver.cloudam.cn:6677"
// privateIp: "10.8.2.67"
// protocolType: "NFS"
// publicMountDir: "/public"
// publicMountUrl: "132594ad6e-atf93.cn-beijing.nas.aliyuncs.com"
// ramUserId: "61261f8a2a2aa4d72f752c3c"
// smbMountUrl: null
// srcAddr: "fileserver.cloudam.cn"
// srcIp: "47.94.198.50"
// sshServerEndPoint: "https://fileserver.cloudam.cn:8888"
// storageType: "Capacity"
// token: null
// userMountDir: "/public/data/"
// userMountUrl: "132594ad6e-uop2.cn-beijing.nas.aliyuncs.com"
// vncServerEndPoint: "https://fileserver.cloudam.cn:9090"
// zoneId: "cn-beijing-h"
// }
// 当前计算区 // 当前计算区
let currentRegion = localStorage.getItem("current-region"); let currentRegion = localStorage.getItem("current-region");
let currentRegionJson = currentRegion && JSON.parse(currentRegion); let currentRegionJson = currentRegion && JSON.parse(currentRegion);
...@@ -114,31 +59,6 @@ const urlToken = (filetoken: string, projectId: string) => { ...@@ -114,31 +59,6 @@ const urlToken = (filetoken: string, projectId: string) => {
return `?username=${projectId}&token=${token}&filetoken=${encodeURIComponent( return `?username=${projectId}&token=${token}&filetoken=${encodeURIComponent(
filetoken filetoken
)}&share=false&project=true`; )}&share=false&project=true`;
// let json = getLoaclStorageOfKey("current-region");
// const userInfo = getLoaclStorageOfKey("userinfo");
// if (json["location"] && json["location"] === "ON_PREMISE") {
// return `?username=${
// userInfo["name"]
// }&token=${token}&filetoken=${encodeURIComponent(filetoken)}&share=false`; // 之前的filetoken是: userInfo["shareFileAccessToken"]
// }
// if (root && root === "home") {
// return `?username=${
// userInfo["homeDirectoryMountPoint"]
// }&token=${token}&filetoken=${encodeURIComponent(filetoken)}&share=false`;
// }
// // 是否共有文件系统
// if (
// localStorage.getItem("isShareFileSystem") &&
// localStorage.getItem("isShareFileSystem") === "true"
// ) {
// return `?username=${
// userInfo["shareDirectoryMountPoint"]
// }&token=${token}&filetoken=${encodeURIComponent(filetoken)}&share=true`;
// } else {
// return `?username=${
// userInfo["homeDirectoryMountPoint"]
// }&token=${token}&filetoken=${encodeURIComponent(filetoken)}&share=false`;
// }
}; };
const getUuid = () => { const getUuid = () => {
...@@ -195,3 +115,60 @@ export { ...@@ -195,3 +115,60 @@ export {
encryptTransfer, encryptTransfer,
getType, getType,
}; };
// mock 数据
// const raysyncAddr = {
// bandwidth: null
// capacity: 10485760
// enableLargeFileTransfer: true
// fileServerEndPoint: "https://fileserver.cloudam.cn"
// fileSystemType: "standard"
// jobLogServerEndPoint: "https://fileserver.cloudam.cn:6677"
// privateIp: "10.8.2.67"
// protocolType: "NFS"
// publicMountDir: "/public"
// publicMountUrl: "132594ad6e-atf93.cn-beijing.nas.aliyuncs.com"
// ramUserId: "61261f8a2a2aa4d72f752c3c"
// smbMountUrl: null
// srcAddr: "fileserver.cloudam.cn"
// srcIp: "47.94.198.50"
// sshServerEndPoint: "https://fileserver.cloudam.cn:8888"
// storageType: "Capacity"
// token: null
// userMountDir: "/public/data/"
// userMountUrl: "132594ad6e-uop2.cn-beijing.nas.aliyuncs.com"
// vncServerEndPoint: "https://fileserver.cloudam.cn:9090"
// zoneId: "cn-beijing-h"
// }
// const currentRegion = {
// cloudProvider: "ALIYUN"
// description: "本计算区有丰富的CPU资源,并提供部分GPU资源,可以满足大部分计算作业需求。"
// enabled: true
// id: "CE-Z1"
// initialized: true
// location: "CLOUD"
// name: "通用计算区"
// primary: true
// storageConfig: {srcAddr: "fileserver.cloudam.cn", srcIp: "47.94.198.50", privateIp: "10.8.2.67",…}
// bandwidth: null
// capacity: 10485760
// enableLargeFileTransfer: true
// fileServerEndPoint: "https://fileserver.cloudam.cn"
// fileSystemType: "standard"
// jobLogServerEndPoint: "https://fileserver.cloudam.cn:6677"
// privateIp: "10.8.2.67"
// protocolType: "NFS"
// publicMountDir: "/public"
// publicMountUrl: "132594ad6e-atf93.cn-beijing.nas.aliyuncs.com"
// ramUserId: "61261f8a2a2aa4d72f752c3c"
// smbMountUrl: null
// srcAddr: "fileserver.cloudam.cn"
// srcIp: "47.94.198.50"
// sshServerEndPoint: "https://fileserver.cloudam.cn:8888"
// storageType: "Capacity"
// token: null
// userMountDir: "/public/data/"
// userMountUrl: "132594ad6e-uop2.cn-beijing.nas.aliyuncs.com"
// vncServerEndPoint: "https://fileserver.cloudam.cn:9090"
// zoneId: "cn-beijing-h"
// }
export const a = () => {
return "a";
};
...@@ -135,7 +135,6 @@ type getDataFileMoveParams = { ...@@ -135,7 +135,6 @@ type getDataFileMoveParams = {
dpath?: string; // 目标路径 dpath?: string; // 目标路径
}; };
// Content-Type application/x-www-form-urlencoded
// 移动到 // 移动到
const getDataFileMove = (params: getDataFileMoveParams) => { const getDataFileMove = (params: getDataFileMoveParams) => {
return request({ return request({
...@@ -148,13 +147,31 @@ const getDataFileMove = (params: getDataFileMoveParams) => { ...@@ -148,13 +147,31 @@ const getDataFileMove = (params: getDataFileMoveParams) => {
}); });
}; };
type getDataFileMovePackageParams = {
projectId: string;
names: string; // 包名
spath?: string; // 原路径
dpath?: string; // 目标路径
};
// 移动文件夹中的数据集
const getDataFileMovePackage = (params: getDataFileMovePackageParams) => {
return request({
url: Api.API_DATA_MOVE_PACKAGE,
method: "put",
data: params,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
};
type getDataFileDelParams = { type getDataFileDelParams = {
projectId: string; projectId: string;
names: string; names: string;
path?: string; path?: string;
}; };
// Content-Type application/x-www-form-urlencoded
// 删除项目中的数据集 // 删除项目中的数据集
const getDataFileDel = (params: getDataFileDelParams) => { const getDataFileDel = (params: getDataFileDelParams) => {
return request({ return request({
...@@ -167,6 +184,24 @@ const getDataFileDel = (params: getDataFileDelParams) => { ...@@ -167,6 +184,24 @@ const getDataFileDel = (params: getDataFileDelParams) => {
}); });
}; };
type getDataFileDelPackageParams = {
projectId: string;
names: string;
path?: string;
};
// 删除项目中的数据集
const getDataFileDelPackage = (params: getDataFileDelPackageParams) => {
return request({
url: Api.API_DATA_DEL_PACKAGE,
method: "delete",
params,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
};
export { export {
current, current,
menu, menu,
...@@ -180,5 +215,7 @@ export { ...@@ -180,5 +215,7 @@ export {
getDataFind, getDataFind,
getDataFileSearch, getDataFileSearch,
getDataFileMove, getDataFileMove,
getDataFileMovePackage,
getDataFileDel, getDataFileDel,
getDataFileDelPackage,
}; };
...@@ -74,11 +74,59 @@ const addWorkbenchTemplate = (params: workflowspecAddTemplateParams) => { ...@@ -74,11 +74,59 @@ const addWorkbenchTemplate = (params: workflowspecAddTemplateParams) => {
}; };
type workflowJobListParams = {
projectId: string;
name?: string;
state?: string;
page?: number;
size?: number;
};
// 查询项目下工作流模板列表
const getWorkflowJobList = (params: workflowJobListParams) => {
return request({
url: Api.API_WORKBENCH_WORKFLOWJOB_LIST,
method: "get",
params,
});
};
type workflowJobDelParams = {
id: string
};
// 项目管理员-删除工作流模板
const deleteWorkflowJob = (params: workflowJobDelParams) => {
return request({
url: Api.API_WORKBENCH_DEL_WORKFLOWJOB + params.id,
method: "delete",
});
};
type workflowJobCancelParams = {
jobid: string
};
// 取消工作流
const cancelWorkflowJob = (params: workflowJobCancelParams) => {
return request({
url: Api.API_WORKBENCH_CANCEL_WORKFLOWJOB,
method: "delete",
params,
});
};
export { export {
current, current,
menu, menu,
getWorkbenchTemplate, getWorkbenchTemplate,
deleteWorkbenchTemplate, deleteWorkbenchTemplate,
getAddWorkbenchTemplate, getAddWorkbenchTemplate,
addWorkbenchTemplate addWorkbenchTemplate,
getWorkflowJobList,
deleteWorkflowJob,
cancelWorkflowJob
}; };
<?xml version="1.0" encoding="UTF-8"?>
<svg width="38px" height="48px" viewBox="0 0 38 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>img_bky.0c94999e备份 5</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#EEF5FF" offset="0%"></stop>
<stop stop-color="#D8E7FF" offset="100%"></stop>
</linearGradient>
<polygon id="path-2" points="0 0 23.8553102 0 23.8553102 6.97165479 0 6.97165479"></polygon>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="项目数据—传输列表" transform="translate(-853.000000, -292.000000)">
<g id="编组-13" transform="translate(829.000000, 172.000000)">
<g id="编组-54" transform="translate(0.000000, 67.000000)">
<g id="编组-52" transform="translate(0.000000, 36.000000)">
<g id="编组-20" transform="translate(24.000000, 16.000000)">
<g id="img_bky.0c94999e备份-5" transform="translate(0.000000, 1.000000)">
<path d="M4,0 L34,0 C36.209139,0 38,1.790861 38,4 L38,36 L38,36 L28,48 L4,48 C1.790861,48 0,46.209139 0,44 L0,4 C0,1.790861 1.790861,0 4,0 Z" id="矩形" fill="url(#linearGradient-1)" fill-rule="nonzero"></path>
<g id="编组" opacity="0.800000012" transform="translate(3.000000, 16.000000)">
<path d="M19.5440063,7.16876077 C19.5440063,7.16876077 17.7817143,6.14587449 16.5897729,5.46257202 C14.3574699,4.18194596 11.7171006,3.17507407 9.08500973,3.58317846 C13.1105773,4.31203006 15.7261828,7.27081968 16.7502019,8.14045351 L19.5440063,7.16876077 Z" id="Fill-1" fill="#00CCCC" fill-rule="nonzero"></path>
<g transform="translate(7.138353, 5.028345)" id="Fill-3-Clipped">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<g id="path-2"></g>
<path d="M23.8475341,1.30693225 C23.7854464,0.676529763 21.2051666,-0.388952164 16.9246113,0.145167087 C10.9941641,0.884848085 7.93902039,3.69347 0,2.7499337 C0.969567451,3.35237664 2.14623668,3.98507627 3.54527983,4.62046684 C9.66384563,7.39870079 15.4135961,7.60025894 19.3981287,5.82699353 C23.3887273,4.05070901 23.931745,2.16468655 23.8475341,1.30693225" id="Fill-3" fill="#0066FF" fill-rule="nonzero" mask="url(#mask-3)"></path>
</g>
<path d="M30.9736907,6.28008688 C30.6298533,8.44006041 25.3893647,8.30971378 20.0153519,4.38211926 C16.2335679,1.61819325 11.5168998,-0.705730866 7.16933256,0.198360149 C12.714265,0.895970559 16.0337454,4.16480925 19.1989342,6.65826274 C22.9154191,9.58528611 26.772993,10.748167 29.483086,9.08424577 C29.9538108,8.7146678 31.1956365,7.49987138 30.9736907,6.28008688" id="Fill-5" fill="#00CCCC" fill-rule="nonzero"></path>
<path d="M3.51830379,6.10049601 C2.21967146,5.72619249 1.51715254,6.10679675 0.0979130386,5.88646764 C2.2898948,7.01777921 4.86839043,7.53496521 7.13837434,7.77826578 C7.7971464,7.84947731 8.55254692,8.01736586 9.56764536,7.96052791 C8.88111225,7.89253239 8.14812039,7.57034126 7.16927547,6.79869712 C5.66461184,5.61225405 3.3792844,3.90370252 0,3.63053905 C1.96033036,4.42088852 2.46738003,5.39264689 3.51830379,6.10049601" id="Fill-7" fill="#0066FF" fill-rule="nonzero"></path>
</g>
<polygon id="矩形" fill="#FFFFFF" fill-rule="nonzero" opacity="0.5" points="28 36 38 36 33 42 28 48"></polygon>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="16px" viewBox="0 0 18 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/文件传输</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
<filter color-interpolation-filters="auto" id="filter-2">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="项目数据-长路径" transform="translate(-1324.000000, -136.000000)">
<g id="编组-10" transform="translate(1317.000000, 128.000000)">
<g id="文件传输" transform="translate(7.000000, 7.000000)" filter="url(#filter-1)">
<g>
<rect id="矩形备份-5" x="0" y="0" width="18" height="18"></rect>
<g filter="url(#filter-2)">
<g transform="translate(0.000000, 1.687500)">
<path d="M5.95624614,0.9 L7.0470055,1.84033454 C7.43885553,2.2205386 7.96337743,2.43318258 8.50936421,2.43318258 L8.50936421,2.43318258 L16.8,2.43318258 L17.1,13.425 L1.2,13.725 L0.9,1.2 L5.95624614,0.9 Z" id="路径-4" stroke="#7C878E" stroke-width="1.8"></path>
<polygon id="路径-5" fill="#7C878E" points="9.26587781 3.28436599 1.47245698 3.28436599 1.47245698 1.2526684 6.01231277 1.2526684"></polygon>
<polygon id="路径-6" fill="#7C878E" fill-rule="nonzero" points="8.05145975 5.6167684 8.05145975 10.8168243 5.59717839 10.8168243 5.59717839 9.06182432 6.2508 9.0612484 6.25145975 5.6167684"></polygon>
<polygon id="路径-6备份" fill="#7C878E" fill-rule="nonzero" transform="translate(11.062078, 8.216796) scale(-1, -1) translate(-11.062078, -8.216796) " points="12.2726957 5.6167684 12.2726957 10.81608 9.85203814 10.8168243 9.85145975 9.06182437 10.472057 9.0612484 10.4726957 5.6167684"></polygon>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 8备份 5</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-8备份-5">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-61备份-8" transform="translate(1.000000, 1.000000)" stroke="#C2C6CC" stroke-width="1.68">
<circle id="椭圆形" cx="7" cy="7" r="6.16"></circle>
<line x1="10.7487096" y1="2.20752017" x2="3.31564484" y2="11.6997394" id="路径-48"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 26备份</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-26备份" transform="translate(2.000000, 2.000000)">
<circle id="椭圆形备份" stroke="#8A9099" stroke-width="1.2" fill-rule="nonzero" cx="6" cy="6" r="6.6"></circle>
<g filter="url(#filter-1)" id="编组-28">
<g transform="translate(3.558554, 2.400000)">
<polyline id="路径-23" stroke="#979797" stroke-width="1.2" points="0.122694244 1.35254766e-12 2.44144585 2.31875161 2.4 7.59435239"></polyline>
<line x1="2.44144585" y1="2.31875161" x2="4.76019746" y2="-1.05607525e-13" id="路径-24" stroke="#979797" stroke-width="1.2"></line>
<line x1="0" y1="3.58021955" x2="4.8" y2="3.58021955" id="路径-60" stroke="#979797" stroke-width="1.2"></line>
<line x1="-5.77512014e-14" y1="6" x2="4.8" y2="6" id="路径-60备份" stroke="#979797" stroke-width="1.2"></line>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/工作流模版备份 7</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组" transform="translate(-1.000000, 0.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g filter="url(#filter-1)" id="编组-50">
<g transform="translate(1.000000, 1.605109)">
<line x1="0" y1="2.39431484" x2="14" y2="2.39431484" id="路径-16" stroke="#979797" stroke-width="1.5"></line>
<path d="M3.37934347,2.39431484 L3.37934347,1 C3.37934347,0.44771525 3.82705872,1.01453063e-16 4.37934347,0 L9.63329305,0 C10.1855778,-1.01453063e-16 10.6332931,0.44771525 10.6332931,1 L10.6332931,2.39431484 L10.6332931,2.39431484" id="路径-17" stroke="#979797" stroke-width="1.5"></path>
<path d="M2.45321216,3.89402686 L2.45321216,11.9292428 C2.45321216,12.4815275 2.90092741,12.9292428 3.45321216,12.9292428 L10.4872657,12.9292428 C11.0395505,12.9292428 11.4872657,12.4815275 11.4872657,11.9292428 L11.4872657,3.89402686 L11.4872657,3.89402686" id="路径-20" stroke="#979797" stroke-width="1.5"></path>
<line x1="5.49894415" y1="3.89402686" x2="5.49894415" y2="10.3954667" id="路径-21" stroke="#979797" stroke-width="1.5"></line>
<line x1="8.49836822" y1="3.89402686" x2="8.49836822" y2="10.3954667" id="路径-22" stroke="#979797" stroke-width="1.5"></line>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 51</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-51">
<rect id="矩形备份-22" x="0" y="0" width="16" height="16"></rect>
<g id="编组-24" transform="translate(1.000000, 1.000000)">
<circle id="椭圆形" fill="#FF4E4E" fill-rule="nonzero" cx="7" cy="7" r="7"></circle>
<line x1="4.2" y1="4.2" x2="9.8" y2="9.8" id="路径-50" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round"></line>
<line x1="4.2" y1="4.2" x2="9.8" y2="9.8" id="路径-50备份" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" transform="translate(7.000000, 7.000000) scale(-1, 1) translate(-7.000000, -7.000000) "></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 8备份</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-8备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-61" transform="translate(1.000000, 1.000000)">
<circle id="椭圆形" fill="#1370FF" fill-rule="nonzero" cx="7" cy="7" r="7"></circle>
<line x1="7" y1="7" x2="7" y2="3.5" id="路径" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round"></line>
<line x1="7" y1="7" x2="9.625" y2="7" id="路径" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 18备份 3</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-18备份-3" transform="translate(0.000000, 0.000000)">
<g id="编组-9" transform="translate(0.500000, 0.500000)">
<circle id="椭圆形" fill="#FF4E4E" cx="7.5" cy="7.5" r="7.5"></circle>
<rect id="矩形" fill="#FFFFFF" x="4.5" y="4.5" width="6" height="6" rx="1"></rect>
</g>
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 50</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-50">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-61备份-4" transform="translate(1.000000, 1.000000)">
<circle id="椭圆形" fill="#0DD09B" fill-rule="nonzero" cx="7" cy="7" r="7"></circle>
<polyline id="路径-47" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" points="4.40461184 7.46931053 7 9.48405007 9.9825782 4.58929929"></polyline>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 26备份</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-26备份" transform="translate(2.000000, 2.000000)" stroke="#8A9099" stroke-width="1.2">
<circle id="椭圆形备份" fill-rule="nonzero" cx="6" cy="6" r="6.6"></circle>
<line x1="6" y1="6" x2="6" y2="3" id="路径备份" stroke-linecap="round"></line>
<line x1="6" y1="6" x2="8.25" y2="6" id="路径备份-2" stroke-linecap="round"></line>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/任务列表</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.760000 0 0 0 0 0.776000 0 0 0 0 0.800000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工作台(管理员)空" transform="translate(-370.000000, -245.000000)">
<g id="编组-5" transform="translate(370.000000, 242.000000)">
<g id="1.Base基础/Icon图标/任务列表" transform="translate(0.000000, 3.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g filter="url(#filter-1)" id="编组-4">
<g transform="translate(0.500000, 0.000000)">
<path d="M7.38809691,0.889939751 C7.45764437,0.855744844 7.53911808,0.85573765 7.60867158,0.889920274 L7.60867158,0.889920274 L14.1102244,4.08516037 C14.1529938,4.10617975 14.187927,4.13844408 14.2121677,4.17736742 C14.2364085,4.21629077 14.2499569,4.26187312 14.2499569,4.30952854 L14.2499569,4.30952854 L14.2499569,11.9840447 C14.2499569,12.0332683 14.2355127,12.0802004 14.2098426,12.119868 C14.1841726,12.1595356 14.1472766,12.1919385 14.1023731,12.2121037 L14.1023731,12.2121037 L7.60081331,15.1318104 C7.53565621,15.161071 7.46109499,15.1610648 7.39594277,15.1317934 L7.39594277,15.1317934 L0.897545722,12.2122049 C0.852652465,12.1920353 0.815766035,12.1596329 0.790102919,12.1199688 C0.764439802,12.0803047 0.75,12.033379 0.75,11.984163 L0.75,11.984163 L0.75,4.30940599 C0.75,4.26175853 0.763543923,4.21618307 0.78777749,4.17726362 L0.78777749,4.17726362 Z" id="路径-15" stroke="#979797" stroke-width="1.5"></path>
<polyline id="路径-20" stroke="#979797" stroke-width="1.5" points="1.29720478 4.56847209 7.47016174 7.45 13.6431187 4.56847209"></polyline>
<line x1="7.47016174" y1="7.39513959" x2="7.47016174" y2="14.8580198" id="路径-21" stroke="#979797" stroke-width="1.5"></line>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/任务列表</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.076000 0 0 0 0 0.440000 0 0 0 0 1.000000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务列表" transform="translate(-370.000000, -245.000000)">
<g id="编组-5" transform="translate(370.000000, 242.000000)">
<g id="1.Base基础/Icon图标/任务列表" transform="translate(0.000000, 3.000000)">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g filter="url(#filter-1)" id="编组-4">
<g transform="translate(0.500000, 0.000000)">
<path d="M7.38809691,0.889939751 C7.45764437,0.855744844 7.53911808,0.85573765 7.60867158,0.889920274 L7.60867158,0.889920274 L14.1102244,4.08516037 C14.1529938,4.10617975 14.187927,4.13844408 14.2121677,4.17736742 C14.2364085,4.21629077 14.2499569,4.26187312 14.2499569,4.30952854 L14.2499569,4.30952854 L14.2499569,11.9840447 C14.2499569,12.0332683 14.2355127,12.0802004 14.2098426,12.119868 C14.1841726,12.1595356 14.1472766,12.1919385 14.1023731,12.2121037 L14.1023731,12.2121037 L7.60081331,15.1318104 C7.53565621,15.161071 7.46109499,15.1610648 7.39594277,15.1317934 L7.39594277,15.1317934 L0.897545722,12.2122049 C0.852652465,12.1920353 0.815766035,12.1596329 0.790102919,12.1199688 C0.764439802,12.0803047 0.75,12.033379 0.75,11.984163 L0.75,11.984163 L0.75,4.30940599 C0.75,4.26175853 0.763543923,4.21618307 0.78777749,4.17726362 L0.78777749,4.17726362 Z" id="路径-15" stroke="#979797" stroke-width="1.5"></path>
<polyline id="路径-20" stroke="#979797" stroke-width="1.5" points="1.29720478 4.56847209 7.47016174 7.45 13.6431187 4.56847209"></polyline>
<line x1="7.47016174" y1="7.39513959" x2="7.47016174" y2="14.8580198" id="路径-21" stroke="#979797" stroke-width="1.5"></line>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/工作流模版</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.760000 0 0 0 0 0.776000 0 0 0 0 0.800000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="任务列表" transform="translate(-245.000000, -246.000000)">
<g id="编组-4" transform="translate(244.000000, 242.000000)">
<g id="编组-5" transform="translate(0.000000, 3.000000)" filter="url(#filter-1)">
<g>
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)" stroke="#979797" stroke-width="1.5">
<rect id="矩形" x="0.75" y="0.75" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份-2" x="0.75" y="8.5" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份" x="8.5" y="0.75" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份-3" x="8.5" y="8.5" width="4.75" height="4.75" rx="1"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/工作流模版</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.076000 0 0 0 0 0.440000 0 0 0 0 1.000000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工作台(管理员)空" transform="translate(-245.000000, -246.000000)">
<g id="编组-4" transform="translate(244.000000, 242.000000)">
<g id="编组-5" transform="translate(0.000000, 3.000000)" filter="url(#filter-1)">
<g>
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)" stroke="#979797" stroke-width="1.5">
<rect id="矩形" x="0.75" y="0.75" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份-2" x="0.75" y="8.5" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份" x="8.5" y="0.75" width="4.75" height="4.75" rx="1"></rect>
<rect id="矩形备份-3" x="8.5" y="8.5" width="4.75" height="4.75" rx="1"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
...@@ -19,7 +19,7 @@ const InformationDisplay = (props: InformationDisplayProps) => { ...@@ -19,7 +19,7 @@ const InformationDisplay = (props: InformationDisplayProps) => {
return ( return (
<div className={style.infoListLi} key={item.label}> <div className={style.infoListLi} key={item.label}>
<div className={style.infoListLiLabel}>{item.label}</div> <div className={style.infoListLiLabel}>{item.label}</div>
<div className={style.infoListLiValue}>{item.value}</div> <div className={style.infoListLiValue}>{item.value || "-"}</div>
</div> </div>
); );
})} })}
......
import React from "react"; import React, { useCallback} from "react";
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody"; import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
...@@ -100,6 +99,18 @@ export default function EnhancedTable(props) { ...@@ -100,6 +99,18 @@ export default function EnhancedTable(props) {
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage); const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
const renderTableCellValue = useCallback(((item, row, index)=>{
if(
item.render
) {
return <>{item.render(row[item.id], row, index)}</>
} else if(row[item.id]) {
return row[item.id] || '-'
} else {
return '-'
}
}),[])
return ( return (
<div className={classes.root}> <div className={classes.root}>
<Paper sx={{ <Paper sx={{
...@@ -189,8 +200,7 @@ export default function EnhancedTable(props) { ...@@ -189,8 +200,7 @@ export default function EnhancedTable(props) {
body: props.bodyTableCell || classes.bodyTableCell body: props.bodyTableCell || classes.bodyTableCell
}} }}
> { > {
item.render ? <>{item.render(row[item.id], row, index)}</> : renderTableCellValue(item, row, index)
row[item.id]
} }
</TableCell> </TableCell>
) )
......
...@@ -18,32 +18,52 @@ import LastPageIcon from '@mui/icons-material/LastPage'; ...@@ -18,32 +18,52 @@ import LastPageIcon from '@mui/icons-material/LastPage';
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
const useStyles = makeStyles({ const useStyles = makeStyles({
firstPageIconStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" }, firstPageIconStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" },
KeyboardArrowLeftStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginRight: "3px" }, KeyboardArrowLeftStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginRight: "3px" },
keyboardArrowRightStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginLeft: "3px" }, keyboardArrowRightStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginLeft: "3px" },
lastPageIconStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" } lastPageIconStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" }
}) })
const TablePaginationActionsConsole = props => { const TablePaginationActionsConsole = props => {
const classes = useStyles(); const classes = useStyles();
const { count, page, rowsPerPage, onChangePage } = props; const { count, page, rowsPerPage, onChangePage, onPageChange } = props;
const handleFirstPageButtonClick = (event) => { const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0); if (!onChangePage) {
onPageChange(event, 0)
return
}
onChangePage(event, 0)
} }
const handleBackButtonClick = (event) => { const handleBackButtonClick = (event) => {
onChangePage(event, page - 1); if (!onChangePage) {
onPageChange(event, page - 1)
return
}
onChangePage(event, page - 1)
} }
const handleNextButtonClick = (event) => { const handleNextButtonClick = (event) => {
onChangePage(event, page + 1); if (!onChangePage) {
onPageChange(event, page + 1);
return
}
onChangePage(event, page + 1)
} }
const btnClick = (event, item) => { const btnClick = (event, item) => {
onChangePage(event, item); if (!onChangePage) {
onPageChange(event, item);
return
}
onChangePage(event, item)
} }
const handleLastPageButtonClick = (event) => { const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); if (!onChangePage) {
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
return
}
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1))
} }
const buttons = (count, page, rowsPerPage) => { const buttons = (count, page, rowsPerPage) => {
let max = 1; let max = 1;
if( rowsPerPage !== -1 ){ if (rowsPerPage !== -1) {
max = count % rowsPerPage === 0 ? count / rowsPerPage : parseInt(count / rowsPerPage) + 1; max = count % rowsPerPage === 0 ? count / rowsPerPage : parseInt(count / rowsPerPage) + 1;
} }
let arr = [...Array(max).keys()]; let arr = [...Array(max).keys()];
...@@ -69,7 +89,7 @@ const TablePaginationActionsConsole = props => { ...@@ -69,7 +89,7 @@ const TablePaginationActionsConsole = props => {
<FirstPageIcon /> <FirstPageIcon />
</IconButton> </IconButton>
<IconButton <IconButton
className = { classes.KeyboardArrowLeftStyle } className={classes.KeyboardArrowLeftStyle}
onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page"> onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
<KeyboardArrowLeft /> <KeyboardArrowLeft />
</IconButton> </IconButton>
......
...@@ -8,7 +8,10 @@ import NotFound from "@/views/404"; ...@@ -8,7 +8,10 @@ import NotFound from "@/views/404";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import { useEffect } from "react"; import { useEffect } from "react";
import { menu } from "@/api/routes_api"; import { menu } from "@/api/routes_api";
import { setFileServerEndPointLocalStorage } from "@/views/Project/project"; import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
const useMyRouter = () => { const useMyRouter = () => {
const { permissionStore, menuStore, currentProjectStore } = useStores(); const { permissionStore, menuStore, currentProjectStore } = useStores();
...@@ -53,6 +56,10 @@ const useMyRouter = () => { ...@@ -53,6 +56,10 @@ const useMyRouter = () => {
currentProjectStore.setProjectList(list); currentProjectStore.setProjectList(list);
currentProjectStore.changeProject(list[0]); currentProjectStore.changeProject(list[0]);
setFileServerEndPointLocalStorage(list[0].zoneId); setFileServerEndPointLocalStorage(list[0].zoneId);
getFiletokenAccordingToId(list[0].id).then((res) => {
list[0].filetoken = res;
currentProjectStore.changeProject(list[0]);
});
} }
} }
......
import React, { FC } from "react"; import React, { FC } from "react";
import { Props } from "ahooks/lib/useControllableValue";
import { makeStyles } from "tss-react/mui";
import { Typography, Menu, MenuItem, IconButton, Button } from "@mui/material"; import { Typography, Menu, MenuItem, IconButton, Button } from "@mui/material";
import { makeStyles } from "@mui/styles";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import cx from "classnames"
type ButtonTagProps = { type ButtonTagProps = {
text: string; text: string;//文本内容
variant?: "text" | 'contained' | 'outlined'; variant?: "text" | 'contained' | 'outlined';//按钮样式
click: any; click?: any;//点击事件
select?: any[]; select?: any[];//选择按钮的下拉列表
fontSize?: string; fontSize?: string;//按钮文字大小
dropValue?: boolean; dropValue?: boolean;//选择的值
drop?: boolean; drop?: boolean;//是否开启选择
color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning" | undefined, color?: "inherit" | "primary" | "secondary" | undefined,//按钮颜色风格
btnStyle?: any,//按钮自定义样式类
size?: "large" | "medium" | "small",//按钮尺寸
disabled?: boolean,//是否禁用
style?: any,//按钮自定义样式
img?: JSX.Element;//图标按钮中的图标
selectCallBack?: (item: any, key: number) => void//选择按钮的回调
} }
const useStyles = makeStyles({
root: { backgroundColor: "#136EFA", boxShadow: "none !important", color: "#ffffff", "&:hover": { backgroundColor: "#ffffff !important" } },
ArrowDropDownIconRoot: { color: "#8A9099", transition: "all 0.2s !important", transform: "rotate(0)" },
ArrowDropDownIconRootOpen: { color: "#8A9099", transform: "rotate(180deg)" },
})
const ButtonComponent = (props: ButtonTagProps) => { const ButtonComponent = (props: ButtonTagProps) => {
const classes = useStyles(); const { size, disabled, variant, color, img, btnStyle = {}, select, selectCallBack } = props;
const { classes, cx } = useStyles({});
const [anchorEl, setAnchorEl] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event: { currentTarget: React.SetStateAction<null>; }) => setAnchorEl(event.currentTarget); const handleClick = (event: { currentTarget: React.SetStateAction<null>; }) => setAnchorEl(event.currentTarget);
const defultClick = (event: { stoppropagation: () => any; }) => event && event.stoppropagation && event.stoppropagation() const defultClick = (event: { stoppropagation: () => any; }) => event && event.stoppropagation && event.stoppropagation()
const handleCloseOption = (item: any, key: number) => {
setAnchorEl(null);
selectCallBack && selectCallBack(item, key)
}
const handleClose = () => setAnchorEl(null); const handleClose = () => setAnchorEl(null);
return ( return (
<> <>
<Button <Button
variant={props.variant || 'contained'} size={size || "medium"}
color={props.color || "primary"} variant={variant || 'contained'}
color={color || "primary"}
disableRipple={true} disableRipple={true}
disableFocusRipple={true} disableFocusRipple={true}
disabled={disabled || false}
classes={{ classes={{
root: classes.root, root: btnStyle.root || classes.root,
}} // disabled: btnStyle.disabled || classes.disabled,
containedSecondary: btnStyle.containedSecondary || classes.containedSecondary,
sx={{ color: "#565C66" }}//暂定 outlined: btnStyle.outlined || classes.outlined,
outlinedSecondary: btnStyle.outlinedSecondary || classes.outlinedSecondary,
text: btnStyle.text || classes.text,
textPrimary: btnStyle.textPrimary || classes.textPrimary,
textSecondary: btnStyle.textSecondary || classes.textSecondary,
sizeSmall: btnStyle.sizeSmall || classes.sizeSmall,
sizeLarge: btnStyle.sizeLarge || classes.sizeLarge,
}}
style={{ ...props.style }}
onClick={props.select ? handleClick : (props.click || defultClick)} onClick={props.select ? handleClick : (props.click || defultClick)}
> >
{img || ''}
<Typography style={{ fontSize: props.fontSize || "14px" }}>{props.text}</Typography> <Typography style={{ fontSize: props.fontSize || "14px" }}>{props.text}</Typography>
{ {
(props.select && props.select.length > 0 || props.drop) && <ArrowDropDownIcon classes={{ (props.select && props.select.length > 0 || props.drop) && <ArrowDropDownIcon classes={{
...@@ -58,38 +73,46 @@ const ButtonComponent = (props: ButtonTagProps) => { ...@@ -58,38 +73,46 @@ const ButtonComponent = (props: ButtonTagProps) => {
} }
</Button> </Button>
<Menu <Menu
id="product-menu" id="simple-menu"
keepMounted
anchorEl={anchorEl} anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)} open={Boolean(anchorEl)}
onClose={handleClose} onClose={handleClose}
MenuListProps={{
"aria-labelledby": "product-button",
}}
> >
{ {
props.select && props.select.length > 0 && props.select.map((item, key) => { select && select.length > 0 && select.map((item, key) => {
return ( return (
<MenuItem <MenuItem
key={item.path} key={key}
classes={{ root: classes.menuItemRoot }}
onClick={() => handleCloseOption(item, key)}>
onClick={() => { {item.name || ""}
// navigate(item.path);
handleClose();
}}
>
{item.name}
</MenuItem> </MenuItem>
); )
})} })
}
</Menu> </Menu>
</> </>
) )
}
const useStyles = makeStyles<{}>()(
(theme, { }) => ({
root: { backgroundColor: "#136EFA", boxShadow: "none !important", color: "#ffffff", "&:hover": { backgroundColor: "#0055D9" } },
containedSecondary: { backgroundColor: "#D62C1F", boxShadow: "none !important", "&:hover": { backgroundColor: "#D82C1F" } },
outlined: { backgroundColor: '#FFFFFF', border: "1px solid #136EFA", boxShadow: "none !important", color: "#136EFA", "&:hover": { backgroundColor: "rgba(19, 110, 250, 0.1)" } },
outlinedSecondary: { border: "1px solid #D62C1F", color: "#D62C1F", "&:hover": { border: "1px solid #D62C1F", backgroundColor: "rgba(214, 44, 31, 0.1)" } },
label: { "& p": { fontSize: "13px" } },
text: { backgroundColor: 'transparent', boxShadow: "none !important" },
textPrimary: { color: "#136EFA", "&:hover": { backgroundColor: "#E8F1FF" } },
textSecondary: { color: "#F44335", "&:hover": { backgroundColor: "rgba(244, 67, 53, 0.1)" } },
sizeSmall: { "& p": { fontSize: "12px" } },
sizeLarge: { "& p": { fontSize: "14px" } },
menuItemRoot: {},
ArrowDropDownIconRoot: { color: "#8A9099", transition: "all 0.2s !important", transform: "rotate(0)" },
ArrowDropDownIconRootOpen: { color: "#8A9099", transform: "rotate(180deg)" },
})
);
}
export default ButtonComponent; export default ButtonComponent;
\ No newline at end of file
...@@ -38,24 +38,8 @@ export interface IDialogProps { ...@@ -38,24 +38,8 @@ export interface IDialogProps {
/** 是否禁用确认按钮 */ /** 是否禁用确认按钮 */
disabledConfirm?: boolean; disabledConfirm?: boolean;
children: React.ReactNode; children: React.ReactNode;
} /** 点击遮罩是否关闭 默认为false*/
clickMaskClose?: boolean;
export interface IFooter {
isHideFooter?: boolean;
footerRender?: () => React.ReactNode;
showCancel?: boolean;
/** 是否显示确定按钮 */
showConfirm?: boolean;
/** 关闭弹窗时的回调函数 */
onClose?: () => void;
/** 点击确定按钮时的回调函数 */
onConfirm?: () => void;
/** 取消按钮文案 */
cancelText?: string;
/** 确认按钮文案 */
okText?: string;
/** 是否禁用确认按钮 */
disabledConfirm?: boolean;
} }
const MyDialog: React.FunctionComponent<IDialogProps> = (props) => { const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
...@@ -76,7 +60,19 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => { ...@@ -76,7 +60,19 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
cancelText, cancelText,
okText, okText,
disabledConfirm, disabledConfirm,
clickMaskClose = false,
} = props; } = props;
const handelClose = (
event: {},
reason: "backdropClick" | "escapeKeyDown"
) => {
if (reason === "backdropClick" && !clickMaskClose) {
return;
}
onClose && onClose();
};
const Footer = () => { const Footer = () => {
if (isHideFooter) return null; if (isHideFooter) return null;
return footerRender ? ( return footerRender ? (
...@@ -104,7 +100,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => { ...@@ -104,7 +100,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
return ( return (
<Dialog <Dialog
open={open} open={open}
onClose={onClose} onClose={handelClose}
style={style} style={style}
className={className} className={className}
aria-labelledby="alert-dialog-title" aria-labelledby="alert-dialog-title"
......
This diff is collapsed.
...@@ -26,7 +26,11 @@ const MyDialog = (props: any) => { ...@@ -26,7 +26,11 @@ const MyDialog = (props: any) => {
setOpen(true); setOpen(true);
}; };
const handleClose = () => { const handleClose = (event: any = {}, reason: any = "other") => {
// 点击弹窗外不关闭弹窗
if (reason === "backdropClick") {
return;
}
setOpen(false); setOpen(false);
}; };
...@@ -57,7 +61,11 @@ const MyDialog = (props: any) => { ...@@ -57,7 +61,11 @@ const MyDialog = (props: any) => {
{title} {title}
</DialogTitle> </DialogTitle>
)} )}
<DialogContent> <DialogContent
sx={{
minWidth: "400px",
}}
>
{props.children} {props.children}
<IconButton <IconButton
aria-label="delete" aria-label="delete"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-11 09:33:46 * @Date: 2022-06-11 09:33:46
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-11 11:33:17 * @LastEditTime: 2022-06-16 14:21:00
* @FilePath: /bkunyun/src/components/mui/MyPopover.tsx * @FilePath: /bkunyun/src/components/mui/MyPopover.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
......
...@@ -6,11 +6,11 @@ import TreeItem from "@mui/lab/TreeItem"; ...@@ -6,11 +6,11 @@ import TreeItem from "@mui/lab/TreeItem";
interface TreeItemType { interface TreeItemType {
id: string; id: string;
name: string; name: string;
disabled?: boolean;
subdirs?: readonly TreeItemType[]; subdirs?: readonly TreeItemType[];
} }
type MyTreeViewProps = { type MyTreeViewProps = {
// treeData: RenderTree;
treeData: Array<TreeItemType>; treeData: Array<TreeItemType>;
onNodeFocus?: (event: object, value: string) => void; // 点击某一项的回调 onNodeFocus?: (event: object, value: string) => void; // 点击某一项的回调
onNodeSelect?: (event: object, value: Array<any> | string) => void; // 点击某一项的回调 onNodeSelect?: (event: object, value: Array<any> | string) => void; // 点击某一项的回调
...@@ -25,6 +25,7 @@ type MyTreeViewProps = { ...@@ -25,6 +25,7 @@ type MyTreeViewProps = {
interface RenderTree { interface RenderTree {
id: string | number; id: string | number;
name: string; name: string;
disabled?: boolean;
subdirs?: readonly RenderTree[]; subdirs?: readonly RenderTree[];
} }
...@@ -48,6 +49,7 @@ const MyTreeView = (props: MyTreeViewProps) => { ...@@ -48,6 +49,7 @@ const MyTreeView = (props: MyTreeViewProps) => {
idFunc ? idFunc(nodes) : nodes.id || `${nodes.name}${index}` idFunc ? idFunc(nodes) : nodes.id || `${nodes.name}${index}`
)} )}
label={renderLabel === undefined ? nodes.name : renderLabel(nodes.name)} label={renderLabel === undefined ? nodes.name : renderLabel(nodes.name)}
disabled={nodes?.disabled ? true : false}
> >
{Array.isArray(nodes.subdirs) {Array.isArray(nodes.subdirs)
? nodes.subdirs.map((node, i) => renderTreeObj(node, i)) ? nodes.subdirs.map((node, i) => renderTreeObj(node, i))
...@@ -55,20 +57,6 @@ const MyTreeView = (props: MyTreeViewProps) => { ...@@ -55,20 +57,6 @@ const MyTreeView = (props: MyTreeViewProps) => {
</TreeItem> </TreeItem>
); );
// const renderTreeArray = (node: TreeItemType, index: number) => {
// return (
// <TreeItem
// key={node.id || `${node.name}${index}`}
// nodeId={String(node.id)}
// label={renderLabel === undefined ? node.name : renderLabel(node.name)}
// >
// {Array.isArray(node.subdirs)
// ? node.subdirs.map((nodeLi: any, i) => renderTreeArray(nodeLi, i))
// : null}
// </TreeItem>
// );
// };
return ( return (
<TreeView <TreeView
defaultCollapseIcon={<ArrowRightIcon />} defaultCollapseIcon={<ArrowRightIcon />}
...@@ -79,14 +67,9 @@ const MyTreeView = (props: MyTreeViewProps) => { ...@@ -79,14 +67,9 @@ const MyTreeView = (props: MyTreeViewProps) => {
defaultExpanded={defaultExpanded} defaultExpanded={defaultExpanded}
sx={{ ...treeViewSx }} sx={{ ...treeViewSx }}
> >
{treeData.length === 0 ? ( {treeData.map((treeItem, index) => {
<div>暂无数据</div> return renderTreeObj(treeItem, index);
) : ( })}
treeData.map((treeItem, index) => {
// return renderTreeArray(treeItem, index);
return renderTreeObj(treeItem, index);
})
)}
</TreeView> </TreeView>
); );
}; };
......
...@@ -8,25 +8,45 @@ ...@@ -8,25 +8,45 @@
*/ */
import { memo } from "react"; import { memo } from "react";
import { isEqual } from "lodash"; import { isEqual } from "lodash";
import { useState, useMemo, useEffect } from "react";
import { Box } from "@mui/system"; import { Box } from "@mui/system";
import Tab from "@mui/material/Tab"; import Tab from "@mui/material/Tab";
import { TabContext, TabList, TabPanel } from "@mui/lab"; import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Typography } from '@mui/material';
interface ITabList { interface ITabList {
label: string; label: string;
value: string; value: string;
component: JSX.Element; component: JSX.Element;
icon?: string;
iconed?: string;
hide?: boolean
} }
interface IProps { interface IProps {
value: string;
onChange: (val: string) => void;
tabList: ITabList[]; tabList: ITabList[];
} }
const Tabs = (props: IProps) => { const Tabs = (props: IProps) => {
const { value, onChange, tabList } = props; const { tabList } = props;
const [value, setValue] = useState(tabList.filter(e => !e.hide)[0].value);
const onChange = (val: string) => {
setValue(val);
};
const labelRender = (item: ITabList, key: number) => {
return (
<Box style={{ display: "flex", alignItems: "center" }}>
{
item.icon ? <img style={{ width: "14px", marginRight: "10px" }} src={value === item.value ? item.iconed : item.icon} alt="" />
: ""
}
<Typography sx={{ fontSize: "14px", fontWeight: '400' }} >{item.label}</Typography>
</Box>
)
}
return ( return (
<TabContext value={value}> <TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "#F0F2F5" }}> <Box sx={{ borderBottom: 1, borderColor: "#F0F2F5" }}>
...@@ -36,9 +56,15 @@ const Tabs = (props: IProps) => { ...@@ -36,9 +56,15 @@ const Tabs = (props: IProps) => {
}} }}
aria-label="lab API tabs example" aria-label="lab API tabs example"
> >
{tabList?.map((item) => { {tabList?.map((item, key) => {
if (item.hide) return ""
return ( return (
<Tab label={item.label} value={item.value} key={item.value} /> <Tab
key={key}
label={labelRender(item, key)}
value={item.value}
id={item.value}
/>
); );
})} })}
</TabList> </TabList>
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-14 17:22:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 17:22:56
* @FilePath: /bkunyun/src/hooks/useDeepEffect.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { useEffect, useRef } from 'react';
import _ from 'lodash';
export default function useDeepEffect(effectFunc: Function, deps: any[]) {
const isFirstRef = useRef(true);
const preDeps = useRef(deps);
useEffect(() => {
const isSame = preDeps.current.every((obj, index) => {
return _.isEqual(obj, deps[index]);
});
if (isFirstRef.current || !isSame) {
effectFunc();
}
isFirstRef.current = false;
preDeps.current = deps;
}, [deps]);
}
...@@ -20,7 +20,7 @@ const theme = createTheme({ ...@@ -20,7 +20,7 @@ const theme = createTheme({
}, },
palette: { palette: {
primary: { main: '#136EFA' }, primary: { main: '#136EFA' },
secondary: { main: '#4EB9FB' } secondary: { main: '#F44335' }
} }
}); });
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-09 20:41:05 * @Date: 2022-06-09 20:41:05
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 10:16:23 * @LastEditTime: 2022-06-14 20:55:22
* @FilePath: /bkunyun/src/store/index.ts * @FilePath: /bkunyun/src/store/index.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -11,11 +11,11 @@ import { configure } from "mobx"; ...@@ -11,11 +11,11 @@ import { configure } from "mobx";
import permissionStore from "./modules/permission"; import permissionStore from "./modules/permission";
import menuStore from "./modules/menu"; import menuStore from "./modules/menu";
import currentProjectStore from "./modules/currentProject"; import currentProjectStore from "./modules/currentProject";
import fileList from "./modules/fileList"; import fileListStore from "./modules/fileList";
configure({ enforceActions: "always" }); configure({ enforceActions: "always" });
export const stores = { permissionStore, menuStore, currentProjectStore, fileList }; export const stores = { permissionStore, menuStore, currentProjectStore, fileListStore };
/** Store类型 */ /** Store类型 */
export type Stores = typeof stores; export type Stores = typeof stores;
......
...@@ -4,6 +4,7 @@ type projectInfo = { ...@@ -4,6 +4,7 @@ type projectInfo = {
name?: string; name?: string;
desc?: string; desc?: string;
projectRole?: string; projectRole?: string;
filetoken?: string;
}; };
type productInfo = { type productInfo = {
......
...@@ -2,18 +2,18 @@ ...@@ -2,18 +2,18 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 17:00:19 * @Date: 2022-06-13 17:00:19
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 11:06:13 * @LastEditTime: 2022-06-16 09:43:42
* @FilePath: /bkunyun/src/store/modules/upload.ts * @FilePath: /bkunyun/src/store/modules/upload.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { makeAutoObservable } from "mobx"; import { makeAutoObservable } from "mobx";
interface IUploadInfo { export interface IUploadInfo {
id: string, id: string,
open: boolean, file: File,
list: any, info: any,
isPermanence: boolean, path: string;
} }
/** 存储地图派单websocket推送数据状态的store */ /** 存储地图派单websocket推送数据状态的store */
...@@ -25,12 +25,23 @@ class FileList { ...@@ -25,12 +25,23 @@ class FileList {
/** 文件上传列表 */ /** 文件上传列表 */
fileList: IUploadInfo[] = []; fileList: IUploadInfo[] = [];
setFileList (val: IUploadInfo[]) {
this.fileList = val // setFileList (val: IUploadInfo[]) {
// this.fileList = val
// }
/** 新需要上传的文件列表 */
newFileList: IUploadInfo[] = [];
/** 设置最新需要上传的文件列表 */
setNewFileList = (val: IUploadInfo[]) => {
this.fileList = this.fileList.concat(val)
this.newFileList = val
} }
/** 设置文件上传信息 */ /** 设置文件上传信息 */
setUploadInfo(id: string, val: IUploadInfo) { setUploadInfo = (id: string, val: IUploadInfo) => {
const newFileList = this.fileList?.map((item)=>{ const newFileList = this.fileList?.map((item)=>{
if(item.id === id){ if(item.id === id){
return val return val
...@@ -39,34 +50,16 @@ class FileList { ...@@ -39,34 +50,16 @@ class FileList {
this.fileList = newFileList this.fileList = newFileList
} }
setUploadInfoOpen(id: string, val: boolean) { setUploadInfoList = (id: string, val: any) => {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return {...item,open: val};
}
return item;
})
this.fileList = newFileList
}
setUploadInfoList(id: string, val: any) {
const newFileList = this.fileList?.map((item)=>{ const newFileList = this.fileList?.map((item)=>{
if(item.id === id){ if(item.id === id){
return {...item, list: val} return {...item, info: {...item.info, ...val}}
} return item } return item
}) })
this.fileList = newFileList this.fileList = newFileList
} }
setUploadInfoIsPermanence(id: string, val: boolean) {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return {...item, isPermanence: val}
} return item
})
this.fileList = newFileList
}
} }
const fileListStore = new FileList()
export default new FileList(); export default fileListStore
This diff is collapsed.
This diff is collapsed.
const localStorageKey = { const localStorageKey = {
TOKEN: "token", TOKEN: "token_key",
USER_INFO: "userInfo", USER_INFO: "userInfo",
USER_LOGIN: "userlogin", USER_LOGIN: "userlogin",
}; };
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-07 18:37:53 * @Date: 2022-06-07 18:37:53
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 10:32:54 * @LastEditTime: 2022-06-15 17:49:27
* @FilePath: /bkunyun/src/utils/util.ts * @FilePath: /bkunyun/src/utils/util.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from "uuid";
export const isProjectOwner = (name: string) => { export const isProjectOwner = (name: string) => {
let localName = ""; let localName = "";
...@@ -23,26 +23,49 @@ export const isProjectOwner = (name: string) => { ...@@ -23,26 +23,49 @@ export const isProjectOwner = (name: string) => {
* 生成32位的随机id * 生成32位的随机id
* @returns 返回32位的uuid * @returns 返回32位的uuid
*/ */
export const uuid = () => { export const uuid = () => {
const reg = /-/g; const reg = /-/g;
const pwd = uuidv4().replace(reg, ''); const pwd = uuidv4().replace(reg, "");
return pwd; return pwd;
}; };
// 获取用户token 信息 /** 格式化时间 xx小时xx分钟xx秒
* params: item: 毫秒的时间戳
*/
export const formatTime = (time: number) => {
const newTime = Math.floor(time / 1000);
const hours = Math.floor(newTime / 3600);
const minutes = Math.floor((newTime % 3600) / 60);
const seconds = newTime % 60;
const hoursString = hours ? `${hours}小时` : "";
const minutesString = minutes ? `${minutes}分钟` : "";
const secondsString = seconds ? `${seconds}秒` : "";
return `${hoursString}${minutesString}${secondsString}`;
};
// 获取用户信息
export const getUserInfo = () => { export const getUserInfo = () => {
let val: any; let val: any;
try { try {
val = JSON.parse(localStorage.getItem("userInfo") || "{}") val = JSON.parse(localStorage.getItem("userInfo") || "{}");
} } catch {
catch { console.error("获取用户信息 出错");
console.error("获取用户信息token 出错");
} }
return val return val;
} };
// 获取token信息
export const getTokenInfo = () => {
let val: any;
try {
val = JSON.parse(localStorage.getItem("token_key") || "{}");
} catch {
console.error("获取token信息 出错");
}
return val;
};
const IsNumberLetterChineseReg = new RegExp("^[A-Za-z0-9\u4e00-\u9fa5]+$"); const IsNumberLetterChineseReg = new RegExp("^[A-Za-z0-9\u4e00-\u9fa5]+$");
...@@ -53,3 +76,20 @@ export const checkIsNumberLetterChinese = (string: string) => { ...@@ -53,3 +76,20 @@ export const checkIsNumberLetterChinese = (string: string) => {
export const getMbfromB = (b: number) => { export const getMbfromB = (b: number) => {
return Math.floor(b / 1048576); return Math.floor(b / 1048576);
}; };
// 内存单位转换
export const storageUnitFromB = (b: number) => {
if (b <= 0) {
return "0B";
} else if (b < 1024) {
return `${b}B`;
} else if (b < 1024 * 1024) {
return `${(b / 1024).toFixed(2)}KB`;
} else if (b < 1024 * 1024 * 1024) {
return `${(b / (1024 * 1024)).toFixed(2)}MB`;
} else if (b < 1024 * 1024 * 1024 * 1024) {
return `${(b / (1024 * 1024 * 1024)).toFixed(2)}G`;
} else {
return `${(b / (1024 * 1024 * 1024 * 1024)).toFixed(2)}t`;
}
};
.itemBox {
height: 50px;
padding: 16px 0;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #f0f2f5;
}
.fileNameBox {
white-space: nowrap;
display: inline-block;
vertical-align: middle;
color: #1e2633;
max-width: 260px;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
}
.speedBox {
display: flex;
justify-content: space-between;
align-items: center;
}
.rightBox {
cursor: pointer;
font-size: 12px;
color: #1370ff;
}
.leftBox {
display: flex;
}
.span {
color: #8a9099;
font-size: 12px;
}
import { useEffect } from "react"; import { toJS } from "mobx";
import { useNavigate, useLocation } from "react-router-dom";
import { observer } from "mobx-react-lite";
import { useMemo } from "react";
import { LinearProgress } from "@mui/material";
import { formatTime, storageUnitFromB } from "@/utils/util";
import useGlobalStore from "@/hooks/useGlobalStore"; import useGlobalStore from "@/hooks/useGlobalStore";
import { observer } from "mobx-react-lite"; import { IUploadInfo } from "@/store/modules/fileList";
import { toJS } from "mobx"; import { useMessage } from "@/components/MySnackbar";
import UseTusUpload from "@/utils/Upload/tusUpload"; import bkunyunFile from "@/assets/img/bkunyunFile.svg";
// toJS(currentProjectStore.currentProjectInfo.id);
import styles from "./index.module.css";
/* /*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-11 15:46:42 * @Date: 2022-06-11 15:46:42
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 11:07:55 * @LastEditTime: 2022-06-16 02:07:56
* @FilePath: /bkunyun/src/views/ConsoleLayout/components/FileItem/index.tsx * @FilePath: /bkunyun/src/views/ConsoleLayout/components/FileItem/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
const FileItem = observer(() => {
const fileList = toJS(useGlobalStore("fileList")); interface IProps {
fileItemInfo: IUploadInfo;
const { uploadFile } = UseTusUpload(fileList?.fileList); }
useEffect(() => { const FileItem = observer((props: IProps) => {
fileList?.fileList?.forEach((item) => { const { fileItemInfo } = props;
uploadFile( const itemInfo = toJS(fileItemInfo)?.info;
item.id, const { statusMsg = "" } = itemInfo || {};
item.list, const uploadInfoStore = toJS(useGlobalStore("fileListStore"));
"/", const currentProjectStore = toJS(useGlobalStore("currentProjectStore"));
"/", const Message = useMessage();
(upload: any, filepath: string) => console.log(upload, filepath, 1111) const navigate = useNavigate();
); const location: any = useLocation();
});
console.log(fileList?.fileList, 1111); /** 时间 */
}, [fileList.fileList, uploadFile]); const TimeText = useMemo(() => {
return <div>dd</div>; const val = itemInfo?.endTime - itemInfo?.startTime;
return formatTime(val) || "";
}, [itemInfo?.endTime, itemInfo?.startTime]);
const text = useMemo(() => {
let result = "";
if (statusMsg === "上传失败") {
result = "重新上传";
}
if (statusMsg === "正在上传") {
if (itemInfo?.isSuspend) {
result = "重新上传";
} else {
result = "暂停";
}
}
if (statusMsg === "上传成功") {
result = "查看文件";
}
return result;
}, [itemInfo?.isSuspend, statusMsg]);
/** 操作合集 */
const onOperation = () => {
if (text === "暂停") {
itemInfo?.upload?.abort(true).then(() => {
Message.info("暂停成功!");
uploadInfoStore.setUploadInfoList(fileItemInfo?.id, {
isSuspend: true,
});
});
}
if (text === "重新上传") {
itemInfo?.upload?.start();
uploadInfoStore.setUploadInfoList(fileItemInfo?.id, {
isSuspend: false,
});
}
if (text === "查看文件") {
if (
location?.state?.pathName !== fileItemInfo?.path ||
location?.pathname !== "/product/cadd/projectData"
) {
navigate(`/product/cadd/projectData`, {
state: { pathName: fileItemInfo?.path },
});
}
}
};
const speed = useMemo(() => {
let val = 0;
const time = Math.floor((itemInfo?.endTime - itemInfo.startTime) / 1000);
if (time > 0) {
val = Math.floor(itemInfo?.bytesUploaded / time);
}
return val;
}, [itemInfo?.bytesUploaded, itemInfo?.endTime, itemInfo.startTime]);
return (
<div className={styles.itemBox}>
<div className={styles.leftBox}>
<img src={bkunyunFile} alt="" style={{ marginRight: 16 }} />
<div>
<div>
<b className={styles.fileNameBox} title={itemInfo?.name || ""}>
{itemInfo?.name || ""}
</b>
{statusMsg === "上传失败" ? (
<span
className={styles.span}
style={{ marginLeft: 16, color: "#FF4E4E" }}
>{`(${statusMsg})`}</span>
) : (
<span className={styles.span} style={{ marginLeft: 16 }}>
{TimeText}
</span>
)}
</div>
{statusMsg !== "上传成功" ? (
<LinearProgress
sx={{
width: 300,
borderRadius: 2,
margin: "6px 0",
color: "red",
}}
variant="determinate"
value={itemInfo?.percentage}
/>
) : null}
<div style={{ fontSize: 12 }}>
{statusMsg === "上传成功" ? (
<>
<span style={{ color: "#8A9099" }}>已上传至</span>
<span style={{ color: "#565C66", marginLeft: 12 }}>
{`CADD - ${
currentProjectStore?.currentProjectInfo?.name || ""
}`}
</span>
</>
) : (
<div className={styles.speedBox}>
<span className={styles.span}>{`${storageUnitFromB(
itemInfo?.bytesUploaded || 0
)}/${storageUnitFromB(itemInfo?.bytesTotal || 0)}`}</span>{" "}
:
<span className={styles.span}>{`${storageUnitFromB(
speed
)}/s`}</span>
</div>
)}
</div>
</div>
</div>
<div className={styles.rightBox} onClick={onOperation}>
{text}
</div>
</div>
);
}); });
export default FileItem; export default FileItem;
...@@ -2,18 +2,23 @@ ...@@ -2,18 +2,23 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-10 18:05:21 * @Date: 2022-06-10 18:05:21
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-11 18:08:27 * @LastEditTime: 2022-06-16 21:15:59
* @FilePath: /bkunyun/src/views/ConsoleLayout/components/TransferList/index.tsx * @FilePath: /bkunyun/src/views/ConsoleLayout/components/TransferList/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { Box, InputLabel, MenuItem, Select } from "@mui/material"; import { Box } from "@mui/material";
import { memo } from "react"; import { memo } from "react";
import MySelect from "@/components/mui/MySelect"; import MySelect from "@/components/mui/MySelect";
import MyTitle from "@/components/mui/MyTitle"; import MyTitle from "@/components/mui/MyTitle";
import FileItem from "../FileItem"; import FileItem from "../FileItem";
import useGlobalStore from "@/hooks/useGlobalStore";
import { observer } from "mobx-react-lite";
import { toJS } from "mobx";
const TranSferList = observer(() => {
const uploadInfoStore = toJS(useGlobalStore("fileListStore"));
const TranSferList = () => {
return ( return (
<Box style={{ width: 520, padding: 20 }}> <Box style={{ width: 520, padding: 20 }}>
<MyTitle title="传输列表" /> <MyTitle title="传输列表" />
...@@ -41,11 +46,13 @@ const TranSferList = () => { ...@@ -41,11 +46,13 @@ const TranSferList = () => {
size="small" size="small"
/> />
</Box> </Box>
<Box> <Box style={{ height: 400, overflowY: "auto" }}>
<FileItem /> {uploadInfoStore?.fileList.map((item) => {
return <FileItem fileItemInfo={item} key={item.id} />;
})}
</Box> </Box>
</Box> </Box>
); );
}; });
export default memo(TranSferList); export default memo(TranSferList);
...@@ -3,10 +3,10 @@ import { Outlet, useLocation, useNavigate } from "react-router-dom"; ...@@ -3,10 +3,10 @@ import { Outlet, useLocation, useNavigate } from "react-router-dom";
import cx from "classnames"; import cx from "classnames";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import Add from "@mui/icons-material/Add";
import Avatar from "@mui/material/Avatar"; import Avatar from "@mui/material/Avatar";
import { Box, Menu, MenuItem } from "@mui/material"; import { Box, Menu, MenuItem } from "@mui/material";
import uploadIcon from "@/assets/img/uploadIcon.svg";
import globalText from "@/utils/globalText_CN"; import globalText from "@/utils/globalText_CN";
import useIndex from "./useIndex"; import useIndex from "./useIndex";
import { useStores } from "@/store/index"; import { useStores } from "@/store/index";
...@@ -45,6 +45,7 @@ const ConsoleLayout = observer(() => { ...@@ -45,6 +45,7 @@ const ConsoleLayout = observer(() => {
<Button <Button
text={globalText.console} text={globalText.console}
variant={"text"} variant={"text"}
style={{ color: "#565C66" }}
click={() => navigate("/home")} click={() => navigate("/home")}
/> />
...@@ -52,6 +53,7 @@ const ConsoleLayout = observer(() => { ...@@ -52,6 +53,7 @@ const ConsoleLayout = observer(() => {
<Button <Button
text={globalText.product} text={globalText.product}
variant={"text"} variant={"text"}
style={{ color: "#565C66" }}
click={handleProductClick} click={handleProductClick}
dropValue={productOpen} dropValue={productOpen}
drop={true} drop={true}
...@@ -105,7 +107,11 @@ const ConsoleLayout = observer(() => { ...@@ -105,7 +107,11 @@ const ConsoleLayout = observer(() => {
}} }}
> >
<Box className={style.topRightItem}> <Box className={style.topRightItem}>
<Add /> <img
src={uploadIcon}
alt=""
style={{ verticalAlign: "middle" }}
/>
</Box> </Box>
</MyPopover> </MyPopover>
<Box className={style.topRightItem}> <Box className={style.topRightItem}>
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
.content { .content {
flex: 1; flex: 1;
height: calc(100vh - 57px); height: calc(100vh - 57px);
overflow: scroll; overflow: hidden;
/* ??????????? */
} }
.list { .list {
/* background-color: red; */ /* background-color: red; */
......
...@@ -5,16 +5,31 @@ import MyDialog from "@/components/mui/MyDialog"; ...@@ -5,16 +5,31 @@ import MyDialog from "@/components/mui/MyDialog";
import { checkIsNumberLetterChinese } from "@/utils/util"; import { checkIsNumberLetterChinese } from "@/utils/util";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import CloudEController from "@/api/fileserver/CloudEController"; import CloudEController from "@/api/fileserver/CloudEController";
import InputAdornment from '@mui/material/InputAdornment';
const AddFolder = (props: any) => { const AddFolder = (props: any) => {
const { list, path, projectId, fileToken, refresh } = props; const { list, path, projectId, fileToken, refresh } = props;
const Message = useMessage(); const Message = useMessage();
let addFolderDialogRef: any = React.createRef(); let addFolderDialogRef: any = React.createRef();
const [fileName, setFileName] = useState("");
const [fileNameCheck, setFileNameCheck] = useState({
error: false,
help: "",
});
const showDialog = () => { const showDialog = () => {
addFolderDialogRef.current.handleClickOpen(); addFolderDialogRef.current.handleClickOpen();
initData()
}; };
const initData = () => {
setFileName('')
setFileNameCheck({
error: false,
help: "",
})
}
useImperativeHandle(props.onRef, () => { useImperativeHandle(props.onRef, () => {
return { return {
showDialog: showDialog, showDialog: showDialog,
...@@ -41,11 +56,6 @@ const AddFolder = (props: any) => { ...@@ -41,11 +56,6 @@ const AddFolder = (props: any) => {
}; };
const addFolderSubmitloading = false; const addFolderSubmitloading = false;
const [fileName, setFileName] = useState("");
const [fileNameCheck, setFileNameCheck] = useState({
error: false,
help: "",
});
const handleFileNameChange = (e: any) => { const handleFileNameChange = (e: any) => {
const fileName = e.target.value; const fileName = e.target.value;
setFileName(fileName); setFileName(fileName);
...@@ -99,6 +109,9 @@ const AddFolder = (props: any) => { ...@@ -99,6 +109,9 @@ const AddFolder = (props: any) => {
value={fileName} value={fileName}
onChange={handleFileNameChange} onChange={handleFileNameChange}
helperText={fileNameCheck.help} helperText={fileNameCheck.help}
InputProps={{
endAdornment: <InputAdornment position="end">{fileName.length}/30</InputAdornment>,
}}
size="small" size="small"
/> />
</MyDialog> </MyDialog>
......
import React, { useState, useImperativeHandle, useMemo } from "react";
import MyDialog from "@/components/mui/MyDialog";
import { useMessage } from "@/components/MySnackbar";
import CloudEController from "@/api/fileserver/CloudEController";
import { getDataFileDel, getDataFileDelPackage } from "@/api/project_api";
import useMyRequest from "@/hooks/useMyRequest";
const DeleteDialog = (props: any) => {
const {
path,
projectId,
fileToken,
currentOperateFile,
selectIds,
refresh,
showList,
} = props;
const Message = useMessage();
let deleteFileDialogRef: any = React.createRef();
const showDialog = () => {
deleteFileDialogRef.current.handleClickOpen();
};
useImperativeHandle(props.onRef, () => {
return {
showDialog: showDialog,
};
});
const { run: getDataFileDelRun } = useMyRequest(getDataFileDel, {
onSuccess: (res: any) => {
successDelete();
},
});
const { run: getDataFileDelPackageRun } = useMyRequest(
getDataFileDelPackage,
{
onSuccess: (res: any) => {
successDelete();
},
}
);
const successDelete = () => {
Message.success("删除成功!");
deleteFileDialogRef?.current?.handleClose();
refresh();
};
const deletePathProvidedToDataSet = useMemo(() => {
return path === "/" ? "/" : `${path}/`;
}, [path]);
const deletePathProvidedFileServer = useMemo(() => {
return path === "/" ? `${path}` : `${path}/`;
}, [path]);
// 删除
const handleSubmit = () => {
if (!currentOperateFile) {
// 批量删除
// 要删除的数据集
const datSetDeleteList = showList.filter((item: any) => {
return selectIds.indexOf(item.name) !== -1 && item.type === "dataSet";
});
// 要删除的文件夹
const folderDeleteList = showList.filter((item: any) => {
return selectIds.indexOf(item.name) !== -1 && item.type === "directory";
});
// 要删除的文件
const fileDeleteList = showList.filter((item: any) => {
return (
selectIds.indexOf(item.name) !== -1 &&
item.type !== "dataSet" &&
item.type !== "directory"
);
});
if (datSetDeleteList.length > 0) {
dataSetsDelete(datSetDeleteList);
}
if (folderDeleteList.length > 0) {
foldersDelete(folderDeleteList);
}
if (fileDeleteList.length > 0) {
filesDelete(fileDeleteList);
}
} else {
if (currentOperateFile.type === "dataSet") {
dataSetDelete();
} else if (currentOperateFile.type === "directory") {
folerDelete();
} else {
fileDelete();
}
}
};
// 删除单个数据集
const dataSetDelete = () => {
getDataFileDelRun({
projectId: projectId as string,
names: currentOperateFile.name,
path: deletePathProvidedToDataSet,
});
};
// 删除单个文件夹
const folerDelete = () => {
fileDelete();
const names = currentOperateFile.name;
dataSetInFolerDelete(names);
};
// 删除文件夹中的数据集
const dataSetInFolerDelete = (names: string) => {
getDataFileDelPackageRun({
projectId: projectId as string,
names,
path: deletePathProvidedToDataSet,
});
};
// 删除单个文件
const fileDelete = () => {
CloudEController.JobOutFileDel(
`${deletePathProvidedFileServer}${currentOperateFile.name}`,
fileToken as string,
projectId as string
)?.then((res) => {
successDelete();
});
};
// 删除多个数据集
const dataSetsDelete = (datSetDeleteList: Array<any>) => {
getDataFileDelRun({
projectId: projectId as string,
names: datSetDeleteList.map((item: any) => item.name).join(","),
path: deletePathProvidedToDataSet,
});
};
// 删除多个文件夹
const foldersDelete = (folderDeleteList: Array<any>) => {
filesDelete(folderDeleteList);
const names = folderDeleteList.map((item: any) => item.name).join(",");
dataSetInFolerDelete(names);
};
// 删除多个文件
const filesDelete = (fileDeleteList: Array<any>) => {
const deletePath = fileDeleteList
.map((item: any) => {
return `${deletePathProvidedFileServer}${item.name}`;
})
.join(" ");
CloudEController.JobOutFileDel(
deletePath,
fileToken as string,
projectId as string
)?.then((res) => {
successDelete();
});
};
const submitloading = false;
return (
<MyDialog
handleSubmit={handleSubmit}
onRef={deleteFileDialogRef}
title="提示"
submitloading={submitloading}
>
{currentOperateFile
? "确认删除该数据吗?"
: `确认删除这${selectIds.length}条数据吗?`}
</MyDialog>
);
};
export default DeleteDialog;
...@@ -20,7 +20,14 @@ ...@@ -20,7 +20,14 @@
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
}
.treeLabelText{
line-height: 44px; line-height: 44px;
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
white-space: nowrap;
width: 320px;
} }
.labelFolderIcon { .labelFolderIcon {
margin-right: 9px; margin-right: 9px;
......
...@@ -45,16 +45,23 @@ ...@@ -45,16 +45,23 @@
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
} }
.tableBox { /* .tableBox {
height: 300px; height: 300px;
overflow: scroll; overflow: scroll;
} } */
.fileIconBox { .fileIconBox {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
} }
.fileIconBoxText{
display: block;
width: 260px;
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
white-space: nowrap;
}
.noFile { .noFile {
position: absolute; position: absolute;
top: 92px; top: 92px;
......
import React, { useState, useImperativeHandle, useCallback } from "react"; import React, {
useState,
useImperativeHandle,
useCallback,
useMemo,
} from "react";
import style from "./index.module.css"; import style from "./index.module.css";
import { TextField } from "@mui/material";
import MyDialog from "@/components/mui/MyDialog"; import MyDialog from "@/components/mui/MyDialog";
import { Button } from "@mui/material"; import { Button } from "@mui/material";
import { checkIsNumberLetterChinese, uuid } from "@/utils/util"; import { uuid } from "@/utils/util";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import Table from "@/components/Material.Ui/Table"; import Table from "@/components/Material.Ui/Table";
...@@ -12,68 +16,140 @@ import fileIcon from "@/assets/project/fileIcon.svg"; ...@@ -12,68 +16,140 @@ import fileIcon from "@/assets/project/fileIcon.svg";
import noFile from "@/assets/project/noFile.svg"; import noFile from "@/assets/project/noFile.svg";
import uploaderIcon from "@/assets/project/uploaderIcon.svg"; import uploaderIcon from "@/assets/project/uploaderIcon.svg";
import classnames from "classnames"; import classnames from "classnames";
import { getMbfromB } from "@/utils/util"; import { storageUnitFromB } from "@/utils/util";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react";
import { useStores } from "@/store";
import { toJS } from "mobx";
import useGlobalStore from "@/hooks/useGlobalStore"; import useGlobalStore from "@/hooks/useGlobalStore";
import { APIOPTION, urlToken } from "@/api/fileserver/raysyncApi";
import UseTusUpload from "@/utils/Upload/tusUpload";
const UpLoaderFile = observer((props: any) => { const UpLoaderFile = observer((props: any) => {
const uploadInfoStore = useGlobalStore("fileList"); const { fileListStore } = useStores();
const message = useMessage(); const message = useMessage();
const [fileList, setFileList] = useState<any>([]); const [fileList, setFileList] = useState<any>([]);
// list 是项目数据table的数据 // list 是项目数据table的数据
const { path, list } = props; const { path, list } = props;
// 集合当前路径下的文件、文件夹、数据集 和已选择要上传的文件列表
const nowNameList = useMemo(() => {
return [...list, ...fileList];
}, [list, fileList]);
const currentProjectStore = toJS(useGlobalStore("currentProjectStore"));
const uploadInfoStore = toJS(useGlobalStore("fileListStore"));
const { uploadFile } = UseTusUpload(uploadInfoStore);
const onDrop = useCallback( const onDrop = useCallback(
(acceptedFiles: any) => { (acceptedFiles: any) => {
// 判断是否有文件名重复 // 获取重复的项目文件列表和要上传(名称不重复就上传)的文件
const fileListRepeatName = getRepeatName(fileList, acceptedFiles); const getRepeatFileAndGetUploderFileList = (
const listRepeatName = getRepeatName(list, acceptedFiles); acceptedFiles: Array<any>
if (fileListRepeatName || listRepeatName) { ) => {
message.error(`${fileListRepeatName || listRepeatName}文件已存在`); let repeatFileList: any = [];
return; let uploderFileList: any = [];
acceptedFiles.forEach((fItem: any, index: number) => {
if (
nowNameList.some((nItem: any) => {
return nItem.name === fItem.name;
})
) {
repeatFileList.push(acceptedFiles[index]);
} else {
uploderFileList.push(acceptedFiles[index]);
}
});
return {
repeatFileList,
uploderFileList,
};
};
const repeatAndUploaderFileList =
getRepeatFileAndGetUploderFileList(acceptedFiles);
if (repeatAndUploaderFileList.repeatFileList.length > 0) {
message.error(
`“${repeatAndUploaderFileList.repeatFileList
.map((i: any) => i.name)
.join("、")}”文件已存在`
);
} }
// 插入新的文件列表 // 插入新的文件列表
const popLength = 10 - fileList.length; const popLength = 10 - fileList.length;
let newFileList = [...acceptedFiles.slice(0, popLength), ...fileList]; if (
fileList.length + repeatAndUploaderFileList.uploderFileList.length >
10
) {
message.error("最大支持同时上传10个文件");
}
let newFileList = [
...repeatAndUploaderFileList.uploderFileList.slice(0, popLength),
...fileList,
];
setFileList(newFileList); setFileList(newFileList);
}, },
[fileList, list, message] [fileList, message, nowNameList]
); );
const getRepeatName = (fList: Array<any>, Alist: Array<any>) => {
let repeatName = "";
Alist.forEach((aItem) => {
fList.forEach((fItem: any) => {
if (fItem.name === aItem.name) {
repeatName = fItem.name;
}
});
});
return repeatName;
};
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
const submitloading = false; const submitloading = false;
let dialogRef: any = React.createRef(); let dialogRef: any = React.createRef();
const handleSubmit = () => { const getFileToken = useCallback(
const newFileList = fileList?.map((item: any) => { (newFileList: any) => {
return { let url =
id: uuid(), APIOPTION() +
open: false, "/parallelupload/" +
list: item, urlToken(
isPermanence: true, currentProjectStore?.currentProjectInfo?.filetoken || "",
}; currentProjectStore?.currentProjectInfo?.id as string
}); );
uploadInfoStore.setFileList(newFileList);
console.log("handleSubmit"); newFileList?.forEach((item: any) => {
uploadFile(
item,
item?.file,
url,
currentProjectStore?.currentProjectInfo?.filetoken || "",
`${path}/${item?.file?.name}`
);
});
},
[
currentProjectStore?.currentProjectInfo?.filetoken,
currentProjectStore?.currentProjectInfo?.id,
path,
uploadFile,
]
);
const handleSubmit = () => {
const newFileList =
fileList?.map((item: any) => {
return {
id: uuid(),
path,
list: [],
file: item,
};
}) || [];
toJS(fileListStore?.setNewFileList)(newFileList);
if (newFileList?.length) {
getFileToken(newFileList);
}
dialogRef.current.handleClose();
}; };
const showDialog = () => { const showDialog = () => {
dialogRef.current.handleClickOpen(); dialogRef.current.handleClickOpen();
initData();
};
const initData = () => {
setFileList([]);
}; };
useImperativeHandle(props.onRef, () => { useImperativeHandle(props.onRef, () => {
...@@ -92,15 +168,13 @@ const UpLoaderFile = observer((props: any) => { ...@@ -92,15 +168,13 @@ const UpLoaderFile = observer((props: any) => {
return ( return (
<span className={style.fileIconBox}> <span className={style.fileIconBox}>
<img className={style.fileIcon} src={fileIcon} alt="" /> <img className={style.fileIcon} src={fileIcon} alt="" />
{item.name} <span className={style.fileIconBoxText}>{item.name}</span>
</span> </span>
); );
}; };
// 1,048,576 // 1,048,576
const renderSize = (item: any) => { const renderSize = (item: any) => {
return ( return <span>{item.size ? storageUnitFromB(Number(item.size)) : "-"}</span>;
<span>{item.size ? `${getMbfromB(Number(item.size))}MB` : "-"}</span>
);
}; };
const handleRowDelete = (index: number) => { const handleRowDelete = (index: number) => {
...@@ -183,12 +257,14 @@ const UpLoaderFile = observer((props: any) => { ...@@ -183,12 +257,14 @@ const UpLoaderFile = observer((props: any) => {
fontSize: "12px", fontSize: "12px",
lineHeight: "20px", lineHeight: "20px",
color: "#8A9099", color: "#8A9099",
// padding: "12px 24px",
}} }}
tableBoySx={{ tableBoySx={{
backgroundColor: backgroundColor:
fileList.length >= 10 ? "rgba(255, 0, 0, 0.6)" : "", fileList.length >= 10 ? "rgba(255, 0, 0, 0.6)" : "",
}} }}
tableContainerStyle={{
maxHeight: "300px",
}}
></Table> ></Table>
</div> </div>
{fileList.length === 0 && ( {fileList.length === 0 && (
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
} }
.projectDataStickyTop { .projectDataStickyTop {
padding: 28px 24px; padding: 28px 24px;
position: relative;
} }
.projectDataTitle { .projectDataTitle {
font-size: 18px; font-size: 18px;
...@@ -73,6 +74,10 @@ ...@@ -73,6 +74,10 @@
align-items: center; align-items: center;
} }
.folderPointer{
cursor: pointer;
}
.folderIcon { .folderIcon {
margin-right: 12px; margin-right: 12px;
} }
...@@ -111,4 +116,21 @@ ...@@ -111,4 +116,21 @@
} }
.showPathSpanActive{ .showPathSpanActive{
color: #1370FF; color: #1370FF;
}
.noDataBox{
background-color: #fff;
height: calc(100vh - 377px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
top: -53px;
}
.noDataText{
margin-top: 8px;
font-size: 14px;
line-height: 22px;
color: #8A9099;
} }
\ No newline at end of file
This diff is collapsed.
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
outline: none; outline: none;
} }
.projectInfoListLiValue:focus { .projectInfoListLiValue:focus {
border: 1px solid #136efa; border: 2px solid #136efa;
} }
.projectInfoTextarea { .projectInfoTextarea {
line-height: 22px; line-height: 22px;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-01 09:15:10 * @LastEditTime: 2022-06-14 15:40:27
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -21,14 +21,17 @@ import { toJS } from "mobx"; ...@@ -21,14 +21,17 @@ import { toJS } from "mobx";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import InformationDisplay from "@/components/InformationDisplay"; import InformationDisplay from "@/components/InformationDisplay";
import classnames from "classnames"; import classnames from "classnames";
import { Button } from "@mui/material"; import { Button, TextField } from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton"; import LoadingButton from "@mui/lab/LoadingButton";
import { useMessage } from "@/components/MySnackbar"; import { useMessage } from "@/components/MySnackbar";
import Loading from "@/views/Loading"; import Loading from "@/views/Loading";
import MyDialog from "@/components/mui/MyDialog"; import MyDialog from "@/components/mui/MyDialog";
import { getProjectList } from "../../project"; import { getProjectList } from "../../project";
import { checkIsNumberLetterChinese } from "@/utils/util"; import { checkIsNumberLetterChinese } from "@/utils/util";
import { setFileServerEndPointLocalStorage } from "@/views/Project/project"; import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
type zoneIdOption = { type zoneIdOption = {
id: string; id: string;
...@@ -40,9 +43,27 @@ const BaseInfo = observer(() => { ...@@ -40,9 +43,27 @@ const BaseInfo = observer(() => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const [projectInfo, setProjectInfo] = useState<any>({}); const [projectInfo, setProjectInfo] = useState<any>({});
const [deleteProjectName, setDeleteProjectName] = useState(""); const [deleteProjectName, setDeleteProjectName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const currentUserName = JSON.parse( const currentUserName = JSON.parse(
localStorage.getItem("userInfo") || "{}" localStorage.getItem("userInfo") || "{}"
).name; ).name;
// 是否拥有编辑权限
const hasEditAuth = useMemo(() => {
if (!currentUserName) {
return false;
} else if (!projectInfo.members) {
return false;
} else {
return projectInfo.members.some((item: any) => {
return (
item.username === currentUserName && item.projectRole === "OWNER"
);
});
}
}, [currentUserName, projectInfo]);
const { run, loading } = useMyRequest(getProject, { const { run, loading } = useMyRequest(getProject, {
onSuccess: (result: any) => { onSuccess: (result: any) => {
setProjectInfo(result.data); setProjectInfo(result.data);
...@@ -98,11 +119,50 @@ const BaseInfo = observer(() => { ...@@ -98,11 +119,50 @@ const BaseInfo = observer(() => {
]; ];
}, [projectInfo, zoneIdMap]); }, [projectInfo, zoneIdMap]);
const checkName = (name: string, showMessage = false) => {
let help = "";
if (name) {
if (name.length > 30) {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
} else if (checkIsNumberLetterChinese(name)) {
setNameCheck({
error: false,
help: "",
});
return true;
} else {
help = "格式不正确,必须在30字符以内,仅限大小写字母、数字、中文";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
} else {
help = "项目名称不能为空";
setNameCheck({
error: true,
help,
});
showMessage && message.error(help);
return false;
}
};
const nameChange = (e: any) => { const nameChange = (e: any) => {
setProjectInfo({ setProjectInfo({
...projectInfo, ...projectInfo,
name: e.target.value, name: e.target.value,
}); });
checkName(e.target.value);
// setNameCheck
}; };
const descChange = (e: any) => { const descChange = (e: any) => {
...@@ -126,16 +186,10 @@ const BaseInfo = observer(() => { ...@@ -126,16 +186,10 @@ const BaseInfo = observer(() => {
// 修改项目 // 修改项目
const handleClickUpdate = () => { const handleClickUpdate = () => {
if (projectInfo.name) { if (checkName(projectInfo.name, true)) {
if (checkIsNumberLetterChinese(projectInfo.name)) { updateProjectRun({ ...projectInfo, product: "CADD" });
updateProjectRun({ ...projectInfo, product: "CADD" });
} else {
message.info(
"格式不正确,必须在30字符以内,仅限大小写字母、数字、中文"
);
}
} else { } else {
message.info("项目名称不能为空"); return;
} }
}; };
...@@ -147,9 +201,23 @@ const BaseInfo = observer(() => { ...@@ -147,9 +201,23 @@ const BaseInfo = observer(() => {
DialogRef.current.handleClose(); DialogRef.current.handleClose();
const projectList = await getProjectList(); const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList); currentProjectStore.setProjectList(projectList);
currentProjectStore.changeProject(projectList[0]); // 项目删完了
setFileServerEndPointLocalStorage(projectList[0].zoneId); if (projectList.length === 0) {
setProjectInfo(projectList[0]); currentProjectStore.changeProject({});
localStorage.setItem("fileServerEndPoint", "");
setProjectInfo({});
} else {
projectList[0].filetoken = getFiletokenAccordingToId(
projectList[0].id
);
currentProjectStore.changeProject(projectList[0]);
setFileServerEndPointLocalStorage(projectList[0].zoneId);
getFiletokenAccordingToId(projectList[0].id).then((res) => {
projectList[0].filetoken = res;
currentProjectStore.changeProject(projectList[0]);
});
setProjectInfo(projectList[0]);
}
}, },
} }
); );
...@@ -158,6 +226,7 @@ const BaseInfo = observer(() => { ...@@ -158,6 +226,7 @@ const BaseInfo = observer(() => {
// 显示删除弹窗 // 显示删除弹窗
const handleClickDelete = () => { const handleClickDelete = () => {
DialogRef.current.handleClickOpen(); DialogRef.current.handleClickOpen();
setDeleteProjectName("");
}; };
const deleteProjectNameChange = (e: any) => { const deleteProjectNameChange = (e: any) => {
...@@ -181,7 +250,7 @@ const BaseInfo = observer(() => { ...@@ -181,7 +250,7 @@ const BaseInfo = observer(() => {
<Loading /> <Loading />
</div> </div>
); );
} else if (currentUserName !== projectInfo.owner) { } else if (!hasEditAuth) {
return <InformationDisplay infoList={infoList} />; return <InformationDisplay infoList={infoList} />;
} else { } else {
return ( return (
...@@ -195,13 +264,26 @@ const BaseInfo = observer(() => { ...@@ -195,13 +264,26 @@ const BaseInfo = observer(() => {
> >
项目名称 项目名称
</div> </div>
<input <TextField
required
error={nameCheck.error}
id="name"
variant="outlined"
value={projectInfo.name}
onChange={nameChange}
helperText={nameCheck.help}
size="small"
sx={{
width: "560px",
}}
/>
{/* <input
value={projectInfo.name} value={projectInfo.name}
className={style.projectInfoListLiValue} className={style.projectInfoListLiValue}
onChange={nameChange} onChange={nameChange}
maxLength={30} maxLength={30}
placeholder="请输入项目名称" placeholder="请输入项目名称"
></input> ></input> */}
</div> </div>
<div className={style.projectInfoListLi}> <div className={style.projectInfoListLi}>
<div className={style.projectInfoListLiLabel}>项目描述</div> <div className={style.projectInfoListLiLabel}>项目描述</div>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-11 15:24:15 * @LastEditTime: 2022-06-15 19:04:11
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -35,16 +35,9 @@ const AddMember = observer((props: IProps) => { ...@@ -35,16 +35,9 @@ const AddMember = observer((props: IProps) => {
const [projectMember, setProjectMember] = useState(""); const [projectMember, setProjectMember] = useState("");
const [filterTableData, setFilterTableData] = useState([]); const [filterTableData, setFilterTableData] = useState([]);
const [checkData, setCheckData] = useState<string[]>([]); const [checkData, setCheckData] = useState<string[]>([]);
const [selectOptions, setSelectOptions] = useState<IOption[]>([]);
const Message = useMessage(); const Message = useMessage();
const selectOptions = useMemo(() => {
return [
{ value: "VIEWER", label: "查看者" },
{ value: "DEVELOPER", label: "研发者" },
{ value: "MANAGER", label: "管理者" },
];
}, []);
const changePermission = useCallback( const changePermission = useCallback(
(val: IOption, index: number) => { (val: IOption, index: number) => {
const tableDataIndex = tableData[index] as any; const tableDataIndex = tableData[index] as any;
...@@ -56,34 +49,53 @@ const AddMember = observer((props: IProps) => { ...@@ -56,34 +49,53 @@ const AddMember = observer((props: IProps) => {
[tableData] [tableData]
); );
const columns = [ const columns = useMemo(() => {
{ id: "checkbox", width: 50 }, return [
{ id: "username", label: "项目成员", width: 160 }, { id: "checkbox", width: 50 },
{ { id: "username", label: "项目成员", width: 160 },
id: "projectRole", {
label: "项目权限", id: "projectRole",
width: 160, label: "项目权限",
render: (item: string, row: any, index: number) => { width: 160,
const defaultValue = selectOptions.filter( render: (item: string, row: any, index: number) => {
(every) => every.value === item const defaultValue = selectOptions.filter(
); (every) => every.value === item
return ( );
<MySelect return (
input={<OutlinedInput />} <MySelect
value={ input={<OutlinedInput />}
defaultValue?.length value={
? defaultValue[0] defaultValue?.length
: { value: "VIEWER", label: "查看者" } ? defaultValue[0]
} : { value: "VIEWER", label: "查看者" }
onChange={(val) => changePermission(val, index)} }
options={selectOptions} onChange={(val) => changePermission(val, index)}
size="small" options={selectOptions}
/> size="small"
); />
);
},
}, },
}, ];
]; }, [changePermission, selectOptions]);
useEffect(() => {
if (addMemberDialog) {
http.get<IResponse<any>>("/cpp/project/listroles").then((res) => {
const arr = [];
const { data } = res;
for (const key in data) {
arr.push({
label: String(data[key]),
value: key,
});
}
setSelectOptions(arr);
});
}
}, [addMemberDialog, http]);
/** 过滤表格数据 */
useEffect(() => { useEffect(() => {
if (!!projectMember) { if (!!projectMember) {
const newVal = const newVal =
...@@ -96,6 +108,7 @@ const AddMember = observer((props: IProps) => { ...@@ -96,6 +108,7 @@ const AddMember = observer((props: IProps) => {
} }
}, [projectMember, tableData]); }, [projectMember, tableData]);
/** 获取表格数据 */
useEffect(() => { useEffect(() => {
if (!addMemberDialog) return; if (!addMemberDialog) return;
const projectInfo = toJS(currentProjectStore?.currentProjectInfo); const projectInfo = toJS(currentProjectStore?.currentProjectInfo);
...@@ -104,19 +117,20 @@ const AddMember = observer((props: IProps) => { ...@@ -104,19 +117,20 @@ const AddMember = observer((props: IProps) => {
params: { id: projectInfo?.id || "" }, params: { id: projectInfo?.id || "" },
}) })
.then((res) => { .then((res) => {
if (res.data.length) { setTableData(res?.data);
setTableData(res?.data);
}
}); });
}, [currentProjectStore?.currentProjectInfo, http, addMemberDialog]); }, [currentProjectStore?.currentProjectInfo, http, addMemberDialog]);
const onClose = () => { const onClose = (event: any = {}, reason: any = "other") => {
// 点击弹窗外不关闭弹窗
if (reason === "backdropClick") {
return;
}
setAddMemberDialog(false); setAddMemberDialog(false);
}; };
const onConfirm = () => { const onConfirm = () => {
const projectInfo = toJS(currentProjectStore?.currentProjectInfo); const projectInfo = toJS(currentProjectStore?.currentProjectInfo);
console.log(tableData, 1111);
const params = tableData.filter((item: any) => { const params = tableData.filter((item: any) => {
return checkData.includes(item?.username); return checkData.includes(item?.username);
}); });
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-07 15:55:26 * @LastEditTime: 2022-06-15 13:50:54
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -34,10 +34,6 @@ const RemoveItem = observer((props: IProps) => { ...@@ -34,10 +34,6 @@ const RemoveItem = observer((props: IProps) => {
}; };
const onConfirm = () => { const onConfirm = () => {
const projectInfo = toJS(currentProjectStore?.currentProjectInfo); const projectInfo = toJS(currentProjectStore?.currentProjectInfo);
console.log(111111, {
id: projectInfo?.id || "",
username: removeDialog.username,
});
http http
.del<IResponse<any>>( .del<IResponse<any>>(
`/cpp/project/removemember?id=${projectInfo?.id || ""}&username=${ `/cpp/project/removemember?id=${projectInfo?.id || ""}&username=${
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13 * @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-10 18:08:00 * @LastEditTime: 2022-06-16 20:49:14
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -25,8 +25,9 @@ import { IDialogInfo } from "./interface"; ...@@ -25,8 +25,9 @@ import { IDialogInfo } from "./interface";
import { toJS } from "mobx"; import { toJS } from "mobx";
import { useStores } from "@/store"; import { useStores } from "@/store";
import { isProjectOwner } from "@/utils/util"; import { isProjectOwner } from "@/utils/util";
import { observer } from "mobx-react";
const ProjectMembers = () => { const ProjectMembers = observer(() => {
const http = useHttp(); const http = useHttp();
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
...@@ -49,22 +50,18 @@ const ProjectMembers = () => { ...@@ -49,22 +50,18 @@ const ProjectMembers = () => {
const [projectName, setProjectMember] = useState(""); const [projectName, setProjectMember] = useState("");
/** 过滤后数据 */ /** 过滤后数据 */
const [filterTableData, setFilterTableData] = useState([]); const [filterTableData, setFilterTableData] = useState([]);
/** 项目所有者 */
const [projectOwner, setProjectOwner] = useState("");
const columns = useMemo(() => { const columns = useMemo(() => {
const val: any = [ const val: any = [
{ id: "username", label: "成员名称" }, { id: "username", label: "成员名称" },
{ id: "projectRoleDesc", label: "项目权限" }, { id: "projectRoleDesc", label: "项目权限" },
{ id: "phone", label: "联系方式" }, { id: "phone", label: "联系方式" },
]; {
if (isProjectOwner(projectOwner)) {
val.push({
id: "operation", id: "operation",
label: "操作", label: "操作",
width: 160, width: 160,
render: (item: any, row: any) => { render: (item: any, row: any) => {
return projectOwner === row?.username ? null : ( return row?.projectRole === "OWNER" ? null : (
<> <>
<span <span
style={{ color: "#1370FF", cursor: "pointer" }} style={{ color: "#1370FF", cursor: "pointer" }}
...@@ -85,10 +82,10 @@ const ProjectMembers = () => { ...@@ -85,10 +82,10 @@ const ProjectMembers = () => {
</> </>
); );
}, },
}); },
} ];
return val; return val;
}, [projectOwner]); }, []);
/** 获取表格数据 */ /** 获取表格数据 */
const getTableList = useCallback(() => { const getTableList = useCallback(() => {
...@@ -100,7 +97,6 @@ const ProjectMembers = () => { ...@@ -100,7 +97,6 @@ const ProjectMembers = () => {
}) })
.then((res) => { .then((res) => {
const { data = {} } = res; const { data = {} } = res;
setProjectOwner(data.owner);
setTableData(data?.members || []); setTableData(data?.members || []);
}); });
}, [currentProjectStore?.currentProjectInfo, http]); }, [currentProjectStore?.currentProjectInfo, http]);
...@@ -154,7 +150,7 @@ const ProjectMembers = () => { ...@@ -154,7 +150,7 @@ const ProjectMembers = () => {
sx={{ width: 340, height: 32 }} sx={{ width: 340, height: 32 }}
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />} endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/> />
{isProjectOwner(projectOwner) ? ( {currentProjectStore?.currentProjectInfo?.projectRole === "OWNER" ? (
<Button <Button
style={{ backgroundColor: "#1370FF " }} style={{ backgroundColor: "#1370FF " }}
variant="contained" variant="contained"
...@@ -194,6 +190,6 @@ const ProjectMembers = () => { ...@@ -194,6 +190,6 @@ const ProjectMembers = () => {
/> />
</> </>
); );
}; });
export default memo(ProjectMembers); export default memo(ProjectMembers);
...@@ -19,8 +19,6 @@ import Tabs from "@/components/mui/Tabs"; ...@@ -19,8 +19,6 @@ import Tabs from "@/components/mui/Tabs";
const ProjectSetting = observer(() => { const ProjectSetting = observer(() => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const [value, setValue] = useState("projectMember");
const tabList = useMemo(() => { const tabList = useMemo(() => {
return [ return [
{ {
...@@ -36,11 +34,7 @@ const ProjectSetting = observer(() => { ...@@ -36,11 +34,7 @@ const ProjectSetting = observer(() => {
]; ];
}, []); }, []);
const changeTabs = (val: string) => { if (currentProjectStore.currentProjectInfo.name) {
setValue(val);
};
if (currentProjectStore.currentProjectInfo.name || true) {
return ( return (
<div style={{ padding: 24 }}> <div style={{ padding: 24 }}>
<div style={{ display: "flex", alignItems: "center" }}> <div style={{ display: "flex", alignItems: "center" }}>
...@@ -50,7 +44,7 @@ const ProjectSetting = observer(() => { ...@@ -50,7 +44,7 @@ const ProjectSetting = observer(() => {
</span> </span>
</div> </div>
<Box sx={{ width: "100%", typography: "body1" }}> <Box sx={{ width: "100%", typography: "body1" }}>
<Tabs value={value} onChange={changeTabs} tabList={tabList} /> <Tabs tabList={tabList} />
</Box> </Box>
</div> </div>
); );
......
...@@ -18,14 +18,24 @@ import WorkbenchList from "./workbenchList"; ...@@ -18,14 +18,24 @@ import WorkbenchList from "./workbenchList";
import Tabs from "@/components/mui/Tabs"; import Tabs from "@/components/mui/Tabs";
import usePass from "@/hooks/usePass"; import usePass from "@/hooks/usePass";
import Template from "@/assets/project/workbenchTemplate.svg"
import Template_select from "@/assets/project/workbenchTemplate_select.svg"
import List from "@/assets/project/workbenchList.svg"
import List_select from "@/assets/project/workbenchList_select.svg"
//ui
import ButtonDemo from "@/views/mui_demo/button"
import InputDemo from "@/views/mui_demo/input"
const ProjectWorkbench = observer(() => { const ProjectWorkbench = observer(() => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const isPass = usePass(); const isPass = usePass();
const [value, setValue] = useState("workbenchTemplate");
useEffect(() => { useEffect(() => {
console.log(isPass("PROJECT_WORKBENCH_FLOES_USE",'USER'), "11111111111"); console.log(isPass("PROJECT_WORKBENCH_FLOES_USE", 'USER'), "11111111111");
console.log(isPass("PROJECT_WORKBENCH_FLOES"), 'wwwwwwwwwww')
}, []) }, [])
const tabList = useMemo(() => { const tabList = useMemo(() => {
...@@ -34,18 +44,35 @@ const ProjectWorkbench = observer(() => { ...@@ -34,18 +44,35 @@ const ProjectWorkbench = observer(() => {
label: "工作流模版", label: "工作流模版",
value: "workbenchTemplate", value: "workbenchTemplate",
component: <WorkbenchTemplate />, component: <WorkbenchTemplate />,
hide: !isPass("PROJECT_WORKBENCH_FLOES"),
icon: Template,
iconed: Template_select
}, },
{ {
label: "任务列表", label: "任务列表",
value: "workbenchList", value: "workbenchList",
component: <WorkbenchList />, component: <WorkbenchList />,
hide: !isPass("PROJECT_WORKBENCH_JOBS"),
icon: List,
iconed: List_select
},
{
label: "按钮组件",
value: "MUI_BUTTON",
component: <ButtonDemo />,
icon: List,
iconed: List_select
},
{
label: "输入框组件",
value: "MUI_INPUT",
component: <InputDemo />,
icon: List,
iconed: List_select
}, },
]; ];
}, []); }, []);
const changeTabs = (val: string) => {
setValue(val);
};
return ( return (
<div style={{ padding: 24 }}> <div style={{ padding: 24 }}>
...@@ -56,7 +83,7 @@ const ProjectWorkbench = observer(() => { ...@@ -56,7 +83,7 @@ const ProjectWorkbench = observer(() => {
</span> </span>
</div> </div>
<Box sx={{ width: "100%", typography: "body1" }}> <Box sx={{ width: "100%", typography: "body1" }}>
<Tabs value={value} onChange={changeTabs} tabList={tabList} /> <Tabs tabList={tabList} />
</Box> </Box>
</div> </div>
); );
......
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);
.headerBox {
margin-bottom: 20px;
}
.tabHeader {
display: flex;
align-items: center;
}
.tabHeaderSelect {
margin-left: 16px;
}
.body {
margin-top: 24px;
border-top: 1px solid #F0F2F5;
overflow: hidden;
overflow-y: auto;
height: calc(100vh - 290px);
}
.tabBox {
padding: 15px 0px 16px 24px;
display: flex;
align-items: center;
width: 100%;
border-bottom: 1px solid #F0F2F5;
}
.tabBox:hover {
background-color: #F5F6F7;
}
.tabBoxInfo {
width: 24%;
}
.tabBoxDescInfo {
display: flex;
}
.tabBoxTitle {
font-size: 14px;
font-weight: 600;
color: #1E2633;
margin-bottom: 10px;
}
.tabBoxDesc {
font-size: 12px;
font-weight: 400;
color: #8A9099;
}
.tabBoxTime {
font-size: 12px;
font-weight: 400;
color: #565C66;
margin-left: 4px;
}
.tabBoxMiddle {
display: flex;
align-items: center;
width: 10%;
}
.tabBoxJobStatus {
display: flex;
align-items: center;
width: 46%;
}
.tabBoxStatusText {
font-size: 12px;
font-weight: 400;
color: #1E2633;
margin: 0px 16px 0px 6px;
white-space: nowrap;
}
.tabBoxJobOperate {
width: 10%;
display: flex;
justify-content: center;
}
\ No newline at end of file
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css"; import styles from "../index.module.css";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button"; import Button from "@/components/mui/Button";
import Dialog from "@/components/mui/Dialog"; import Dialog from "@/components/mui/Dialog";
import OutlinedInput from "@mui/material/OutlinedInput"; import OutlinedInput from "@mui/material/OutlinedInput";
import SearchIcon from "@mui/icons-material/Search"; import SearchIcon from "@mui/icons-material/Search";
import Checkbox from '@mui/material/Checkbox'; import Checkbox from '@mui/material/Checkbox';
import CloseOutlinedIcon from '@mui/icons-material/CloseOutlined'; import CloseOutlinedIcon from '@mui/icons-material/CloseOutlined';
import noData from '../../../../../assets/project/noTemplate.svg'
import _ from "lodash"; import _ from "lodash";
const AddTemplate = (props: any) => { const AddTemplate = (props: any) => {
...@@ -36,15 +37,22 @@ const AddTemplate = (props: any) => { ...@@ -36,15 +37,22 @@ const AddTemplate = (props: any) => {
endAdornment={<SearchIcon style={{ color: "#8A9099" }} />} endAdornment={<SearchIcon style={{ color: "#8A9099" }} />}
/> />
<Button <Button
style={{ backgroundColor: "#1370FF", marginLeft: "12px" }} click={addTemplateCallback}
variant="contained" size={"small"}
onClick={addTemplateCallback} text={'添加模版' + (selectTemplateData.length === 0 ? "" : `(${selectTemplateData.length})`)}
size="small" />
>
添加模版{selectTemplateData.length === 0 ? "" : `(${selectTemplateData.length})`}
</Button>
</Box> </Box>
{
addTemplateList.length === 0 && <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>
}
<Box sx={{ display: "flex", flexWrap: 'wrap', overflowX: 'hidden', overflowY: 'overlay', marginLeft: '-8px' }} > <Box sx={{ display: "flex", flexWrap: 'wrap', overflowX: 'hidden', overflowY: 'overlay', marginLeft: '-8px' }} >
{ {
addTemplateList.map((item: any, key: any) => { addTemplateList.map((item: any, key: any) => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css"; import styles from "../index.module.css";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button"; import Button from "@/components/mui/Button";
import usePass from "@/hooks/usePass"; import usePass from "@/hooks/usePass";
const TemplateBox = (props: any) => { const TemplateBox = (props: any) => {
...@@ -23,27 +23,15 @@ const TemplateBox = (props: any) => { ...@@ -23,27 +23,15 @@ const TemplateBox = (props: any) => {
display: 'flex', justifyContent: 'end' display: 'flex', justifyContent: 'end'
}} > }} >
{ {
isPass("PROJECT_WORKBENCH_FLOES_USE", 'MANAGER') && <Button isPass("PROJECT_WORKBENCH_FLOES_USE", 'MANAGER') &&
style={{ backgroundColor: "#F0F2F5", color: "#565C66" }} <Button size={"small"} text={'删除模版'} click={() => { props.startDialog(info.id) }} style={{ backgroundColor: "#F0F2F5", color: "#565C66" }} />
variant="contained"
onClick={() => { props.startDialog(info.id) }}
size="small"
>
删除模版
</Button>
} }
{ {
isPass("PROJECT_WORKBENCH_FLOES_USE", 'USER') && <Button isPass("PROJECT_WORKBENCH_FLOES_USE", 'USER') &&
style={{ backgroundColor: "#1370FF", marginLeft: "12px" }} <Button size={"small"} text={'使用模版'} click={() => { }} style={{ marginLeft: "12px" }} />
variant="contained"
// onClick={addTemplateBlock}
size="small"
>
使用模版
</Button>
} }
</Box> </Box>
</Box> </Box >
); );
}; };
......
.headerBox { .headerBox {
/* display: flex;
justify-content: space-between;
align-items: center; */
margin-bottom: 20px; margin-bottom: 20px;
} }
......
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { memo, SetStateAction, useCallback, useEffect, useMemo, useState } from "react";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import styles from "./index.module.css"; import styles from "./index.module.css";
import OutlinedInput from "@mui/material/OutlinedInput"; import OutlinedInput from "@mui/material/OutlinedInput";
import SearchIcon from "@mui/icons-material/Search"; import SearchIcon from "@mui/icons-material/Search";
// import Button from "@/components/mui/Button"; import Button from "@/components/mui/Button";
import Button from "@mui/material/Button"; // import Button from "@mui/material/Button";
import Add from "@mui/icons-material/Add"; import Add from "@mui/icons-material/Add";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import TemplateBox from "./components/templateBox" import TemplateBox from "./components/templateBox"
...@@ -29,9 +29,13 @@ import _ from "lodash"; ...@@ -29,9 +29,13 @@ import _ from "lodash";
import { IResponse, useHttp } from "@/api/http"; import { IResponse, useHttp } from "@/api/http";
import { useStores } from "@/store"; import { useStores } from "@/store";
import usePass from "@/hooks/usePass"; import usePass from "@/hooks/usePass";
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
const ProjectMembers = () => { const ProjectMembers = observer(() => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const projectIdData = toJS(currentProjectStore.currentProjectInfo.id);
const isPass = usePass(); const isPass = usePass();
/** 搜索模板名称 */ /** 搜索模板名称 */
...@@ -92,6 +96,12 @@ const ProjectMembers = () => { ...@@ -92,6 +96,12 @@ const ProjectMembers = () => {
}); });
}, [currentProjectStore.currentProjectInfo.id, getTemplateInfo]); }, [currentProjectStore.currentProjectInfo.id, getTemplateInfo]);
useEffect(() => {
console.log('projectIdData: ', projectIdData);
}, [projectIdData])
/** 点击添加工作流模版 */ /** 点击添加工作流模版 */
const onAddMember = () => { const onAddMember = () => {
// setAddMemberDialog(true); // setAddMemberDialog(true);
...@@ -159,11 +169,17 @@ const ProjectMembers = () => { ...@@ -159,11 +169,17 @@ const ProjectMembers = () => {
} }
const searchChange = (data: any) => {
setTemplateName(data.length > 30 ? data.slice(0, 30) : data);
}
useEffect(() => { useEffect(() => {
getTemplateInfo({ setTimeout(() => {
projectId: currentProjectStore.currentProjectInfo.id as string, getTemplateInfo({
title: templateName projectId: currentProjectStore.currentProjectInfo.id as string,
}); title: templateName
});
}, 300)
}, [templateName]); }, [templateName]);
return ( return (
...@@ -172,10 +188,9 @@ const ProjectMembers = () => { ...@@ -172,10 +188,9 @@ const ProjectMembers = () => {
<Box className={styles.tabBox} > <Box className={styles.tabBox} >
<OutlinedInput <OutlinedInput
onChange={(e: any) => { onChange={(e: any) => {
_.debounce(() => { searchChange(e.target.value)
setTemplateName(e.target.value);
}, 200)();
}} }}
value={templateName}
placeholder="输入关键词搜索" placeholder="输入关键词搜索"
size="small" size="small"
sx={{ width: 340, height: 32 }} sx={{ width: 340, height: 32 }}
...@@ -183,21 +198,14 @@ const ProjectMembers = () => { ...@@ -183,21 +198,14 @@ const ProjectMembers = () => {
/> />
{ {
templateList.length > 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && <Button templateList.length > 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') &&
style={{ backgroundColor: "#1370FF " }} <Button text={'添加工作流模版'} img={<Add />} click={addTemplateBlock} size={'small'} />
variant="contained"
onClick={addTemplateBlock}
startIcon={<Add />}
size="small"
>
添加工作流模版
</Button>
} }
</Box> </Box>
{ {
templateList.length === 0 && !isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && templateList.length === 0 && templateName.length > 0 &&
<Box sx={{ <Box sx={{
display: 'flex', alignItems: 'center', flexDirection: 'column', minHeight: 'calc(100vh - 376px)', display: 'flex', alignItems: 'center', flexDirection: 'column', minHeight: 'calc(100vh - 376px)',
justifyContent: 'center' justifyContent: 'center'
...@@ -216,7 +224,7 @@ const ProjectMembers = () => { ...@@ -216,7 +224,7 @@ const ProjectMembers = () => {
</Box> </Box>
} }
{ {
templateList.length === 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && <Box className={styles.addNewTemplate} templateList.length === 0 && templateName.length === 0 && isPass("PROJECT_WORKBENCH_FLOES_ADD", 'MANAGER') && <Box className={styles.addNewTemplate}
onClick={addTemplateBlock} onClick={addTemplateBlock}
> >
<Add sx={{ color: "#565C66", fontSize: "20px", width: "30px", height: '30px' }} /> <Add sx={{ color: "#565C66", fontSize: "20px", width: "30px", height: '30px' }} />
...@@ -244,6 +252,6 @@ const ProjectMembers = () => { ...@@ -244,6 +252,6 @@ const ProjectMembers = () => {
</Box> </Box>
); );
}; });
export default memo(ProjectMembers); export default memo(ProjectMembers);
...@@ -8,6 +8,10 @@ import { useMessage } from "@/components/MySnackbar"; ...@@ -8,6 +8,10 @@ import { useMessage } from "@/components/MySnackbar";
import { getProjectList } from "../../project"; import { getProjectList } from "../../project";
import { useStores } from "@/store"; import { useStores } from "@/store";
import { checkIsNumberLetterChinese } from "@/utils/util"; import { checkIsNumberLetterChinese } from "@/utils/util";
import {
setFileServerEndPointLocalStorage,
getFiletokenAccordingToId,
} from "@/views/Project/project";
type zoneIdOption = { type zoneIdOption = {
id: string; id: string;
...@@ -18,14 +22,25 @@ const AddProject = (props: any) => { ...@@ -18,14 +22,25 @@ const AddProject = (props: any) => {
const { currentProjectStore } = useStores(); const { currentProjectStore } = useStores();
const message = useMessage(); const message = useMessage();
let DialogRef: any = React.createRef(); let DialogRef: any = React.createRef();
const [name, setName] = useState("");
const [nameCheck, setNameCheck] = useState({
error: false,
help: "",
});
const [desc, setDesc] = useState("");
const [descCheck, setDescCheck] = useState({
error: false,
help: "",
});
const [zoneId, setZoneId] = useState("");
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
const [submitloading, setSubmitloading] = useState(false);
useImperativeHandle(props.onRef, () => { useImperativeHandle(props.onRef, () => {
return { return {
handleClickOpen: handleClickOpen, handleClickOpen: handleClickOpen,
}; };
}); });
const [zoneId, setZoneId] = useState("");
const [zoneIdOptions, setZoneIdOptions] = useState<Array<zoneIdOption>>([]);
// 设置计算区 // 设置计算区
const { run } = useMyRequest(hpczone, { const { run } = useMyRequest(hpczone, {
onSuccess: (result: any) => { onSuccess: (result: any) => {
...@@ -33,7 +48,6 @@ const AddProject = (props: any) => { ...@@ -33,7 +48,6 @@ const AddProject = (props: any) => {
setZoneId(result[0].id || ""); setZoneId(result[0].id || "");
}, },
}); });
const [submitloading, setSubmitloading] = useState(false);
const { run: addProjectRun } = useMyRequest(addProject, { const { run: addProjectRun } = useMyRequest(addProject, {
onBefore: () => { onBefore: () => {
setSubmitloading(true); setSubmitloading(true);
...@@ -45,6 +59,18 @@ const AddProject = (props: any) => { ...@@ -45,6 +59,18 @@ const AddProject = (props: any) => {
message.success("新建项目成功"); message.success("新建项目成功");
const projectList = await getProjectList(); const projectList = await getProjectList();
currentProjectStore.setProjectList(projectList); currentProjectStore.setProjectList(projectList);
let project: any = {};
projectList.forEach((item: any) => {
if (item.name === name) {
project = { ...item };
}
});
currentProjectStore.changeProject(project);
setFileServerEndPointLocalStorage(project.zoneId);
getFiletokenAccordingToId(project.id).then((res) => {
project.filetoken = res;
currentProjectStore.changeProject(project);
});
} }
}, },
onError: () => { onError: () => {
...@@ -58,18 +84,17 @@ const AddProject = (props: any) => { ...@@ -58,18 +84,17 @@ const AddProject = (props: any) => {
const handleClickOpen = () => { const handleClickOpen = () => {
DialogRef.current.handleClickOpen(); DialogRef.current.handleClickOpen();
initData()
}; };
const [name, setName] = useState(""); const initData = () => {
const [nameCheck, setNameCheck] = useState({ setName('')
error: false, setDesc('')
help: "", if (zoneIdOptions.length > 0) {
}); setZoneId(zoneIdOptions[0].id)
const [desc, setDesc] = useState(""); }
const [descCheck, setDescCheck] = useState({ }
error: false,
help: "",
});
const checkName = (name: string) => { const checkName = (name: string) => {
if (name) { if (name) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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