Commit b2e01846 authored by wuyongsheng's avatar wuyongsheng

Merge branch 'feat-20220530-project' into 'release'

Feat 20220530 project

See merge request !2
parents e70beb15 78c54465
...@@ -9,7 +9,7 @@ In the project directory, you can run: ...@@ -9,7 +9,7 @@ In the project directory, you can run:
### `npm start` ### `npm start`
Runs the app in the development mode.\ Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser. Open [http://localhost:8088](http://localhost:8088) to view it in the browser.
The page will reload if you make edits.\ The page will reload if you make edits.\
You will also see any lint errors in the console. You will also see any lint errors in the console.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
"@emotion/react": "^11.9.0", "@emotion/react": "^11.9.0",
"@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/material": "^5.6.4", "@mui/material": "^5.6.4",
"@mui/styles": "^5.8.0", "@mui/styles": "^5.8.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
...@@ -45,11 +46,13 @@ ...@@ -45,11 +46,13 @@
"jest": "^27.4.3", "jest": "^27.4.3",
"jest-resolve": "^27.4.2", "jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0", "jest-watch-typeahead": "^1.0.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.5", "mini-css-extract-plugin": "^2.4.5",
"mobx": "^6.5.0", "mobx": "^6.5.0",
"mobx-react": "^7.4.0", "mobx-react": "^7.4.0",
"mobx-react-lite": "^3.4.0", "mobx-react-lite": "^3.4.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"moment": "^2.29.3",
"postcss": "^8.4.4", "postcss": "^8.4.4",
"postcss-flexbugs-fixes": "^5.0.2", "postcss-flexbugs-fixes": "^5.0.2",
"postcss-loader": "^6.2.1", "postcss-loader": "^6.2.1",
......
...@@ -42,7 +42,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { ...@@ -42,7 +42,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
} }
// Tools like Cloud9 rely on this. // Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 8088;
const HOST = process.env.HOST || "0.0.0.0"; const HOST = process.env.HOST || "0.0.0.0";
if (process.env.HOST) { if (process.env.HOST) {
......
import { BACKEND_API_URI_PREFIX } from './api_prefix' import { BACKEND_API_URI_PREFIX } from "./api_prefix";
const RESTAPI = { const RESTAPI = {
API_USER_FETCH: `${BACKEND_API_URI_PREFIX}/accounts/current`,//获取账户信息 API_USER_FETCH: `${BACKEND_API_URI_PREFIX}/accounts/current`, //获取账户信息
API_PROJECT_LIST: `${BACKEND_API_URI_PREFIX}/cpp/project/list`,//获取产品列表 // API_PRIVILEGE_LIST: `${BACKEND_API_URI_PREFIX}/routes/privilege/list`, //
} API_PROJECT_LIST: `${BACKEND_API_URI_PREFIX}/cpp/project/list`, //获取产品下的项目列表
API_PROJECT_ADD: `${BACKEND_API_URI_PREFIX}/cpp/project/add`, //新增项目
API_CPCE_HPCZONE: `${BACKEND_API_URI_PREFIX}/cpp/cpce/hpczone`, //获取计算区列表
};
export default RESTAPI export default RESTAPI;
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-01 16:57:23
* @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// const AWSPREFIX = "/0xaws"; // const AWSPREFIX = "/0xaws";
// const PRIVATIZATIONPREFIX = "/fileserver" // const PRIVATIZATIONPREFIX = "/fileserver"
// const PRIVATIZATION_API_URI_PREFIX = process.env.NODE_ENV === 'development' ? "http://123.57.131.31" : ""; // const PRIVATIZATION_API_URI_PREFIX = process.env.NODE_ENV === 'development' ? "http://123.57.131.31" : "";
...@@ -24,7 +32,7 @@ switch (process.env.REACT_APP_ENV) { ...@@ -24,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 = "https://www.cloudam.cn"; BACKEND_API_URI_PREFIX = "http://47.57.4.97";
} }
break; break;
} }
......
import request from "@/utils/axios/service"; import request from "@/utils/axios/service";
import Api from "./api_manager" import Api from "./api_manager";
function current() { function current() {
return request({ return request({
...@@ -15,11 +15,16 @@ function menu() { ...@@ -15,11 +15,16 @@ function menu() {
}); });
} }
function product() { type projectListParams = {
product: string;
name?: string;
};
function product(params: projectListParams) {
return request({ return request({
url: Api.API_PROJECT_LIST + "?name=", url: Api.API_PROJECT_LIST,
method: "get", method: "get",
params,
}); });
} }
......
import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios';
import React, { useContext } from 'react';
import _ from 'lodash';
import localStorageKey from '@/utils/localStorageKey';
import { BACKEND_API_URI_PREFIX } from './api_prefix';
export interface IAxiosRequestConfig extends AxiosRequestConfig {
/** 取消全局错误提示 */
noToastWarn?: boolean;
/** 允许截流 */
allowIntercept?: boolean;
}
export type HttpConfig = IAxiosRequestConfig;
export interface IRequest {
method: <T>(config: AxiosRequestConfig) => Promise<T>;
config: IAxiosRequestConfig;
}
export class Http {
instance: AxiosInstance;
/** 请求方法集合
* key-唯一标识
*/
requestList: {
[key: string]: IRequest[];
} = {};
/** 请求锁 */
isRequesting: { [key: string]: boolean } = {};
constructor(defaultConfig: IAxiosRequestConfig = {}) {
this.instance = axios.create(defaultConfig);
}
/** 更新回调函数数组 */
setRequestList = (key: string, params: IRequest) => {
this.requestList = {
[key]: this.requestList[key] ? [...this.requestList[key], params] : [params],
};
};
/** 处理成功请求
* first-首次请求 last-最后一次请求 key-请求路径
*/
handleSuccess = ({ key, resolve, res: firstRes }: { key: string; resolve: any; res: any }) => {
this.isRequesting[key] = false;
const requestLen = this.requestList[key]?.length || 0;
if (requestLen >= 2) {
const first = this.requestList[key][0];
const last = this.requestList[key][requestLen - 1];
if (!_.isEqual(first.config, last.config)) {
// @ts-ignore
last.method<T>(last.config).then((lastRes: AxiosResponse<any>) => {
resolve(lastRes?.data);
});
} else {
resolve(firstRes.data);
}
} else {
resolve(firstRes.data);
}
this.requestList[key] = [];
};
/** 请求截流
* 当多次发起请求并且第一次请求未结束时,若参数完全一致只允许首次请求,不一致在首次结束后,进行最后一次
*/
requestInterception<T>(config: IAxiosRequestConfig): Promise<T> {
const requestMethod = this.instance.request;
const key: string = config.url || '';
return new Promise((resolve, reject) => {
if (this.isRequesting[key]) {
this.setRequestList(key, { method: requestMethod, config });
} else {
this.isRequesting[key] = true;
this.setRequestList(key, { method: requestMethod, config });
requestMethod<T>(config)
.then((res: AxiosResponse<any>) => {
/** 可以接入日志监控 */
// const { code, msg = '' } = res.data;
// if (code !== 200 && code !== 0) {
// this.handleSentry({
// ...sentryParams,
// msg,
// code,
// });
// }
this.handleSuccess({
res,
key,
resolve,
});
})
.catch((e) => {
/** 可以接入日志监控 */
// this.handleSentry({
// ...sentryParams,
// msg: e.error || '',
// code: e.code || '',
// });
reject(e);
});
}
});
}
request<T>(config: IAxiosRequestConfig) {
const requestMethod = this.instance.request<T>(config);
return requestMethod.then((res) => res.data);
}
getConfig(config?: IAxiosRequestConfig) {
let Authorization: string =
`Bearer ` +
JSON.parse(localStorage.getItem(localStorageKey.TOKEN) || "{}")
?.access_token || "";
return {
headers:{'Content-Type': "application/x-www-form-urlencoded",Authorization, ...config?.headers, },...config
}
}
get<T>(url: string, config?: IAxiosRequestConfig) {
if (config?.allowIntercept) {
return this.requestInterception<T>({ url: `${BACKEND_API_URI_PREFIX}${url}`, method: 'GET', ...this.getConfig(config) });
}
return this.request<T>({ url: `${BACKEND_API_URI_PREFIX}${url}`, method: 'GET', ...this.getConfig(config) });
}
patch<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'PATCH', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config) });
}
put<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'PUT', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config) });
}
post<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
if (config?.allowIntercept) {
return this.requestInterception<T>({ method: 'POST', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config) });
}
return this.request<T>({ method: 'POST', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config) });
}
del<T>(url: string, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'DELETE', url: `${BACKEND_API_URI_PREFIX}${url}`, ...this.getConfig(config) });
}
}
const rawHttp = new Http();
const HttpContext = React.createContext<Http>(rawHttp);
export const HttpProvider = HttpContext.Provider;
export function useHttp(raw?: boolean) {
const httpClient = useContext(HttpContext);
return raw ? rawHttp : httpClient;
}
export default rawHttp;
import request from "@/utils/axios/service";
import Api from "./api_manager";
function current() {
return request({
url: Api.API_USER_FETCH,
method: "get",
});
}
function menu() {
return request({
url: "/accounts/menu-mock",
method: "get",
});
}
type projectListParams = {
product: string;
name?: string;
};
// 查询当前用户可以看到的项目列表
const product = (params: projectListParams) => {
return request({
url: Api.API_PROJECT_LIST,
method: "get",
params,
});
};
type addProjectParams = {
product: string;
name: string;
zoneId: string;
desc?: string;
};
// 新增项目
const addProject = (params: addProjectParams) => {
console.log("params", params);
return request({
url: Api.API_PROJECT_ADD,
method: "post",
data: params,
});
};
// 获取计算区列表
const hpczone = () => {
return request({
url: Api.API_CPCE_HPCZONE,
method: "get",
});
};
export { current, menu, product, hpczone, addProject };
<?xml version="1.0" encoding="UTF-8"?>
<svg width="220px" height="143px" viewBox="0 0 220 143" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 6</title>
<defs>
<rect id="path-1" x="0" y="0" width="72.6" height="77" rx="2.2"></rect>
<filter x="-17.2%" y="-16.2%" width="139.9%" height="137.7%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="2" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="4.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0.0553718645 0 0 0 0 0.196954257 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="未创建项目" transform="translate(-720.000000, -376.000000)">
<g id="编组-6" transform="translate(720.000000, 376.000000)">
<rect id="矩形" x="0" y="0" width="220" height="143"></rect>
<g id="img_启动ssh" transform="translate(13.200000, 17.600000)">
<g id="编组-7">
<ellipse id="椭圆形" fill="#F3F9FF" fill-rule="nonzero" opacity="0.55971" cx="90.11849" cy="61.6" rx="90.11849" ry="61.6"></ellipse>
<g id="矩形" transform="translate(16.418490, 12.100000)" fill="#F2F2F5" fill-rule="nonzero">
<rect id="矩形" x="1.95399252e-15" y="0" width="149.6" height="100.1" rx="2.2"></rect>
</g>
<path d="M16.41849,14.3 C16.41849,13.08494 17.40343,12.1 18.61849,12.1 L163.8186,12.1 C165.033,12.1 166.0186,13.08494 166.0186,14.3 L166.0186,24.2 L16.41849,24.2 L16.41849,14.3 Z" id="矩形备份-9" fill="#D9DDE3" fill-rule="nonzero"></path>
<rect id="矩形备份-15" fill="#FFFFFF" fill-rule="nonzero" x="30.71849" y="40.7" width="123.2" height="64.9" rx="1.1"></rect>
<rect id="矩形_2" fill-opacity="0.159801" fill="#136EFA" fill-rule="nonzero" x="36.21849" y="44" width="11" height="11"></rect>
<rect id="矩形备份-2" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="76.91849" y="68.2" width="42.9" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-4" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="76.91849" y="90.2" width="42.9" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-3" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="60.41849" y="68.2" width="11" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-5" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="60.41849" y="90.2" width="11" height="4.4" rx="1.1"></rect>
<rect id="矩形备份" fill-opacity="0.235003" fill="#02CDD1" fill-rule="nonzero" x="50.51849" y="44" width="11" height="11"></rect>
<rect id="矩形备份-34" fill="#FFFFFF" fill-rule="nonzero" x="30.71849" y="28.6" width="123.2" height="8.8" rx="1.1"></rect>
<circle id="椭圆形备份-11" fill="#FFFFFF" fill-rule="nonzero" cx="37.31849" cy="18.7" r="2.2"></circle>
<circle id="椭圆形备份-13" fill="#FFFFFF" fill-rule="nonzero" cx="48.31849" cy="18.7" r="2.2"></circle>
<circle id="椭圆形备份-12" fill="#FFFFFF" fill-rule="nonzero" cx="26.31849" cy="18.7" r="2.2"></circle>
<rect id="矩形备份-21" fill="#4C93FF" fill-rule="nonzero" x="34.01849" y="31.9" width="17.6" height="2.2"></rect>
<rect id="矩形备份-35" fill="#4C93FF" fill-rule="nonzero" x="129.7186" y="33" width="17.6" height="1.65"></rect>
<g id="编组-6" transform="translate(116.518600, 35.200000)" fill-rule="nonzero">
<g id="矩形">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#FFFFFF" xlink:href="#path-1"></use>
</g>
</g>
<circle id="椭圆形_2" stroke-opacity="0.346236" stroke="#136EFA" stroke-width="2.2" cx="43.91849" cy="71.5" r="7.7"></circle>
<circle id="椭圆形备份" fill-opacity="0.753196" fill="#18B267" fill-rule="nonzero" cx="43.91849" cy="92.4" r="7.7"></circle>
<path d="M51.61849,70.4 C51.61849,66.75493 48.66356,63.8 45.01849,63.8" id="形状" stroke="#136EFA" stroke-width="3.3"></path>
<polyline id="路径-7" stroke="#FFFFFF" stroke-width="1.1" points="39.8134 92.9005 42.69518 95.94827 48.19518 90.44827"></polyline>
</g>
<g id="编组备份" transform="translate(131.918600, 59.400000)">
<path d="M16.9103,27.88181 L15.3142,33.44319 L10.5765,33.44319 C10.3422,33.44319 10.1519,33.59356 10.1519,33.77902 L10.1519,34.77463 C10.1519,34.96009 10.3422,35.11079 10.5765,35.11079 L31.5436,35.11079 C31.7768,35.11079 31.9671,34.96009 31.9671,34.77463 L31.9671,33.75636 C31.9671,33.57112 31.7768,33.42075 31.5436,33.42075 L26.1778,33.42075 L24.3529,27.83671 L16.9103,27.88181 Z" id="Fill-1" fill="#136EFA"></path>
<path d="M39.9179,28.787 L1.8447,28.787 C0.825,28.787 0,27.96112 0,26.94219 L0,1.84481 C0,0.82588 0.825,0 1.8447,0 L39.9179,0 C40.9365,0 41.7626,0.82588 41.7626,1.84481 L41.7626,26.94219 C41.7626,27.96112 40.9365,28.787 39.9179,28.787 Z" id="Fill-3" fill="#136EFA"></path>
<polygon id="Fill-5" fill="#FFFFFF" opacity="0.881487" points="1.6357 24.90576 40.0433 24.90576 40.0433 1.41724 1.6357 1.41724"></polygon>
<path d="M21.5248,26.78984 C21.5248,27.12897 21.2509,27.40364 20.911,27.40364 C20.5722,27.40364 20.2972,27.12897 20.2972,26.78984 C20.2972,26.45071 20.5722,26.17604 20.911,26.17604 C21.2509,26.17604 21.5248,26.45071 21.5248,26.78984 Z" id="Fill-7" fill="#EFEFEF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" 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">
<rect id="矩形" fill="#FFFFFF" x="0" y="0" width="32" height="32" rx="4"></rect>
<g id="编组-18备份" transform="translate(6.000000, 6.000000)">
<rect id="矩形" x="0" y="0" width="20" height="20"></rect>
<g id="编组-17" transform="translate(1.666667, 1.800000)">
<path d="M0,12.3158333 L0,6.76916667 C0,6.11833333 0.7125,5.71916667 1.2675,6.05833333 L7.10083333,9.62333333 C7.34916667,9.77416667 7.5,10.0433333 7.5,10.3341667 L7.5,15.8808333 C7.5,16.5316667 6.7875,16.9308333 6.2325,16.5916667 L0.399166667,13.0266667 C0.150833333,12.8758333 0,12.6066667 0,12.3158333 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<path d="M16.6666667,11.9933333 L16.6666667,7.79416667 C16.6666667,6.89833333 16.6666667,6.45 16.4533333,6.2125 C16.3308333,6.07583333 16.1658333,5.98333333 15.985,5.95 C15.6708333,5.89166667 15.2883333,6.12583333 14.5241667,6.5925 L9.84083333,9.455 L9.84083333,9.455 C9.5725,9.61833333 9.43916667,9.7 9.34666667,9.81666667 C9.29166667,9.88583333 9.24833333,9.96333333 9.21833333,10.0458333 C9.16666667,10.1858333 9.16666667,10.3425 9.16666667,10.6566667 L9.16666667,14.8558333 C9.16666667,15.7516667 9.16666667,16.2 9.38,16.4375 C9.5025,16.5741667 9.6675,16.6666667 9.84833333,16.7 C10.1625,16.7583333 10.545,16.5241667 11.3091667,16.0575 L15.9925,13.195 C16.2608333,13.0316667 16.3941667,12.95 16.4866667,12.8333333 C16.5416667,12.7641667 16.585,12.6866667 16.615,12.6041667 C16.6666667,12.4641667 16.6666667,12.3075 16.6666667,11.9933333 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<path d="M2.47083333,3.315 L7.91083333,0.115 C8.17166667,-0.0383333333 8.495,-0.0383333333 8.75583333,0.115 L14.1958333,3.315 C14.7433333,3.6375 14.7433333,4.42916667 14.1958333,4.75166667 L8.75583333,7.95166667 C8.495,8.105 8.17166667,8.105 7.91083333,7.95166667 L2.47083333,4.75166667 C1.92333333,4.42916667 1.92333333,3.6375 2.47083333,3.315 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<circle id="椭圆形" fill="#1370FF" fill-rule="nonzero" cx="14.1666667" cy="13.2" r="3.33333333"></circle>
<line x1="14.1666667" y1="13.2" x2="14.1666667" y2="11.5333333" id="路径" stroke="#FFFFFF" stroke-width="0.8125" stroke-linecap="round"></line>
<line x1="14.1666667" y1="13.2" x2="15.4166667" y2="13.2" id="路径" stroke="#FFFFFF" stroke-width="0.8125" stroke-linecap="round"></line>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 18</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-18">
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
<g id="编组-17" transform="translate(2.000000, 2.160000)">
<path d="M0,14.779 L0,8.123 C0,7.342 0.855,6.863 1.521,7.27 L8.521,11.548 C8.819,11.729 9,12.052 9,12.401 L9,19.057 C9,19.838 8.145,20.317 7.479,19.91 L0.479,15.632 C0.181,15.451 0,15.128 0,14.779 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<path d="M20,14.392 L20,9.353 C20,8.278 20,7.74 19.744,7.455 C19.597,7.291 19.399,7.18 19.182,7.14 C18.805,7.07 18.346,7.351 17.429,7.911 L11.809,11.346 L11.809,11.346 C11.487,11.542 11.327,11.64 11.216,11.78 C11.15,11.863 11.098,11.956 11.062,12.055 C11,12.223 11,12.411 11,12.788 L11,17.827 C11,18.902 11,19.44 11.256,19.725 C11.403,19.889 11.601,20 11.818,20.04 C12.195,20.11 12.654,19.829 13.571,19.269 L19.191,15.834 C19.513,15.638 19.673,15.54 19.784,15.4 C19.85,15.317 19.902,15.224 19.938,15.125 C20,14.957 20,14.769 20,14.392 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<path d="M2.965,3.978 L9.493,0.138 C9.806,-0.046 10.194,-0.046 10.507,0.138 L17.035,3.978 C17.692,4.365 17.692,5.315 17.035,5.702 L10.507,9.542 C10.194,9.726 9.806,9.726 9.493,9.542 L2.965,5.702 C2.308,5.315 2.308,4.365 2.965,3.978 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<circle id="椭圆形" fill="#1370FF" fill-rule="nonzero" cx="17" cy="15.84" r="4"></circle>
<line x1="17" y1="15.84" x2="17" y2="13.84" id="路径" stroke="#FFFFFF" stroke-linecap="round"></line>
<line x1="17" y1="15.84" x2="18.5" y2="15.84" id="路径" stroke="#FFFFFF" 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>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>
</defs>
<g id="1.Base基础/Icon图标/项目设置" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g filter="url(#filter-1)" id="项目设置">
<g>
<path d="M10.3115139,0.785133195 C10.3755597,0.771624135 10.4453689,0.766989913 10.5042749,0.794023758 L10.496,0.792 L12.4222041,1.92660078 C12.4559203,1.95719461 12.4812649,1.99554138 12.4995296,2.03712459 L12.521778,2.10136218 C12.5433438,2.18324054 12.5426377,2.27315196 12.5086525,2.35408221 L12.5086525,2.35408221 L12.5048006,2.36325497 L12.500855,2.37339637 C12.4840295,2.41651602 12.2821914,2.9537808 12.2821914,3.4239819 C12.2821914,4.19023092 12.5792307,4.88335657 13.0540612,5.3859324 C13.5439168,5.90441126 14.2215221,6.22104975 14.9662484,6.22104975 L14.9662484,6.22104975 L14.9972506,6.22104975 C15.0498002,6.28382486 15.076073,6.37642377 15.0946517,6.48033289 C15.1008851,6.51473263 15.25,7.34188133 15.25,8.00533082 C15.25,8.66737979 15.1010676,9.49361375 15.0943199,9.53058939 C15.07605,9.63286911 15.0492782,9.72511901 14.9979973,9.78866221 L14.9979973,9.78866221 L14.9662682,9.78866221 C14.2215791,9.78866221 13.5440039,10.1052781 13.0541588,10.6236657 C12.5792668,11.1262288 12.2822113,11.819322 12.2822113,12.5854135 C12.2822113,13.0633674 12.4859773,13.5981268 12.5029718,13.6411469 L12.5029718,13.6411469 L12.5074956,13.6526223 C12.5434026,13.7339976 12.5443228,13.8251291 12.5223924,13.9079504 C12.5028075,13.9819135 12.4646577,14.0530337 12.4018898,14.099455 L12.405,14.095 L10.4481974,15.2366664 C10.4348404,15.2411364 10.4210591,15.2444698 10.4069281,15.2466857 L10.3635604,15.25 C10.263522,15.25 10.1638019,15.2086135 10.1012748,15.1361523 C9.8023742,14.7872629 8.74070743,13.8890234 7.95899092,13.8890234 C7.23777174,13.8890234 6.20467319,14.6831976 5.82852375,15.113358 C5.78299038,15.1660371 5.71513977,15.1953819 5.64752747,15.2103769 C5.5856678,15.2240961 5.51805495,15.2283952 5.4681655,15.2052094 L5.4681655,15.2052094 L5.464,15.203 L3.57644234,14.0819598 C3.54295021,14.0517742 3.51787907,14.0137663 3.49982514,13.9725262 L3.47783167,13.9088156 C3.45618706,13.8264678 3.45718182,13.735983 3.49128245,13.654389 L3.49128245,13.654389 L3.49560429,13.6438226 L3.50193727,13.6273674 C3.53876372,13.5297751 3.71780868,13.0304496 3.71780868,12.5853924 C3.71780868,11.8193033 3.42075488,11.1262121 2.94586849,10.6236497 C2.45602443,10.1052579 1.77845122,9.7886411 1.03377167,9.7886411 L1.03377167,9.7886411 L1.00292788,9.7886411 C0.950315899,9.72573378 0.923953458,9.6326991 0.904129254,9.52195387 C0.897650311,9.48798028 0.75,8.66482749 0.75,8.0053097 C0.75,7.34441337 0.897848614,6.52032512 0.905715983,6.47853298 C0.923936126,6.37654964 0.950558339,6.28454366 1.00153983,6.22107084 L1.00153983,6.22107084 L1.03377167,6.22107084 C1.7784884,6.22107084 2.45609161,5.9044315 2.94594621,5.38594835 C3.4207711,4.88337328 3.71780868,4.19024958 3.71780868,3.42400299 C3.71780868,3.02238874 3.57391765,2.58082274 3.51757676,2.42371732 L3.49612978,2.36618463 L3.49315408,2.35869169 C3.45683118,2.27204258 3.45656197,2.18287001 3.47809083,2.10170557 C4.57078234,1.37491171 5.22597891,1.07614779 5.67360535,0.949157118 C5.79924532,0.913513324 5.89595722,0.889926603 5.97304559,0.890276597 C6.30133364,1.23618208 7.30122443,2.03357391 8.0410091,2.03357391 C8.79391996,2.03357391 9.82900874,1.20312298 10.1257116,0.879260616 C10.1726744,0.827482687 10.2425344,0.7996829 10.3115139,0.785133195 Z" id="路径" stroke="#8A9099" stroke-width="1.5" fill-rule="nonzero"></path>
<circle id="椭圆形备份" stroke="#8A9099" stroke-width="1.5" cx="8" cy="8" r="2.45"></circle>
</g>
</g>
</g>
</svg>
\ No newline at end of file
/* 修改滚动条样式 */
div::-webkit-scrollbar,
main::-webkit-scrollbar {
width: 8px;
height: 5px !important;
}
div::-webkit-scrollbar-track,
main::-webkit-scrollbar-track {
background-color: #fff;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
}
div::-webkit-scrollbar-thumb,
main::-webkit-scrollbar-thumb {
background-color: #d8d8d8;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
height: 5px !important;
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-04 15:00:09
* @FilePath: /bkunyun/src/components/Material.Ui/Button.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@mui/styles";
import { Typography, Button, Menu, MenuItem } from "@mui/material";
const useStyles = makeStyles({
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: {}
})
const ButtonComponent = (props) => {
const classes = useStyles();
const { img, select, selectCallBack, text, size, click, variant, color, disabled, disableElevation, disableFocusRipple, btnStyle = {}, fontSize = '' } = props;
const [anchorEl, setAnchorEl] = React.useState(null);
const defultClick = (event) => event && event.stoppropagation && event.stoppropagation()
// 更多按钮 点击 弹出菜单
const handleClick = (event) => setAnchorEl(event.currentTarget);
// 关闭更多 menu 弹框
const handleClose = () => setAnchorEl(null);
// 选择更多按钮回调
const handleCloseOption = (item, key) => {
setAnchorEl(null);
selectCallBack && selectCallBack(item, key)
};
return (
<>
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disabled={disabled || false}
disableElevation={disableElevation || false}
disableFocusRipple={disableFocusRipple || false}
classes={{
root: btnStyle.root || classes.root,
label: btnStyle.label || classes.label,
disabled: btnStyle.disabled || classes.disabled,
containedSecondary: btnStyle.containedSecondary || classes.containedSecondary,
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={select ? handleClick : (click || defultClick)}
>
{img || ''}
<Typography style={{ fontSize: fontSize }}>{text || ""}</Typography>
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{
select && select.length > 0 && select.map((item, key) => {
return (
<MenuItem
key={key}
classes={{ root: classes.menuItemRoot }}
onClick={() => handleCloseOption(item, key)}>
{item.text || ""}
</MenuItem>
)
})
}
</Menu>
</>
)
}
ButtonComponent.propTypes = {
size: PropTypes.oneOf(["large", "medium", "small"]),
variant: PropTypes.oneOf(["contained", "outlined", "text"]),
color: PropTypes.oneOf(["default", "inherit", "primary", "secondary"]),
disabled: PropTypes.bool,
disableElevation: PropTypes.bool,
disableFocusRipple: PropTypes.bool,
text: PropTypes.string,
onClick: propTypes.func.isRequired,
};
export default ButtonComponent;
\ No newline at end of file
import 'date-fns';
import React, { useState } from 'react';
import { Grid, Typography } from '@material-ui/core';
import DateFnsUtils from '@date-io/date-fns';
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
} from '@material-ui/pickers';
import makeStyles from "@material-ui/styles/makeStyles";
import frLocale_cn from "date-fns/locale/zh-CN";
import frLocale_en from "date-fns/locale/en-US";
import { isEn } from "../../../commons/utils/helper.js";
const frLocale = isEn() ? frLocale_en : frLocale_cn
const useStyles = makeStyles({
dateInputBox: {
width: "8.125rem",
boxSizing: "border-box",
},
dateInputBody: {
height: "36px !important",
},
root: {
margin: "0",
background: "#FFFFFF",
borderRadius: "4px",
border: "1px solid #D8D8D8",
},
input: {
fontSize: "0.8125rem",
padding: "8px 0 8px 8px",
marginRight: "-10px"
},
label: {
opacity: "0.3",
},
rootButton: {
background: "none",
backgroundColor: "none",
'&:hover': {
background: "none",
backgroundColor: "none"
},
'&:before': {
background: "none",
backgroundColor: "none"
},
'&:hover:before': {
background: "none",
backgroundColor: "none"
},
'&:after': {
background: "none",
backgroundColor: "none"
}
},
underline: {
border: "none",
content: "",
borderBottom: "none",
'&:before': {
border: "none",
content: "",
borderBottomStyle: "none !important",
borderBottom: "none",
},
'&:hover:before': {
border: "none",
content: "",
borderBottom: "none",
},
'&:after': {
border: "none",
content: "",
borderBottom: "none",
}
},
calendar_body: {
display: 'flex',
marginLeft: "-0.5rem",
alignItems: "center",
justifyContent: "center",
marginRight: "10px",
height: "36px",
marginLeft: "10px"
},
lineFiltrate: {
width: '1rem',
height: "1px",
backgroundColor: "#D8D8D8",
margin: "0 0.3125rem"
},
})
export default function MaterialUIPickers(props) {
const { startTime, endTime, DateChange, lastDate } = props;
const [openDatePicker, setOpenDatePicker] = useState({
one: false,
two: false,
})
const classes = useStyles()
const openCalendar = (type, date) => {
setOpenDatePicker({
one: type === 'start' ? date : openDatePicker[`${type === 'start' ? 'one' : 'two'}`],
two: type === 'end' ? date : openDatePicker[`${type === 'start' ? 'one' : 'two'}`],
})
};
const closeCalendar = () => {
setOpenDatePicker({
one: false,
two: false,
})
};
const handleDateChange = (type, date) => {
let d = new Date(date);
DateChange(type, d)
setOpenDatePicker({
one: false,
two: false,
})
}
const Calendar = (type) => {
return (
<Grid container item className={classes.dateInputBox}>
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={frLocale} >
<Grid container justifycontent="space-around" className={classes.dateInputBody}>
<KeyboardDatePicker
disableToolbar
variant="inline"
open={openDatePicker[`${type === 'start' ? 'one' : 'two'}`]}
format={isEn() ? "MM/dd/yyyy" : "yyyy-MM-dd"}
disableFuture
minDate={lastDate ? new Date(lastDate) : new Date("1900-01-01")}
margin="normal"
id="date-picker-inline"
onClick={() => openCalendar(type, true)}
onOpen={() => openCalendar(type, true)}
onClose={() => closeCalendar()}
value={type === 'start' ? startTime : endTime}
onChange={(date) => handleDateChange(type, date)}
InputProps={{
classes: {
input: classes.input,
underline: classes.underline
},
}}
classes={{
root: classes.root
}}
KeyboardButtonProps={{
'aria-label': 'change date',
classes: {
root: classes.rootButton,
label: classes.label
},
}}
/>
</Grid>
</MuiPickersUtilsProvider>
</Grid>
)
}
return (
<Grid className={classes.calendar_body}>
{Calendar('start')}
<Typography className={classes.lineFiltrate}></Typography>
{Calendar('end')}
</Grid>
);
}
\ No newline at end of file
import React from 'react';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { Radio } from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
label: { color: "#383838", fontSize: "14px" },
root: { marginRight: 0 },
radioRoot: { color: "#c9c9c9" },
radioChecked: { color: "#136EFA !important" },
})
const CheckBoxComponent = props => {
const { defaultChecked = false, checkChange, label, color, id, checkBoxStyle = {}, size, disabled, labelPlacement, controllChecked, controllCheckChange, controll, radio, show = true } = props;
const [checked, setChecked] = React.useState(defaultChecked);
const classes = useStyles()
const handleChange = (event) => {
setChecked(event.target.checked);
checkChange && checkChange(event.target.checked)
};
const controllHandleChange = (event) => {
controllCheckChange(event.target.checked)
};
if (!show) return ""
if (controll) {
return (
<FormControlLabel
control={
radio ?
<Radio size={'small'}
classes={{ root: classes.radioRoot, checked: classes.radioChecked }}
checked={controllChecked} onChange={controllHandleChange} /> :
<Checkbox
checked={controllChecked}
onChange={controllHandleChange}
name={id || "name"}
color={color || "primary"}
disabled={disabled || false}
size={size || "medium"}
/>
}
label={label || ""}
labelPlacement={labelPlacement || "end"}
classes={{
label: checkBoxStyle.label || classes.label,
root: checkBoxStyle.root || classes.root,
}}
/>
)
}
return (
<FormControlLabel
control={
<Checkbox
checked={checked}
onChange={handleChange}
name={id || "name"}
color={color || "primary"}
disabled={disabled || false}
size={size || "medium"}
/>
}
label={label || ""}
labelPlacement={labelPlacement || "end"}
classes={{
label: checkBoxStyle.label || classes.label,
root: checkBoxStyle.root || classes.root,
}}
/>
)
}
CheckBoxComponent.propTypes = {
size: PropTypes.oneOf(["medium", "small"]),
disabled: PropTypes.oneOf([true, false]),
};
export default CheckBoxComponent
\ No newline at end of file
import React from "react";
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
import { Typography, Button, Menu, MenuItem } from "@material-ui/core";
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import CheckboxComponent from "@/commons/components/Material.Ui/Checkbox"
import Text from "@/commons/components/Material.Ui/Text"
import { isEn } from "@/commons/utils/helper";
const useStyles = makeStyles({
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: { width: "110px" },
textStyle: { padding: "8px 22px", borderRight: "1px solid rgb(0,44,112,0.2)" },
textStyle_en: { padding: "8px 16px", borderRight: "1px solid rgb(0,44,112,0.2)" },
checkBoxBody: { width: "100%", marginLeft: "0px" }
})
const ButtonComponent = (props) => {
const classes = useStyles();
const { subText, Checked, selectCallBack, text, size, click, variant, color, disabled, disableElevation, disableFocusRipple, btnStyle = {}, fontSize, subClick } = props;
const [anchorEl, setAnchorEl] = React.useState(null);
const defultClick = (event) => event && event.stoppropagation && event.stoppropagation()
// 更多按钮 点击 弹出菜单
const handleClick = (event) => {
console.log(event.currentTarget, 'lllll')
setAnchorEl(event.currentTarget)
}
// 关闭更多 menu 弹框
const handleClose = () => setAnchorEl(null);
// 选择更多按钮回调
const handleCloseOption = (item, key) => {
setAnchorEl(null);
selectCallBack && selectCallBack(item, key)
};
return (
<>
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disabled={disabled || false}
disableElevation={disableElevation || false}
disableFocusRipple={disableFocusRipple || false}
classes={{
root: btnStyle.root || classes.root,
label: btnStyle.label || classes.label,
disabled: btnStyle.disabled || classes.disabled,
containedSecondary: btnStyle.containedSecondary || classes.containedSecondary,
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, boxShadow: "none !important", backgroundColor: "#136EFA", padding: "0px 0px", width: "110px" }}
>
<Typography
className={isEn() ? classes.textStyle_en : classes.textStyle}
style={fontSize ? { fontSize: fontSize } : {}}
onClick={click}
>
{text || ""}</Typography>
<div
style={{ display: "flex", padding: "0px 5px" }}
onClick={handleClick}
>
<ArrowDropDownIcon fontSize={"small"} style={{ color: "#fff" }} />
</div>
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
style={{ marginTop: "47px", marginLeft: isEn() ? "-77px" : "-76px" }}
>
<div style={{ width: "110px" }}>
<CheckboxComponent
defaultChecked={Checked}
label={<Text text={subText} op={"lg"} variant={"body1"} />}
labelPlacement={"end"}
size={"small"}
checkChange={(event) => subClick(event)}
checkBoxStyle={{
root: classes.checkBoxBody
}}
/>
</div>
</Menu>
</>
)
}
ButtonComponent.propTypes = {
size: PropTypes.oneOf(["large", "medium", "small"]),
variant: PropTypes.oneOf(["contained", "outlined", "text"]),
color: PropTypes.oneOf(["default", "inherit", "primary", "secondary"]),
disabled: PropTypes.bool,
disableElevation: PropTypes.bool,
disableFocusRipple: PropTypes.bool,
};
export default ButtonComponent;
\ No newline at end of file
import React, { useMemo } from 'react';
import { withStyles } from '@material-ui/core/styles';
import Dialog from '@material-ui/core/Dialog';
import MuiDialogTitle from '@material-ui/core/DialogTitle';
import MuiDialogContent from '@material-ui/core/DialogContent';
import MuiDialogActions from '@material-ui/core/DialogActions';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import Typography from '@material-ui/core/Typography';
import Slide from '@material-ui/core/Slide';
import ButtonComponent from "@/commons/components/Material.Ui/Button";
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { useTheme } from '@material-ui/core/styles';
import PropTypes from "prop-types";
import { CLOUDE } from "@/commons/utils/constants"
import { useEffect } from 'react';
const styles = (theme) => ({
root: {
margin: 0,
padding: "16px 24px",
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1) - 4,
color: theme.palette.grey[500],
},
});
const DialogTitle = withStyles(styles)((props) => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="body1">{children}</Typography>
{onClose ? (
<IconButton aria-label="close" className={classes.closeButton} onClick={() => onClose(false)}>
<CloseIcon />
</IconButton>
) : null}
</MuiDialogTitle>
);
});
const DialogActions = withStyles(() => ({
root: {
margin: 0,
padding: "16px 24px",
"& > :not(:first-child)": {
marginLeft: "15px"
}
},
}))(MuiDialogActions);
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction={props.direction || "up"} ref={ref} {...props} />;
});
const AlertDialogSlide = props => {
const { open, handleClose, dividers, content, padding = true,confirmDisabled=false, header, canncel = CLOUDE.canncel, confirm = CLOUDE.confirm, fullScreen, scroll, maxWidth, bottom, backAndKey, direction, classes, contentStyle } = props;
const theme = useTheme();
const mediaFull = useMediaQuery(theme.breakpoints.down('sm'));
const [fullWidth, setFullWidth] = React.useState(true);
const DialogContent = withStyles(() => ({
root: {
padding: padding ? "20px 24px 40px" : "0", fontWeight: "400", ...contentStyle
},
dividers: { borderColor: "rgba(34, 34, 34, 0.08)" },
}))(MuiDialogContent);
const otherName = useMemo(() => { return (content) }, [content])
return (
<Dialog
open={open}
classes={classes}
TransitionComponent={Transition}
keepMounted
onClose={() => handleClose(false)}
fullScreen={fullScreen || mediaFull}
scroll={scroll || "paper"}
aria-describedby="dialog"
aria-labelledby="confirmation-dialog-title"
fullWidth={fullWidth}
// disableBackdropClick={backAndKey || true}//点击屏幕外关闭
// disableEscapeKeyDown={backAndKey || true}//按下键盘ESC关闭
maxWidth={maxWidth || "sm"}
>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
{header || ""}
</DialogTitle>
<DialogContent dividers={dividers || true}>
{/* {content || ""} */}
{otherName}
</DialogContent>
{
!bottom && (canncel || confirm) && <DialogActions>
{canncel && <ButtonComponent click={() => handleClose(false)} variant={"outlined"} text={canncel} />}
{confirm && <ButtonComponent click={() => handleClose(1)} text={confirm} disabled={ confirmDisabled || false} />}
</DialogActions>
}
{
bottom && bottom
}
</Dialog>
)
}
AlertDialogSlide.propTypes = {
maxWidth: PropTypes.oneOf([false, "xs", "sm", "md", "lg", "xl"]),
scroll: PropTypes.oneOf(['paper', 'body'])
};
export default AlertDialogSlide
\ No newline at end of file
import React from 'react'
import { Grid , Typography } from '@material-ui/core'
import icondelete from '../../assets/img/iconDelete.svg'
import iconDashboard from '../../assets/img/iconDashboard.svg'
import { makeStyles } from '@material-ui/core'
const Style = makeStyles({
paddingbox:{
borderRadius: '4px',
border:' 1px solid rgba(19, 110, 250, 1)',
cursor:'pointer',
minHeight:'33px',
display:'flex',
alignItems:'center',
// justifyContent:'center'
},
content:{
color:'rgba(19, 110, 250, 1)',
fontSize:'13px',
lineHeight:'17px',
fontWeight:'400',
fontFamily:'PingFangSC-Regular, PingFang SC'
},
img:{
// width:'17px',
marginRight:'4px'
}
})
export default props =>{
const { startIcon = '' , color , onClick , text = '' , marginright = '16px' ,style={} , paddingleft='' } = props
const classes = Style()
const icon = (str)=>{
switch(str){
case 'delete' :
return icondelete;
case 'dashboard':
return iconDashboard;
default:
break;
}
}
return <Grid onClick = {()=>{onClick&&onClick()}} className = {classes.paddingbox}
style={{padding:Boolean(startIcon)?'3px 14px 3px 7px':' 6px 8px ',marginRight:marginright,paddingLeft:paddingleft, ...style}}>
{startIcon&& <img src ={icon(startIcon)} alt ='' className= {classes.img}/>}
<Typography className={classes.content}>{ text }</Typography>
</Grid>
}
\ No newline at end of file
import React from "react";
import TextField from '@mui/material/TextField';
import MenuItem from '@mui/material/MenuItem';
import { makeStyles } from "@mui/styles";
import cx from "classnames"
const useStyles = makeStyles({
MuiOutlinedInputInputLarge: { padding: "13.5px 15px", MozAppearance: 'textfield' },
MuiOutlinedInputInput: { padding: "6px 15px", "&::placeholder": { fontSize: "14px" }, MozAppearance: 'textfield' },
MuiOutlinedInputInputSmall: { padding: "10px 15px", "&::placeholder": { fontSize: "13px" }, MozAppearance: 'textfield' },
MuiOutlinedInputInputXsmall: { padding: "8px 15px", "&::placeholder": { fontSize: "12px" }, MozAppearance: 'textfield' },
outlinedLarge: { transform: "translate(14px, 15.5px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlined: { transform: "translate(14px, 14px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedSmall: { transform: "translate(14px, 11px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedXsmall: { transform: "translate(12px, 11px) scale(1)", fontSize: '13px', fontWeight: '400', color: '#707070' },
notchedOutline: { borderColor: "rgba(216, 216, 216, 1)" },
root: {
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "rgba(19, 110, 250, 0.9)" }
},
},
error: {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#D62C1F !important"
},
},
disabled: {
color: "#E3E3E3 !important",
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" },
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" }
},
},
errorLabel: { color: "#D62C1F !important" },
errorFormHelperTextProps: { color: "#D62C1F !important", fontSize: "12px", lineHeight: '14px' },
SelectPropsright: { textAlign: "right" },
SelectPropscenter: { textAlign: "center" },
SelectPropsleft: { textAlign: "left" },
selectProp: { fontSize: "14px" },
selectPropsLarge: { fontSize: "14px" },
selectPropsSmall: { fontSize: "13px" },
selectPropsXsmall: { fontSize: "12px" },
adornedEnd: { paddingRight: "8px" },
defaultSelectStyle: { fontSize: "14px" }
})
export default props => {
const classes = useStyles();
const { label, type, variant, disabled, onChange, placeholder, value, textAlign, customClass,
autoFocus, defaultValue, error, fullWidth, margin, select, disabledClass, onBlur, selectStyle,
multiline, required, rows, startAdornment, endAdornment, helperText, size, onkeydown, selectSize, onFocus
} = props;
const onChangeDefault = () => { }
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const reSelectSizeBys = (sty) => {
switch (selectSize) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const onBlurDefault = () => {
}
const onFocusDefault = () => { }
if (![undefined, null].includes(value)) {
return (
<TextField
label={label || ""}
autoFocus={autoFocus || false}
type={type || "text"}
value={value || ""}
placeholder={placeholder || ""}
variant={variant || "outlined"}
select={select ? true : false}
disabled={disabled || false}
onChange={onChange || onChangeDefault}
onBlur={onBlur || onBlurDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
onFocus={onFocus || onFocusDefault}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: cx({
width: '320px',
height: '32px',
[classes[resizeBys("MuiOutlinedInputInput")]]: true,
[classes[`SelectProps${textAlign}`]]: textAlign,
[customClass]: customClass,
}),
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: disabledClass || classes.disabled,
adornedEnd: classes.adornedEnd
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || ""
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
SelectProps={{
native: (select && select.native) || false,
classes: {
outlined: textAlign ? classes[`SelectProps${textAlign}`] : classes['SelectPropsleft'],
selectMenu: classes[reSelectSizeBys("selectProps")]
}
}}
>
{
select && select.json && select.json.length > 0 && select.json.map((option, key) => {
return (
<MenuItem key={key} disabled={option.disabled || false} value={option.value} className={selectStyle || classes.defaultSelectStyle}>
{option.label}
</MenuItem>
)
})
}
</TextField>
)
}
return (
<TextField
label={label || ""}
autoFocus={autoFocus || false}
type={type || "text"}
defaultValue={defaultValue || ""}
placeholder={placeholder || ""}
variant={variant || "outlined"}
select={select ? true : false}
disabled={disabled || false}
onChange={onChange || onChangeDefault}
onBlur={onBlur || onBlurDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
onKeyDown={onkeydown || (() => { })}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: cx({
[classes[resizeBys("MuiOutlinedInputInput")]]: true,
[classes[`SelectProps${textAlign}`]]: textAlign,
[customClass]: customClass
}),
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: disabledClass || classes.disabled,
adornedEnd: classes.adornedEnd
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || ""
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
SelectProps={{
native: (select && select.native) || false,
classes: {
outlined: textAlign ? classes[`SelectProps${textAlign}`] : classes['SelectPropsleft'],
}
}}
>
{
select && select.json && select.json.length > 0 && select.json.map((option, key) => {
return (
<MenuItem key={key} disabled={option.disabled || false} value={option.value} className={selectStyle || classes.defaultSelectStyle}>
{option.label}
</MenuItem>
)
})
}
</TextField>
)
}
\ No newline at end of file
import React from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TablePagination from "@material-ui/core/TablePagination";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Checkbox from "@material-ui/core/Checkbox";
import Spin from "@/commons/components/Material.Ui/Spin";
import { CLOUDE } from '@/commons/utils/constants';
import EnhancedTableToolbarComponent from "./Table/EnhancedTableToolbar"
import EnhancedTableHeadComponent from "./Table/EnhancedTableHead"
import { getComparator, stableSort, useStyles } from "./Table/function";
import ActionsComponent from "./Table/ActionsComponent"
import { useEffect } from "react";
import Tooltip from '@material-ui/core/Tooltip';
export default function EnhancedTable(props) {
const classes = useStyles();
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("");
const { headCells, rows, footer = true, elevation1, tableStyle, tableContainerStyle, stickyheader, TableHeadClasses, onRowClick, defaultRow, minHeight = '', borderBottom = '', onDoubleClick, bodyTableCellStyle, headTableCellStyle, cancelHover,
load, size, checkboxData, rowsPerPage = 10, initSelected, page = 0, changePage = function () { }, toolbar, count, param, disabledparam = "id", headTableCellCheckbox, RowHeight = '', CellWidth = '', rowHover, TableNodataPadding = '', TableNodataLineHeight = '' } = props;
const [selected, setSelected] = React.useState(initSelected || []);
const [rowsPerPageOptions, setRowsPerPageOptions] = React.useState(initSelected || [5, 10, 20, 50, { value: -1, label: 'All' }]);
const [spin, setSpin] = React.useState(false)
const [onRow, setOnRow] = React.useState('')
useEffect(() => {
setOnRow(defaultRow)
}, [defaultRow])
const onRowClickDefault = (value) => {
setOnRow(value)
onRowClick(value)
}
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = rows.map((n) => n[param || 'id']);
setSelected(newSelecteds);
checkboxData(newSelecteds);
return;
}
setSelected([]);
checkboxData([]);
};
React.useEffect(() => {
setSpin(load)
}, [load]);
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
checkboxData(newSelected)
setSelected(newSelected);
};
const handleOnPageChange = (event, newPage) => {
changePage(newPage, rowsPerPage);
};
const handleChangeRowsPerPage = (event) => {
changePage(0, parseInt(event.target.value, 10));
};
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
return (
<div className={classes.root}>
<Paper className={classes.paper} classes={{ elevation1: elevation1 || classes.elevation1 }} >
<Spin spin={spin} />
{toolbar && toolbar}
<TableContainer style={{ ...tableContainerStyle }}>
<Table stickyHeader={stickyheader || false} className={classes.table} style={{ ...tableStyle }} aria-labelledby="tableTitle" size={size || "medium"} aria-label="cloudam table header" >
<EnhancedTableHeadComponent
classes={classes}
{...props}
numSelected={selected.length}
headTableCellCheckbox={headTableCellCheckbox}
headTableCell={headTableCellStyle}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={rows.length}
headCells={headCells || []}
/>
<TableBody>
{
(rows.length === 0 && !load) && <TableRow>
<TableCell
colSpan={headCells.filter(k => k.id === "checkbox").length === 0 ? headCells.length : headCells.length + 1}
className={classes.TypographyStyle}
style={{ minHeight: minHeight, height: minHeight, borderBottom: borderBottom, padding: TableNodataPadding, lineHeight: TableNodataLineHeight }}
>
No Data
</TableCell>
</TableRow>
}
{stableSort(rows, getComparator(order, orderBy)).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row, index) => {
const isItemSelected = isSelected(row[param || "id"]);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover={rowHover ? false : (row[disabledparam || "enabled"] ? true : false)}
onClick={(event) => {
if (!row[disabledparam]) return;
onRowClick && onRowClickDefault(row[param || "id"])
headCells.filter(k => k.id === "checkbox").length > 0 && handleClick(event, row[param || "id"])
}}
onDoubleClick={() => {
onDoubleClick && onDoubleClick(row)
}}
style={{
height: RowHeight,
border: onRow === row[param || "id"] ? !row[disabledparam] ? "" : '1px solid #136EFA' : "",
backgroundColor: onRow === row[param || "id"] ? !row[disabledparam] ? "rgba(255, 255, 255, 0.4)" : "rgba(19, 110, 250, 0.1)" : "",
cursor: props.cursor ? (row[props.cursor] ? "pointer" : "auto") : (onRowClick ? !row[disabledparam] ? "no-drop" : "pointer" : "auto"),
opacity: !row[disabledparam] ? 0.3 : 1
}}
classes={{
root: cancelHover && classes.cancelHoverStyle
}}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row[param || "id"]}
selected={isItemSelected}
>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell padding="checkbox">
<Checkbox color={"primary"} checked={isItemSelected} inputProps={{ "aria-labelledby": labelId }} />
</TableCell>
}
{
headCells.map((item, k) => {
let subscript = rows.findIndex((e) => e[item.id] === 'merge')
if (index !== subscript && row[item.id] === 'merge') return null
return (
<TableCell key={k} component="th" id={labelId + k}
style={{ width: CellWidth, textAlign: item.numeric ? "right" : "left", paddingRight: item.sort && item.numeric ? "40px" : "", boxSizing: "border-box" }}
scope="row"
rowSpan={(row[item.id] === 'merge') ? (rows.length - (index)) : 1}
padding={item.disablePadding ? "none" : "default"}
classes={{
body: bodyTableCellStyle || classes.bodyTableCell,
}}
> {row[item.id] === 'merge' ? ((item.id === 'parallelFileSystem' && rows[0].parallelFileSystem === "merge") ? CLOUDE.chargesText16 : "") : row[item.id]}</TableCell>
)
})
}
</TableRow>
);
})}
{/* {emptyRows > 0 && (
<TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)} */}
</TableBody>
</Table>
</TableContainer>
{
footer && <TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={count || rows.length}
rowsPerPage={rowsPerPage}
page={page}
ActionsComponent={ActionsComponent}
onChangePage={handleOnPageChange}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
}
</Paper>
</div>
);
}
import React, { useState, useEffect, useRef } from "react";
import TextField from '@material-ui/core/TextField';
import cx from "classnames"
import { makeStyles } from '@material-ui/core/styles';
import { Grid, List, ListItem, ListItemText, Chip } from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
const useStyles = makeStyles({
MuiOutlinedInputInputLarge: { padding: "13.5px 15px" },
MuiOutlinedInputInput: { padding: "12px 15px" },
MuiOutlinedInputInputSmall: { padding: "10px 15px" },
outlinedLarge: { transform: "translate(14px, 15.5px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlined: { transform: "translate(14px, 14px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedSmall: { transform: "translate(14px, 11px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
notchedOutline: { borderColor: "rgba(216, 216, 216, 1)" },
root: {
width: "100%",
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "rgba(19, 110, 250, 0.9)" }
},
},
error: {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#D62C1F !important"
},
},
disabled: {
color: "#E3E3E3 !important",
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" },
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" }
},
},
errorLabel: { color: "#D62C1F !important" },
errorFormHelperTextProps: { color: "#D62C1F !important", fontSize: "12px" },
wrap: { width: "100%", position: "relative" },
contentWrap: {
padding: "8px 0", height: 0, transition: "all 1s", position: "absolute", zIndex: 9, width: "100%",
backgroundColor: "#FFFFFF", boxShadow: "0px 2px 3px 0px rgba(0, 0, 0, 0.16)", borderRadius: "4px",
overflowY: "scroll",
maxHeight: "398px"
},
contentWrapOpenPosition:{top:"-400px"},
contentWrapOpen: { height: "auto" },
ArrowDropDownIconRoot: { transition: "all 0.2s", transform: "rotate(0)", position: "absolute", right: "15px", top: "6px" },
ArrowDropDownIconRootOpen: { transform: "rotate(180deg)" },
inputWrap: { position: "relative" },
checked: { color: "#136EFA !important" }
})
let time = null;
export default props => {
const classes = useStyles();
const { label, type, variant, disabled, onChange, placeholder, autoFocus, defaultValue, error, fullWidth, margin, multiline, required, rows, startAdornment, endAdornment, helperText, size, option, callback, values = [], inputValue } = props;
const [open, setOpen] = useState(false)
const [curDomBottom, setCurDomBottom] = useState('')
const onChangeDefault = (e) => {
onChange && throttle(e.target.value)
}
const handleMouseUp = (event) => {
setOpen(false)
event && event.stopPropagation()
}
//节流
const throttle = (e) => {
if (!time) {
time = setTimeout(() => {
onChange(e)
time = null
}, 400);
}
}
const inputEl = useRef(null);
useEffect(() => {
window.addEventListener('click', handleMouseUp, false)
return () => window.removeEventListener('click', handleMouseUp, false)
}, [])
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
default:
return sty;
}
}
// 获取当前 元素距离底部位置
const scrollFun = (sty) => {
let dom = inputEl.current;
const height = window.innerHeight //可视区窗口高度
const curDomHeight = dom.offsetHeight
// const curDomHeight = dom.getBoundingClientRect().height
const curDomY = dom.getBoundingClientRect().y
const curDomBottom = height - curDomHeight - curDomY
if( curDomBottom<400 ){
setCurDomBottom("top")
}else setCurDomBottom("")
}
const selectClick = (e, item) => {
callback && callback(item)
}
return (
<Grid ref={inputEl} className={cx({ [classes.wrap]: true, })} onClick={(e) => e.stopPropagation()}>
<Grid className={cx({ [classes.inputWrap]: true, })}>
<TextField
onFocus={() => {
scrollFun()
setOpen(true);
}}
label={label || ""}
style={{ width: "100%" }}
autoFocus={autoFocus || false}
defaultValue={defaultValue || ""}
type={type || "text"}
placeholder={placeholder || ""}
variant={variant || "outlined"}
disabled={disabled || false}
onChange={onChangeDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: classes[resizeBys("MuiOutlinedInputInput")],
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: classes.disabled
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || "",
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
/>
<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />
</Grid>
{
open && inputValue !== "" && (
<Grid onClick={(e) => e.stopPropagation()} className={cx({
[classes.contentWrap]: true,
[classes.contentWrapOpen]: open,
[classes.contentWrapOpenPosition]: curDomBottom==="top",
})
} id="select-wrap-content">
<Grid className={classes.gridScroll}>
<List component="nav" className={classes.root} aria-label="contacts">
{
option && option.map((item, key) => {
return (
<ListItem
selected={values.filter(k => k.value === item.value).length > 0}
classes={{ root: classes.rootListItem }} key={key} button
onClick={(event) => selectClick(event, item)}
>
<ListItemText primary={item.label} />
<Checkbox
checked={values.filter(k => k.value === item.value).length > 0}
onChange={(event) => selectClick(event, item)}
classes={{
checked: classes.checked
}}
/>
</ListItem>
)
})
}
</List>
</Grid>
</Grid>
)
}
</Grid >
)
}
\ No newline at end of file
import React, { useState, useEffect } from "react";
import Selectzone from './Selectzone.jsx'
import { Grid, Typography, List, ListItem, ListItemText } from '@mui/material';
import { makeStyles } from "@mui/styles";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import cx from "classnames"
const useStyles = makeStyles({
wrapHeightLarge: { height: "44px" },
wrapHeight: { height: "40px" },
wrapHeightSmall: { height: "36px" },
wrapHeightXsmall: { height: "32px" },
wrap: { width: "100%", position: "relative" },
noBorderwrap: { width: "125px", position: "relative" },
noBorderEnwrap: { width: "165px", position: "relative" },
inputWrap: {
display: "flex", justifyContent: "space-between", alignItems: "center", background: "#FFFFFF", borderRadius: '4px', border: "1px solid #D8D8D8",
cursor: "pointer", padding: "0 15px",
"&:hover": { borderColor: "#136EFA" }
},
noBorderinputWrap: {
display: "flex", justifyContent: "space-between", alignItems: "center", background: "#FFFFFF",
cursor: "pointer", padding: "0",
},
inputHeightLarge: { height: "44px" },
inputHeight: { height: "40px" },
inputHeightSmall: { height: "36px" },
inputHeightXsmall: { height: "32px" },
inputWrapOpen: { border: "1px solid #136EFA" },
text: { color: "#1B1B1B", fontSize: '14px', fontWeight: 400 },
ArrowDropDownIconRoot: { transition: "all 0.2s", transform: "rotate(0)" },
ArrowDropDownIconRootOpen: { transform: "rotate(180deg)" },
contentWrap: {
padding: "8px 0", height: 0, transition: "all 1s", position: "absolute", zIndex: 9, width: "100%",
backgroundColor: "#FFFFFF", boxShadow: "0px 2px 3px 0px rgba(0, 0, 0, 0.16)", borderRadius: "4px",
overflowY: "auto",
maxHeight: "400px"
},
contentWrapOpen: { height: "auto" },
rootListItem: { width: "100%", paddingRight: "0px" },
root: { flex: '1 1 auto', minWidth: 0, color: '#222', marginTop: '4px', marginBottom: '4px' },
primary: { fontSize: "14px" },
lg: { fontSize: "16px" },
sm: { fontSize: "13px" },
md: { fontSize: "12px" },
selected: {
// background:'red',
// color:'red'
}
})
export default props => {
const classes = useStyles();
const { value, size, option, callback, noBorder, rootStyle, customSvg, textStyle, sz, startIcon, DropdownboxStyle, DropdownboxitemStyle } = props;
const [open, setOpen] = useState(false)
const [values, setValue] = useState(value || '请选择')
const handleClick = (event) => {
event.stopPropagation()
setOpen((open) => !open)
}
const handleMouseUp = (event) => {
setOpen(false)
event && event.stopPropagation()
}
useEffect(() => {
window.addEventListener('click', handleMouseUp, false)
return () => window.removeEventListener('click', handleMouseUp, false)
}, [])
useEffect(() => {
setValue(value)
}, [value])
const selectClick = (event, item) => {
setValue(item.label)
callback && callback(item)
handleMouseUp()
event.stopPropagation()
}
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const reBorder = (sty) => {
switch (noBorder) {
case "true_cn":
return "noBorder" + sty;
case "true_en":
return "noBorderEn" + sty;
default:
return sty;
}
}
const fontsizeFun = () => {
switch (sz) {
case 'lg':
case 'sm':
case 'md':
return sz;
default:
return "primary"
}
}
return (
<Grid className={
cx({
[classes[reBorder('wrap')]]: true,
[classes[resizeBys("wrapHeight")]]: true,
})
} onClick={(e) => e.stopPropagation()}>
<Grid onClick={handleClick} className={
cx({
[classes[resizeBys('inputHeight')]]: true,
[classes[reBorder('inputWrap')]]: true,
[classes.inputWrapOpen]: open && !noBorder
})
}
style={{ ...rootStyle }}
>
{startIcon && startIcon}
<Typography className={classes.text} style={{ ...textStyle }}>{values || '请选择'}</Typography>
{
customSvg ? (
(
<div style={{ ...customSvg }}>
<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />
</div>
)
) : (<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />)
}
</Grid>
{
open && (
<Grid onClick={(e) => e.stopPropagation()} className={
cx({
[classes.contentWrap]: true,
[classes.contentWrapOpen]: open
})
} style={{ ...DropdownboxStyle, DropdownboxitemStyle }} id="select-wrap-content">
<Grid className={classes.gridScroll}>
<List component="nav" className={classes.root} aria-label="contacts">
{
option && option.map((item, key) => {
return (
<ListItem
selected={values === item.label}
classes={{ root: classes.rootListItem, selected: classes.selected }} key={key} button
style={{ ...DropdownboxitemStyle }}
onClick={(event) => selectClick(event, item)}
>
{item.icon ? <Selectzone Icon={item.icon} selected={values === item.label} key={key} classes={{ root: classes.rootListItem, popper: classes.popper, primary: classes[fontsizeFun()] }} selectClick={selectClick} item={item} /> : <ListItemText primary={item.label}
classes={{ primary: classes[fontsizeFun()] }}
/>}
</ListItem>
)
})
}
</List>
</Grid>
</Grid>
)
}
</Grid >
)
}
\ No newline at end of file
This diff is collapsed.
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-05 16:39:01
* @FilePath: /bkunyun/src/components/Material.Ui/Selectzone.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React, { useState, useEffect } from "react";
import { makeStyles } from '@mui/styles';
import {
Grid,
ListItemText,
Tooltip,
} from "@mui/material";
import icon from "@/assets/img/icon_about_grey.png";
const useStyles = makeStyles({
popper:{fontSize:'12px'}
})
export default props => {
const classesstyle=useStyles()
const { item, classes , Icon , selected } = props;
const [hover, sethover] = useState(false);
const [select,setselect] = useState(false)
useEffect(() => {
setselect(selected?true:false)
}, [selected]);
const move = () => {
!hover&&sethover(true)
};
const leave = () => {
hover&&sethover(false)
};
return (
<Grid
onMouseEnter={move}
onMouseLeave ={leave}
style={{display:'flex',alignItems:"center",justifyContent:'space-between',width:"100%",background:Icon === 'dashBoard' &&selected?'rgba(25, 28, 31, 1)':''}}
>
{
Icon === 'dashBoard' && <Grid style={{
width:'2px',
height:'34px',
marginRight:'13px',
background:selected?'linear-gradient(180deg, #F05A28 0%, #FBC40D 100%)':'transparent',
}}></Grid>
}
<ListItemText
primary={item.label}
classes={{ primary: classes.primary }}
/>
{Icon !=='dashBoard' &&item.description&&hover&&<Tooltip
arrow
placement={'top'}
classes={{
tooltip: classesstyle.popper,
}}
title={item.description?item.description:""}><img src={item.src?item.src:icon} alt='' style={{ width: "16px",height:'16px', marginRight: "10px" ,marginLeft:'auto'}}/></Tooltip>}
</Grid>
);
};
import React from "react";
import "./css/Spin.css";
export default (props) => {
const { spin, relative } = props;
if (!spin) return ""
return (
<div className="ant-spin ant-spin-spinning ant-spin-show-text" style={{ position: relative ? "relative" : "" }}>
<span className="ant-spin-dot ant-spin-dot-spin">
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
</span>
<div className="ant-spin-text">Loading...</div>
<div className="ant-spin-background">
</div>
</div>
)
}
\ No newline at end of file
import React from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox";
// import Spin from "./Spin";
import EnhancedTableToolbarComponent from "./Table/EnhancedTableToolbar"
import EnhancedTableHeadComponent from "./Table/EnhancedTableHead"
import { getComparator, stableSort, useStyles } from "./Table/function";
import ActionsComponent from "./Table/ActionsComponent"
import { useEffect } from "react";
export default function EnhancedTable(props) {
const classes = useStyles;
console.log(classes,11111);
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("");
const { headCells, rows, footer = true, elevation1, tableStyle,tablecellstyle, tableContainerStyle, stickyheader, TableHeadClasses, onRowClick, defaultRow, minHeight='', borderBottom='', onDoubleClick,
load, size, checkboxData, rowsPerPage = 10, initSelected, page = 0, changePage = function () { }, toolbar, count, param, disabledparam = "id", headTableCellCheckbox ,RowHeight='',CellWidth='',rowHover, TableNodataPadding = '',TableNodataLineHeight=''} = props;
const [selected, setSelected] = React.useState(initSelected || []);
const [rowsPerPageOptions, setRowsPerPageOptions] = React.useState(initSelected || [5, 10, 20, 50, { value: -1, label: 'All' }]);
// const [spin, setSpin] = React.useState(false)
const [onRow, setOnRow] = React.useState('')
useEffect(() => {
setOnRow(defaultRow)
}, [defaultRow])
const onRowClickDefault = (value) => {
setOnRow(value)
onRowClick(value)
}
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = rows.map((n) => n[param || 'id']);
setSelected(newSelecteds);
checkboxData(newSelecteds);
return;
}
setSelected([]);
checkboxData([]);
};
// React.useEffect(() => {
// setSpin(load)
// }, [load]);
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
checkboxData(newSelected)
setSelected(newSelected);
};
const handleOnPageChange = (event, newPage) => {
changePage(newPage, rowsPerPage);
};
const handleChangeRowsPerPage = (event) => {
changePage(0, parseInt(event.target.value, 10));
};
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
return (
<div className={classes.root}>
<Paper className={classes.paper} classes={{ elevation1: elevation1 || classes.elevation1 }} >
{/* <Spin spin={spin} /> */}
{toolbar && toolbar}
<TableContainer style={{ ...tableContainerStyle }}>
<Table stickyHeader={stickyheader || false} className={classes.table} style={{ ...tableStyle }} aria-labelledby="tableTitle" size={size || "medium"} aria-label="cloudam table header" >
<EnhancedTableHeadComponent
classes={classes}
{...props}
numSelected={selected.length}
headTableCellCheckbox={headTableCellCheckbox}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={rows.length}
headCells={headCells || []}
/>
<TableBody>
{
(rows.length === 0 && !load) && <TableRow>
<TableCell
colSpan={headCells?.filter(k => k.id === "checkbox")?.length === 0 ? headCells?.length : headCells?.length + 1}
className={classes.TypographyStyle}
style={{ minHeight: minHeight, height: minHeight, borderBottom: borderBottom ,padding:TableNodataPadding,lineHeight:TableNodataLineHeight}}
>
No Data
</TableCell>
</TableRow>
}
{stableSort(rows, getComparator(order, orderBy)).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row, index) => {
const isItemSelected = isSelected(row[param || "id"]);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover={ rowHover ? false : (row[disabledparam || "enabled"] ? true : false)}
onClick={(event) => {
if (!row[disabledparam]) return;
onRowClick && onRowClickDefault(row[param || "id"])
headCells.filter(k => k.id === "checkbox").length > 0 && handleClick(event, row[param || "id"])
}}
onDoubleClick={() => {
onDoubleClick && onDoubleClick(row)
}}
style={{
height:RowHeight,
border: onRow === row[param || "id"] ? !row[disabledparam] ? "" : '1px solid #136EFA' : "",
backgroundColor: onRow === row[param || "id"] ? !row[disabledparam] ? "rgba(255, 255, 255, 0.4)" : "rgba(19, 110, 250, 0.1)" : "",
cursor: props.cursor ? (row[props.cursor] ? "pointer" : "auto") : (onRowClick ? !row[disabledparam] ? "no-drop" : "pointer" : "auto"),
}}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row[param || "id"]}
selected={isItemSelected}
>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell padding="checkbox">
<Checkbox color={"primary"} checked={isItemSelected} inputProps={{ "aria-labelledby": labelId }} />
</TableCell>
}
{
headCells.map((item, k) => {
return (
<TableCell key={k} component="th" id={labelId + k}
// align={}
style={{ width:CellWidth, textAlign: item.numeric ? "right" : "left", paddingRight: item.sort && item.numeric ? "40px" : "",border:tablecellstyle }}
scope="row"
padding={item.disablePadding ? "none" : "default"}
classes={{
body: props.bodyTableCell || classes.bodyTableCell
}}
> {
item.render ? <>{item.render(row,index)}</> :
row[item.id]
}
</TableCell>
)
})
}
</TableRow>
);
})}
{/* {emptyRows > 0 && (
<TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)} */}
</TableBody>
</Table>
</TableContainer>
{
footer && <TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={count || rows.length}
rowsPerPage={rowsPerPage}
page={page}
ActionsComponent={ActionsComponent}
onChangePage={handleOnPageChange}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
}
</Paper>
</div>
);
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 10:16:28
* @FilePath: /bkunyun/src/components/Material.Ui/Table/ActionsComponent.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from 'react';
import PropTypes from 'prop-types';
import Button from "@mui/material/Button";
import IconButton from '@mui/material/IconButton';
import FirstPageIcon from '@mui/icons-material/FirstPage';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import LastPageIcon from '@mui/icons-material/LastPage';
import { makeStyles } from "@mui/styles";
const useStyles = makeStyles({
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" },
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" }
})
const TablePaginationActionsConsole = props => {
const classes = useStyles();
const { count, page, rowsPerPage, onChangePage } = props;
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
}
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
}
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
}
const btnClick = (event, item) => {
onChangePage(event, item);
}
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
}
const buttons = (count, page, rowsPerPage) => {
let max = 1;
if( rowsPerPage !== -1 ){
max = count % rowsPerPage === 0 ? count / rowsPerPage : parseInt(count / rowsPerPage) + 1;
}
let arr = [...Array(max).keys()];
return arr.map((item) => {
if (item - 4 <= page && item + 4 >= page && count > 4)
return <Button
key={item}
onClick={() => btnClick('', item)}
style={{ minWidth: '28px', marginRight: "3px", marginLeft: "3px", minHeight: '28px', lineHeight: '28px', fontSize: "12px", border: page === item ? "1px solid #136EFA" : "1px solid #D8D8D8", color: page === item ? "#fff" : "#111111", background: page === item ? '#136EFA' : "#fff", borderRadius: "2px", padding: '0' }}>
{item + 1}
</Button>
return ""
})
}
return (
<div style={{ flexShrink: 0, }}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
className={classes.firstPageIconStyle}
aria-label="first page"
>
<FirstPageIcon />
</IconButton>
<IconButton
className = { classes.KeyboardArrowLeftStyle }
onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
<KeyboardArrowLeft />
</IconButton>
{
buttons(count, page, rowsPerPage)
}
<IconButton
onClick={handleNextButtonClick}
className={classes.keyboardArrowRightStyle}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
<KeyboardArrowRight />
</IconButton>
<IconButton
className={classes.lastPageIconStyle}
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
<LastPageIcon />
</IconButton>
</div>
);
}
TablePaginationActionsConsole.propTypes = {
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
};
export default TablePaginationActionsConsole
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 10:19:08
* @FilePath: /bkunyun/src/components/Material.Ui/Table/EnhancedTableHead.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import TableHead from "@mui/material/TableHead";
import TableSortLabel from "@mui/material/TableSortLabel";
import PropTypes from "prop-types";
import TableRow from "@mui/material/TableRow";
import TableCell from "@mui/material/TableCell";
import Checkbox from "@mui/material/Checkbox";
import Typography from "@mui/material/Typography";
import Tooltip from '@mui/material/Tooltip';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
const EnhancedTableHead = (props) => {
const { classes, onSelectAllClick, order, orderBy, TableHeadClasses, numSelected, rowCount, onRequestSort, headCells, headTableCell, headTableCellCheckbox,RowStyle } = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead classes={{ root: TableHeadClasses || classes.TableHeadClasses }}>
<TableRow style={{...RowStyle}}>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell padding="checkbox">
<Checkbox
color={'primary'}
indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount}
onChange={onSelectAllClick}
inputProps={{ "aria-label": "select all desserts" }}
/>
</TableCell>
}
{headCells.map((headCell,k) => (
<TableCell
key={headCell.id}
style={{ width: headCell.width ? headCell.width : "", textAlign: headCell.numeric ? "right" : "left", display: headCell.id !== "checkbox" ? "" : "none" }}
padding={headCell.disablePadding ? "none" : "default"}
sortDirection={orderBy === headCell.id ? order : false}
classes={{ head:( k && headTableCell) || classes.headTableCell }}
>
{
headCell.sort && <TableSortLabel active={orderBy === headCell.id} direction={order} onClick={createSortHandler(headCell.id)} >
{headCell.label}
</TableSortLabel>
}
{
!headCell.sort && <Typography className={headTableCellCheckbox || ''} style={headCell.tooltip ? { display: "flex", alignItems: "center" } : {}} >
{headCell.label}
{headCell.tooltip ? <Tooltip title={headCell.tooltip} placement="top" arrow>
<ErrorOutlineIcon style={{ fontSize: "16px",marginLeft:"5px" }} fontSize="small" />
</Tooltip> : ""}
</Typography>
}
</TableCell>
))}
</TableRow>
</TableHead>
);
}
EnhancedTableHead.propTypes = {
classes: PropTypes.object.isRequired,
numSelected: PropTypes.number.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
export default EnhancedTableHead
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 10:18:54
* @FilePath: /bkunyun/src/components/Material.Ui/Table/EnhancedTableToolbar.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import { useToolbarStyles } from "./function";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import PropTypes from "prop-types";
import clsx from "clsx";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import DeleteIcon from "@mui/icons-material/Delete";
import FilterListIcon from "@mui/icons-material/FilterList";
const EnhancedTableToolbar = (props) => {
const classes = useToolbarStyles();
const { numSelected } = props;
return (
<Toolbar
className={clsx(classes.root, { [classes.highlight]: numSelected > 0 })}
>
{numSelected > 0 ? (
<Typography
className={classes.title}
color="inherit"
variant="subtitle1"
component="div"
>
{numSelected} selected
</Typography>
) : (
<Typography
className={classes.title}
variant="h6"
id="tableTitle"
component="div"
>
Nutrition
</Typography>
)}
{numSelected > 0 ? (
<Tooltip title="Delete">
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</Tooltip>
) : (
<Tooltip title="Filter list">
<IconButton aria-label="filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)}
</Toolbar>
);
};
EnhancedTableToolbar.propTypes = {
numSelected: PropTypes.number.isRequired,
};
export default EnhancedTableToolbar;
\ No newline at end of file
import { makeStyles } from "@mui/styles";
/*
*@分割线=======================================================================================================================================
*@Description: 排序算法
*@File:
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:51
*/
export function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) return -1;
if (b[orderBy] > a[orderBy]) return 1;
return 0;
}
/*
*@分割线=======================================================================================================================================
*@Description: 表格排序
*@File: /commons/components/Material.Ui/Table.jsx
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:36
*/
export function getComparator(order, orderBy) {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
/*
*@分割线=======================================================================================================================================
*@Description: 排序算法
*@File:
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:24
*/
export function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
/*
*@分割线=======================================================================================================================================
*@Description: table toolbar styles
*@File: EnhancedTableToolbar
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:41:53
*/
export const useToolbarStyles = makeStyles((theme) => ({
root: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
},
highlight:
theme.palette.type === "light"
? {
color: theme.palette.primary.main,
backgroundColor: "red",
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.primary.dark,
},
title: { flex: "1 1 100%" },
}));
/*
*@分割线=======================================================================================================================================
*@Description: 样式
*@File:
*@param: {theme} [theme]
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:40:37
*/
export const useStyles = makeStyles((theme) => ({
root: { width: "100%", position: "relative" },
paper: { width: "100%", marginBottom: 8 },
elevation1: { boxShadow: "none", padding: "20px" },
elevationNoPadding: { boxShadow: "none", padding: "0" },
table: { minWidth: 500 },
visuallyHidden: {
border: 0,
clip: "rect(0 0 0 0)",
height: 1,
margin: -1,
overflow: "hidden",
padding: 0,
position: "absolute",
top: 20,
width: 1,
},
LinearProgressStyle: {
position: "absolute",
left: 0,
top: "0",
width: "100%",
},
TypographyStyle: {
height: "300px",
width: "100%",
justifyContent: "center",
alignItems: "center",
color: "#666",
fontSize: "16px",
textAlign: "center",
},
bodyTableCell: {
color: "#222222",
fontSize: "12px",
borderBottom: "1px solid rgba(34, 34, 34, 0.08)",
padding: "10px",
paddingLeft: "16px",
},
headTableCell: {
color: "rgba(34, 34, 34, 0.65)",
fontSize: "12px",
padding: "16px",
},
rootTableContainer: {
position: "relative",
overflowX: "auto",
maxHeight: "700px",
},
TableHeadClasses: { backgroundColor: "rgba(34, 34, 34, 0.03)" },
bodyTableCellRoot: { borderBottom: "1px solid rgba(34, 34, 34, 0.08)" },
TypographyboderStyle: {
height: "300px",
width: "100%",
justifyContent: "center",
alignItems: "center",
color: "#666",
fontSize: "16px",
textAlign: "center",
borderBottom: "none",
},
rootTableboderContainer: {
position: "relative",
overflowX: "auto",
maxHeight: "700px",
border: "1px solid rgb(216, 216, 216)",
},
cancelHoverStyle: { "&:hover": { background: "none !important" } },
}));
This diff is collapsed.
import React from "react";
import { Typography } from "@material-ui/core";
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
h3: { fontSize: "24px" },
h4: { fontSize: "20px" },
h5: { fontSize: "16px" },
body1: { fontSize: "14px" },
subtitle1: { fontSize: "13px" },
subtitle2: { fontSize: "12px" },
colorInherit: { color: "#222222" },
colorInherit_hover: { color: "#222222", "&:hover": { color: "#136EFA" } },
colorSecondary: { color: "#00CCCC" },
colorError: { color: "#FF4E4E" },
colorTextPrimary: { color: "#0DD09B" },
HiddenRoot: {
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
},
line: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
});
const TextComponent = props => {
const classes = useStyles();
const fontWT = (fontWeight) => {
switch (fontWeight) {
case "small":
return 300;
case "large":
return 500;
case "big":
return 600;
case "bigger":
return 800;
default:
return 400;
}
}
const opacityFun = (value) => {
switch (value) {
case 'l':
return 0.05
case 'm':
return 0.08
case 'mh':
return 0.1
case 'h':
return 0.15
case 'xs':
return 0.25
case 'ss':
return 0.3
case 'sm':
return 0.45
case 'mm':
return 0.5
case 'md':
return 0.65
case 'gx':
return 0.8
case 'lg':
return 0.85
default:
return 1
}
}
const { text, align, color, display, gutterBottom, variant, fw, op, style, wordBreak, line, click, hover, hoverClass = false } = props;
const defaultClick = () => { }
const stylesFun = () => {
return {
wordBreak: wordBreak ? "break-all" : "keep-all",
textTransform: "none",
...style,
fontWeight: fontWT(fw),
opacity: opacityFun(op),
WebkitLineClamp: line && line.num ? line.num : 1,
width: line && line.width ? line.width : "auto",
maxWidth: line && line.maxWidth ? line.maxWidth : "100%",
}
}
return (
<Typography
align={align || "inherit"}
color={color || "inherit"}
display={display || "initial"}
gutterBottom={gutterBottom || false}
variant={variant || "body1"}
onClick={click || defaultClick}
classes={{
h3: classes.h3,
h4: classes.h4,
h5: classes.h5,
body1: classes.body1,
subtitle1: classes.subtitle1,
subtitle2: classes.subtitle2,
colorInherit: hover ? (hoverClass || classes.colorInherit_hover) : classes.colorInherit,
colorSecondary: classes.colorSecondary,
colorTextPrimary: classes.colorTextPrimary,
colorError: classes.colorError,
root: line ? (line.num && line.num === 1 ? classes.line : classes.HiddenRoot) : classes.root
}}
style={stylesFun()}
>
{text || ''}
</Typography>
)
}
TextComponent.propTypes = {
fw: PropTypes.oneOf(["bigger","big", "large", "medium", "small"]),
variant: PropTypes.oneOf(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subtitle1', 'subtitle2', 'body1', 'body2', 'caption', 'button', 'overline', 'srOnly', 'inherit']),
color: PropTypes.oneOf(["initial", "inherit", "primary", "secondary", "textPrimary", "textSecondary", "error"]),
op: PropTypes.oneOf(['', 'l', 'm', 'mh', 'h', 'xs', 'ss', 'sm', 'mm', 'md', 'lg', 'gx', 'xl']),
};
export default TextComponent
\ No newline at end of file
import React from 'react';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import Text from "@/commons/components/Material.Ui/Text"
import makeStyles from "@material-ui/styles/makeStyles";
import { Grid } from '@material-ui/core';
const useStyles = makeStyles({
tipBody: { width: "100%", height: "40px", background: "#FFEDED", boxShadow: "0px 2px 6px 0px rgba(189, 14, 0, 0.03)", borderRadius: "4px", display: "flex", alignItems: "center" },
root: { marginRight: 0 }
})
export default props => {
const { text } = props;
const classes = useStyles()
return (
<Grid className={classes.tipBody}>
<ErrorOutlineIcon style={{ color: "#FF4E4E", margin: "0px 10px 0px 20px" }} fontSize="small" />
<Text color={"error"} variant={"subtitle2"} text={text} />
</Grid>
)
}
\ No newline at end of file
import React from 'react';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import makeStyles from "@material-ui/styles/makeStyles";
import { Grid } from '@material-ui/core';
import { Typography } from "@material-ui/core";
import { BACKEND_API_URI_PREFIX } from "@/commons/utils/api_prefix";
const useStyles = makeStyles({
tipBody: { border: "1px solid rgba(19, 110, 250, 0.09)", borderRadius: "4px", display: "flex", alignItems: "center" },
root: { marginRight: 0 },
goText: {
color: "rgb(19, 110, 250)",
cursor: "pointer",
'&:hover': {
textDecoration: "underline"
}
}
})
export default props => {
const { style, text, iconColor, backgroundColor, margin, manual } = props;
const classes = useStyles()
return (
<Grid className={style ? style : classes.tipBody} style={{ backgroundColor: backgroundColor ? backgroundColor : "#FFEDED", margin: margin ? margin : "0" }} >
<ErrorOutlineIcon style={{ color: iconColor ? iconColor : "#FF4E4E", margin: "0px 10px 0px 20px" }} fontSize="small" />
<Typography style={{ fontSize: "12px", marginRight: "20px" ,padding:'12px 0'}}>
{text || ''}
{
manual ? (
<span className={classes.goText} onClick={()=>{
window.open(BACKEND_API_URI_PREFIX + '/helpce/docs/2027/about3', '_blank')
}}>
安装手册
</span>
) : ""
}
</Typography>
</Grid>
)
}
\ No newline at end of file
import React from 'react';
import makeStyles from '@material-ui/styles/makeStyles';
import Tooltip from "@/commons/components/Material.Ui/Tooltip";
const COIN_IAMGE_TIPS = require("@/console/cloudelastic/assets/img/templates/icon_about_grey.png");
const useStyles = makeStyles({
tooltipStyle: { lineHeight: "22px" ,backgroundColor: "#4D4D4D", borderRadius: "4px",padding:"8px 10px"}
});
export default props => {
const classes = useStyles();
const { title, marginLeft,iconWidth } = props;
return (
<Tooltip title={title} tooltip={classes.tooltipStyle}>
<img src={COIN_IAMGE_TIPS} style={{ width:iconWidth || "16px", marginLeft: marginLeft || "8px" }} alt="" />
</Tooltip>
)
}
\ No newline at end of file
import React, { useState } from 'react';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
tooltip: { backgroundColor: "#4D4D4D", borderRadius: "4px",padding:"8px 10px" ,fontSize:'12px'},
})
export default props => {
const classes = useStyles()
const { title, placement, children,tooltip } = props
return (
<Tooltip
interactive={true}
title={title}
classes={{
popper: classes.popper,
tooltip:tooltip || classes.tooltip
}}
placement={placement || "top"}>
{children}
</Tooltip>
)
}
// placement 'bottom-end'
// | 'bottom-start'
// | 'bottom'
// | 'left-end'
// | 'left-start'
// | 'left'
// | 'right-end'
// | 'right-start'
// | 'right'
// | 'top-end'
// | 'top-start'
// | 'top'
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Dialogs from "@/commons/components/Dialog/Dialogs";
import { Typography } from "@material-ui/core";
import { CopyToClipboard } from 'react-copy-to-clipboard';
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined';
import Public from "@/commons/components/Public";
import { CLOUDE } from "@/commons/utils/constants";
import { Grid } from "@material-ui/core";
import Text from "@/commons/components/Material.Ui/Text"
const useStyles = makeStyles({
classNameType:{ maxWidth:'inherit' }
})
export default props => {
const { open, password, closeDialogCallBack, system } = props;
const classes = useStyles()
const { setMessages, render } = Public()
return render(
<Dialogs
dialogs={open}
type="2"
classes={classes}
isBotton={false}
btnMarginTop="20px"
mixWidth="28rem"
height="11.125rem"
classNameType = {'classNameType'}
isBottom={true}
style={{ flex: 1 }}
closeAccountDialog={() => closeDialogCallBack()}
>
<Grid style={{ margin: "0 auto", padding: "46px 0 60px", boxSizing: "border-box", alignItems: 'center' }}>
<Grid style={{ display: "flex", }} >
<Text variant={"body1"} text={CLOUDE['userName'] + ":" + (system === "LINUX" ? "cloudam" : "Administrator")} />
<CopyToClipboard text={system === "LINUX" ? "cloudam" : "Administrator"}
onCopy={() => {
setMessages({
message: CLOUDE['copySuccess'],
messagetype: 'success',
})
}}>
<FileCopyOutlinedIcon fontSize={'small'} style={{ color: "#136EFA", marginLeft: "10px", cursor: "pointer" }} />
</CopyToClipboard>
</Grid>
<Grid style={{ display: "flex", }} >
<Grid style={{ textAlign: 'center', display: "flex", alignItems: "center" }}>
<Text variant={"body1"} text={CLOUDE['password'] + ":"} />
<Text variant={"body1"} text={password} />
</Grid>
<CopyToClipboard text={`${password}`}
onCopy={() => {
setMessages({
message: CLOUDE['copySuccess'],
messagetype: 'success',
})
}}>
<FileCopyOutlinedIcon fontSize={'small'} style={{ color: "#136EFA", marginLeft: "10px", cursor: "pointer" }} />
</CopyToClipboard>
</Grid>
</Grid>
</Dialogs>
)
}
\ No newline at end of file
import React from 'react'
import { makeStyles,Grid, } from '@material-ui/core'
import Text from "@/commons/components/Material.Ui/Text"
import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp';
import SelectComponent from "@/commons/components/Material.Ui/Input"
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
const style= makeStyles({
flex:{
minWidth:'74px',
height:'32px',
display:'flex',
alignItems:'center',
justifyContent:'space-evenly',
border:'1px solid rgba(216, 216, 216, 0.6)'
},
icon:{
height:'32px',
display:'flex',
flexDirection:'column',
justifyContent:'space-around'
// overflow:'hidden',
},
up:{
height:'0',
width:'0',
cursor:'pointer',
border:'5px solid transparent',
borderBottomColor:'rgba(117, 117, 117, 1)'
},
down:{
height:'0',
width:'0',
cursor:'pointer',
border:'5px solid transparent',
borderTopColor:'rgba(117, 117, 117, 1)'
},
handwareRightContentGrid2:{
width:'74px',
height:'32px',
},
customizationRoot:{
height:'16px',
}
})
let time = 0
let timer = null
let timer2 = null
let numCache = 0
let upCache = false
export default props => {
const classes = style()
const [num,setNum] = React.useState(72)
const { change, current } = props
const operation ={
down:(up)=>{
numCache = num
time = 0
upCache = up ? true : false
window.addEventListener('mouseup',operation.up)
timer = setTimeout( ()=>{
time = 1
operation.ldown(up)
} ,500 )
},
up:()=>{
window.removeEventListener('mouseup',operation.up)
clearTimeout(timer)
timer = null
timer2 && clearTimeout(timer2)
timer2 = null
if(time === 0 && !(!upCache && numCache <= 0)) {
setNum(upCache?numCache+1:numCache-1)
}
timer = 0
},
ldown:(up)=>{
timer2 && clearTimeout(timer2)
if( !up && numCache <= 0 ) return
numCache = up?(numCache+1):(numCache-1)
setNum(numCache)
timer2 = setTimeout(()=>{
time = time+1
operation.ldown(up)
},time>10?100:200)
},
change:(e)=>{
if( e.target.value.indexOf('-') > -1 ) return
setNum(Number(e.target.value))
}
}
React.useEffect(()=>{
time = 0
timer = null
timer2 = null
numCache = 0
upCache = false
},[])
React.useEffect(()=>{
![undefined,''].includes(current) && setNum(current)
},[current])
React.useEffect(()=>{
change && change( num )
},[num])
const typeInput = {
icon: (type) => {
return (
<Grid className={classes.icon}>
<Grid className={classes.up} onMouseDown={()=>operation.down(1)}></Grid>
<Grid className={classes.down} onMouseDown={()=>operation.down()}></Grid>
</Grid>
)
},
}
return (
<Grid className={classes.handwareRightContentGrid2}>
<SelectComponent
size='xsmall'
customClass = {classes.customizationRoot}
fullWidth={true}
textAlign={"right"}
value={String(num)}
endAdornment={typeInput.icon("cpu")}
type={'number'}
onChange={operation.change}
/>
</Grid>)
}
\ No newline at end of file
.ant-spin-spinning{
opacity:1
}
.ant-spin{
position: absolute;
top: 0;
left: 0;
z-index: 4;
display: block;
width: 100%;
z-index: 999;
height: 100%;
min-height: 100px;
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: "tnum";
color: #1890ff;
text-align: center;
transition: transform .3s cubic-bezier(.78,.14,.15,.86);
}
.ant-spin.ant-spin-show-text .ant-spin-dot{
margin-top: -20px;
}
.ant-spin .ant-spin-dot{
position: absolute;
top: 50%;
left: 50%;
margin: -10px;
z-index: 11111;
}
.ant-spin-dot-spin{
transform: rotate( 45deg );
-webkit-animation: antRotate 1.2s infinite linear;
animation: antRotate 1.2s infinite linear;
}
.ant-spin-dot{
display: inline-block;
font-size: 20px;
width: 1em;
height: 1em;
}
.ant-spin-dot-item{
position: absolute;
display: block;
width: 9px;
height: 9px;
background-color: #1890ff;
border-radius: 100%;
transform: scale(.75);
transform-origin: 50% 50%;
opacity: .3;
-webkit-animation: antSpinMove 1s infinite linear alternate;
animation: antSpinMove 1s infinite linear alternate;
}
.ant-spin-dot-item:nth-child(1){
top: 0;
left: 0;
}
.ant-spin-dot-item:nth-child(2){
top: 0;
right: 0;
-webkit-animation-delay: .4s;
animation-delay: .4s;
}
.ant-spin-dot-item:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: .8s;
animation-delay: .8s;
}
.ant-spin-dot-item:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
.ant-spin .ant-spin-text {
position: absolute;
top: 50%;
width: 100%;
padding-top: 5px;
text-shadow: 0 1px 2px #fff;
font-weight: 500;
}
.ant-spin.ant-spin-show-text .ant-spin-text {
display: block;
}
@-webkit-keyframes antRotate {
to {
transform: rotate(405deg)
}
}
@keyframes antRotate {
to {
transform: rotate(405deg)
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1
}
}
@keyframes antSpinMove {
to {
opacity: 1
}
}
.ant-spin-background{
width: 100%;
height: 100%;
background-color: rgba(255,255,255,0.6);
z-index: 9999;
transition: all 0.3s;
}
\ No newline at end of file
import { useStores } from "@/store/index"; import { useStores } from "@/store/index";
import { elements } from "@/router"; import { elements } from "@/router";
import { current, menu, product } from "@/api/demo_api"; import { current, menu } from "@/api/demo_api";
import { product } from "@/api/project_api";
import localStorageKey from "@/utils/localStorageKey"; import localStorageKey from "@/utils/localStorageKey";
import NotFound from "@/views/404"; import NotFound from "@/views/404";
import useMyRequest from "@/hooks/useMyRequest"; import useMyRequest from "@/hooks/useMyRequest";
import { useEffect } from "react"; import { useEffect } from "react";
const useMyRouter = () => { const useMyRouter = () => {
const { permissionStore, menuStore } = useStores(); const { permissionStore, menuStore, currentProjectStore } = useStores();
const userInfo = useMyRequest(current); const userInfo = useMyRequest(current);
const menuInfo = useMyRequest(menu); const menuInfo = useMyRequest(menu);
const productInfo = useMyRequest(product); const productInfo = useMyRequest(product);
useEffect(() => { useEffect(() => {
userInfo.run(); userInfo.run();
menuInfo.run(); menuInfo.run();
productInfo.run() productInfo.run({
product: "CADD",
});
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useEffect(() => { useEffect(() => {
if (userInfo.res && menuInfo.res) { if (userInfo.res && menuInfo.res) {
localStorage.setItem(localStorageKey.USER_INFO, JSON.stringify(userInfo.res)); localStorage.setItem(
localStorageKey.USER_INFO,
JSON.stringify(userInfo.res)
);
permissionStore.restAddRoutes(); permissionStore.restAddRoutes();
for (let item of menuInfo.res.data) { for (let item of menuInfo.res.data) {
...@@ -39,11 +42,17 @@ const useMyRouter = () => { ...@@ -39,11 +42,17 @@ const useMyRouter = () => {
permissionStore.initAllRoutes(); permissionStore.initAllRoutes();
} }
if (productInfo.res) { if (productInfo.res) {
console.log(productInfo, '1111111111111') console.log(productInfo, "1111111111111");
let list = productInfo.data?.data;
if (list.length === 0) {
currentProjectStore.setProjectList([]);
currentProjectStore.changeProject({});
} else {
currentProjectStore.setProjectList(list);
currentProjectStore.changeProject(list[0]);
}
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [userInfo.data, menuInfo.data, productInfo.data]); }, [userInfo.data, menuInfo.data, productInfo.data]);
......
.noProject {
width: 100%;
height: calc(100vh - 57px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.noDataImg {
width: 220px;
margin-bottom: 4px;
}
.text1 {
line-height: 24px;
font-size: 16px;
color: #1e2633;
margin-bottom: 4px;
}
.text2 {
line-height: 22px;
font-size: 14px;
color: #8a9099;
margin-bottom: 24px;
}
.button {
background-color: #1370ff;
color: #fff;
}
import style from "./NoProject.module.css";
import noData from "@/assets/project/noData.svg";
import { Button } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import AddProject from "@/views/Project/components/AddProject";
import React from "react";
const NoProject = () => {
let addProjectRef: any = React.createRef();
const handleClickOpen = () => {
addProjectRef.current.handleClickOpen();
};
return (
<div className={style.noProject}>
<img src={noData} alt="" className={style.noDataImg} />
<div className={style.text1}>当前产品暂无项目</div>
<div className={style.text2}>请先创建项目</div>
<Button
variant="contained"
size="large"
className={style.button}
startIcon={<AddIcon />}
onClick={handleClickOpen}
style={{ backgroundColor: "#1370ff", color: "#fff" }}
>
创建项目
</Button>
<AddProject onRef={addProjectRef} />
</div>
);
};
export default NoProject;
import NoProject from "./NoProject";
export default NoProject;
import React from "react";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
export interface IDialogProps {
/** 自定义类名 */
className?: string;
/** 自定义样式 */
style?: React.CSSProperties;
/** 弹窗的标题 */
title?: string;
/** 是否显示弹窗 */
open: boolean;
isHideHeader?: boolean;
/** 是否隐藏弹窗底部按钮部分 */
isHideFooter?: boolean;
/** 自定义底部按钮 */
footerRender?: () => React.ReactNode;
/** 是否显示取消按钮 */
showCancel?: boolean;
/** 是否显示确定按钮 */
showConfirm?: boolean;
/** 关闭弹窗时的回调函数 */
onClose?: () => void;
/** 点击确定按钮时的回调函数 */
onConfirm?: () => void;
/** 取消按钮文案 */
cancelText?: string;
/** 确认按钮文案 */
okText?: string;
/** 是否禁用确认按钮 */
disabledConfirm?: boolean;
children: React.ReactNode;
}
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 {
title,
open,
style,
onClose,
onConfirm,
isHideFooter,
isHideHeader,
children,
footerRender,
className,
showCancel = true,
/** 是否显示确定按钮 */
showConfirm = true,
cancelText,
okText,
disabledConfirm,
} = props;
const Footer = () => {
if (isHideFooter) return null;
return footerRender ? (
footerRender()
) : (
<DialogActions style={{ padding: "0 24px 24px 24px" }}>
{showCancel ? (
<Button onClick={onClose} variant="outlined" size="small">
{cancelText || "取消"}
</Button>
) : null}
{showConfirm ? (
<Button
onClick={onConfirm}
variant="contained"
size="small"
disabled={disabledConfirm}
>
{okText || "确定"}
</Button>
) : null}
</DialogActions>
);
};
return (
<Dialog
open={open}
onClose={onClose}
style={style}
className={className}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
{isHideHeader ? null : (
<DialogTitle id="alert-dialog-title">
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<span>{title}</span>
<CloseIcon
onClick={onClose}
style={{ color: "#C2C6CC", cursor: "pointer" }}
/>
</div>
</DialogTitle>
)}
<DialogContent style={{ minWidth: 400 }}>{children}</DialogContent>
{Footer()}
</Dialog>
);
};
export default MyDialog;
import {
Button,
Dialog,
DialogActions,
DialogContent,
IconButton,
DialogTitle,
} from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton";
import CloseIcon from "@mui/icons-material/Close";
import { useState } from "react";
import React, { useImperativeHandle } from "react";
// import LoadingButton from '@mui/lab/LoadingButton';
const MyDialog = (props: any) => {
const [open, setOpen] = useState(false);
const { title, handleSubmit, submitloading } = props;
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useImperativeHandle(props.onRef, () => {
return {
handleClickOpen: handleClickOpen,
handleClose: handleClose,
};
});
return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
{title && <DialogTitle id="form-dialog-title">{title}</DialogTitle>}
<DialogContent>
{props.children}
<IconButton
aria-label="delete"
style={{ position: "absolute", top: "10px", right: "12px" }}
onClick={handleClose}
>
<CloseIcon style={{ color: "#C2C6CC" }} />
</IconButton>
</DialogContent>
<DialogActions style={{ padding: "24px" }}>
<Button
onClick={handleClose}
color="inherit"
variant="contained"
style={{ color: "#1E2633", backgroundColor: "#fff" }}
>
取消
</Button>
<LoadingButton
loading={submitloading}
onClick={handleSubmit}
color="primary"
variant="contained"
style={{ backgroundColor: "#1370FF" }}
>
确认
</LoadingButton>
</DialogActions>
</Dialog>
);
};
export default MyDialog;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2021-12-04 15:46:25
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-05 18:06:47
* @FilePath: /lionet-slb-pc/src/components/SearchView/components/Collapse.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import * as React from "react";
import Box from "@mui/material/Box";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl";
import Select, { SelectChangeEvent } from "@mui/material/Select";
interface IOption {
label: string;
value: string;
disabled?: boolean;
}
interface IProps {
value?: IOption;
options: IOption[];
onChange?: (val: IOption) => void;
title?: string;
}
export default function BasicSelect(props: IProps) {
const { value, options, onChange, title } = props;
const handleChange = (event: SelectChangeEvent) => {
const newValue = options?.filter((item) => {
return item.value === event.target.value;
});
if (onChange) {
onChange(newValue[0] || { label: "", value: "" });
}
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
{title || "请选择"}
</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={value?.value}
label={title || "请选择"}
onChange={handleChange}
>
{options.length
? options?.map((item: IOption) => {
return (
<MenuItem value={item.value} disabled={item?.disabled}>
{item.label}
</MenuItem>
);
})
: null}
</Select>
</FormControl>
</Box>
);
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-02 10:38:01
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 13:45:33
* @FilePath: /bkunyun/src/components/mui/Table.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import * as React from "react";
import MuiTable from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import { Box } from "@mui/material";
interface IColumns {
key: string;
title: string;
align?: "left" | "center" | "right";
render?: (value: any, index: number) => void;
}
interface IProps {
columns: IColumns[];
dataSource: any;
}
export default function Table(props: IProps) {
const { columns = [], dataSource = [] } = props;
return (
<TableContainer component={Paper}>
<MuiTable sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
{columns?.map((item: IColumns) => {
return (
<TableCell {...item} key={item.key}>
{item.title}
</TableCell>
);
})}
</TableRow>
</TableHead>
<TableBody>
{dataSource.length ? (
dataSource?.map(() => (
<TableRow
key={Math.random()}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
{columns?.map((item: IColumns, index: number) => {
if (item.render) {
return <>{item.render(item, index)}</>;
} else {
return (
<TableCell align="right" key={item.key}>
{item.title}
</TableCell>
);
}
})}
</TableRow>
))
) : (
<Box p={2}>暂无数据</Box>
)}
</TableBody>
</MuiTable>
</TableContainer>
);
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 18:48:15
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo } from "react";
import { isEqual } from "lodash";
import { Box } from "@mui/system";
import Tab from "@mui/material/Tab";
import { TabContext, TabList, TabPanel } from "@mui/lab";
interface ITabList {
label: string;
value: string;
component: JSX.Element;
}
interface IProps {
value: string;
onChange: (val: string) => void;
tabList: ITabList[];
}
const Tabs = (props: IProps) => {
const { value, onChange, tabList } = props;
return (
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "#F0F2F5" }}>
<TabList
onChange={(e: any, val: string) => {
onChange(val);
}}
aria-label="lab API tabs example"
>
{tabList?.map((item) => {
return (
<Tab label={item.label} value={item.value} key={item.value} />
);
})}
</TabList>
</Box>
{tabList?.map((item) => {
return (
<TabPanel value={item.value} key={item.value}>
{item.component}
</TabPanel>
);
})}
</TabContext>
);
};
const handleEqual = (prvProps: IProps, nextProps: IProps) => {
if (isEqual(prvProps, nextProps)) {
return true;
}
return false;
};
export default memo(Tabs, handleEqual);
...@@ -7,6 +7,7 @@ import { Provider } from "mobx-react"; ...@@ -7,6 +7,7 @@ import { Provider } from "mobx-react";
import { stores } from "@/store/index"; import { stores } from "@/store/index";
import { MySnackbarProvider } from "@/components/MySnackbar"; import { MySnackbarProvider } from "@/components/MySnackbar";
import "@/mocks/index"; import "@/mocks/index";
import './assets/style/public.css'
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement document.getElementById("root") as HTMLElement
......
...@@ -30,6 +30,22 @@ const demo = [ ...@@ -30,6 +30,22 @@ const demo = [
icon: "", icon: "",
type: "product", type: "product",
routes: [ routes: [
{
id: "PROJECT_SETTING",
type: "page",
name: "项目设置",
path: "/setting",
icon: "",
element: "ProjectSetting",
show: "true",
// children: [
// {
// id: "PROJECT_OVERIVEW_CREATE",
// type: "operation",
// name: "创建项目",
// },
// ],
},
{ {
id: "PROJECT_OVERIVEW", id: "PROJECT_OVERIVEW",
type: "page", type: "page",
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:23
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 17:15:35
* @FilePath: /bkunyun/src/react-app-env.d.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/// <reference types="node" /> /// <reference types="node" />
/// <reference types="react" /> /// <reference types="react" />
/// <reference types="react-dom" /> /// <reference types="react-dom" />
...@@ -69,3 +77,7 @@ declare module '*.module.sass' { ...@@ -69,3 +77,7 @@ declare module '*.module.sass' {
const classes: { readonly [key: string]: string }; const classes: { readonly [key: string]: string };
export default classes; export default classes;
} }
declare module '@mui/lab';
declare module 'lodash';
declare module "@mui/material/Tab"
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-05-31 15:15:59
* @FilePath: /bkunyun/src/router/index.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
import { AnyMap } from "immer/dist/internal";
*/
import ConsoleLayout from "@/views/ConsoleLayout"; import ConsoleLayout from "@/views/ConsoleLayout";
import Home from "@/views/Home"; import Home from "@/views/Home";
import MenuLayout from "@/views/MenuLayout"; import MenuLayout from "@/views/MenuLayout";
import * as React from "react"; import * as React from "react";
import NotFound from "@/views/404"; import NotFound from "@/views/404";
import Demo from "@/views/demo"; import Demo from "@/views/demo";
import ProjectSetting from "@/views/Project/ProjectSetting";
export type route = { export type route = {
id?: string; id?: string;
...@@ -33,9 +43,10 @@ export const elements: { ...@@ -33,9 +43,10 @@ export const elements: {
childrenRoutes, childrenRoutes,
}: { }: {
childrenRoutes?: Array<route | operation>; childrenRoutes?: Array<route | operation>;
}) => JSX.Element; }) => JSX.Element | any;
} = { } = {
Demo: Demo, Demo: Demo,
ProjectSetting: ProjectSetting,
}; };
export const routes: Array<route | navigate> = [ export const routes: Array<route | navigate> = [
......
...@@ -2,10 +2,11 @@ import * as React from "react"; ...@@ -2,10 +2,11 @@ import * as React from "react";
import { configure } from "mobx"; 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";
configure({ enforceActions: "always" }); configure({ enforceActions: "always" });
export const stores = { permissionStore, menuStore }; export const stores = { permissionStore, menuStore, currentProjectStore };
export const CounterContext = React.createContext(stores); export const CounterContext = React.createContext(stores);
export const useStores = () => React.useContext(CounterContext); export const useStores = () => React.useContext(CounterContext);
import { makeAutoObservable } from "mobx";
type projectInfo = {
id?: string;
name?: string;
desc?: string;
};
type productInfo = {
id?: string;
name?: string;
};
class currentProject {
constructor() {
makeAutoObservable(this);
}
// 选中的项目
currentProjectInfo: projectInfo = {};
// 选中的产品下的项目列表
projectList: Array<projectInfo> = [];
// 选中的产品
currentProductInfo: productInfo = {};
setProjectList = (list: Array<projectInfo>) => {
this.projectList = list;
};
changeProject = (project: projectInfo) => {
this.currentProjectInfo = project;
};
}
const currentProjectStore = new currentProject();
export default currentProjectStore;
import { Box, Menu, MenuItem, IconButton } from "@mui/material"; import { Box, Menu, MenuItem } from "@mui/material";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Outlet, useLocation, useNavigate } from "react-router-dom"; import { Outlet, useLocation, useNavigate } from "react-router-dom";
import style from "./index.module.css"; import style from "./index.module.css";
import globalText from "@/utils/globalText_CN"; import globalText from "@/utils/globalText_CN";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import useIndex from "./useIndex"; import useIndex from "./useIndex";
import { useStores } from "@/store/index"; import { useStores } from "@/store/index";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import Button from "@/components/mui/Button"; import Button from "@/components/mui/Button";
import logo from '@/assets/img/logo.svg' import logo from "@/assets/img/logo.svg";
import Avatar from '@mui/material/Avatar'; import Avatar from "@mui/material/Avatar";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import cx from "classnames" import cx from "classnames";
const ConsoleLayout = observer(() => { const ConsoleLayout = observer(() => {
const { const {
...@@ -37,13 +35,22 @@ const ConsoleLayout = observer(() => { ...@@ -37,13 +35,22 @@ const ConsoleLayout = observer(() => {
<Box> <Box>
<Box className={style.topApp}> <Box className={style.topApp}>
<Box className={style.topLeftBox}> <Box className={style.topLeftBox}>
<img src={logo} alt="" className={style.logo} /> <img src={logo} alt="" className={style.logo} />
<Button text={globalText.console} variant={"text"} click={() => navigate("/home")} /> <Button
text={globalText.console}
<Box sx={{ display: 'flex', alignItems: 'center' }}> variant={"text"}
<Button text={globalText.product} variant={"text"} click={handleProductClick} dropValue={productOpen} drop={true} /> click={() => navigate("/home")}
/>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Button
text={globalText.product}
variant={"text"}
click={handleProductClick}
dropValue={productOpen}
drop={true}
/>
{/* <ArrowDropDownIcon classes={{ {/* <ArrowDropDownIcon classes={{
root: cx({ root: cx({
...@@ -58,7 +65,7 @@ const ConsoleLayout = observer(() => { ...@@ -58,7 +65,7 @@ const ConsoleLayout = observer(() => {
open={productOpen} open={productOpen}
onClose={handleClose} onClose={handleClose}
classes={{ classes={{
paper: style.menuPaper paper: style.menuPaper,
}} }}
MenuListProps={{ MenuListProps={{
"aria-labelledby": "product-button", "aria-labelledby": "product-button",
...@@ -68,11 +75,9 @@ const ConsoleLayout = observer(() => { ...@@ -68,11 +75,9 @@ const ConsoleLayout = observer(() => {
return ( return (
<MenuItem <MenuItem
key={item.path} key={item.path}
classes={{ classes={{
root: style.menuItemRoot root: style.menuItemRoot,
}} }}
onClick={() => { onClick={() => {
navigate(item.path); navigate(item.path);
handleClose(); handleClose();
...@@ -84,27 +89,34 @@ const ConsoleLayout = observer(() => { ...@@ -84,27 +89,34 @@ const ConsoleLayout = observer(() => {
})} })}
</Menu> </Menu>
</Box> </Box>
</Box> </Box>
<Box className={style.topRightBox}> <Box className={style.topRightBox}>
<Box
<Box sx={{ display: 'flex', alignItems: 'center' }} onClick={handleUtilityClick}> sx={{ display: "flex", alignItems: "center" }}
onClick={handleUtilityClick}
>
<Avatar <Avatar
sx={{ bgcolor: "#1370FF", width: 28, height: 28, fontSize: "14px", cursor: 'pointer' }} sx={{
>H</Avatar> bgcolor: "#1370FF",
<ArrowDropDownIcon classes={{ width: 28,
height: 28,
fontSize: "14px",
cursor: "pointer",
}}
>
H
</Avatar>
<ArrowDropDownIcon
classes={{
root: cx({ root: cx({
[style.ArrowDropDownIconRoot]: true, [style.ArrowDropDownIconRoot]: true,
[style.ArrowDropDownIconRootOpen]: Boolean(utilityOpen) [style.ArrowDropDownIconRootOpen]: Boolean(utilityOpen),
}) }),
}} /> }}
/>
</Box> </Box>
<Menu <Menu
id="utility-menu" id="utility-menu"
anchorEl={utilityAnchorEl} anchorEl={utilityAnchorEl}
......
...@@ -3,3 +3,12 @@ ...@@ -3,3 +3,12 @@
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
} }
.aside {
border-right: 1px solid #e6e8eb;
width: 10%;
min-width: 220px;
height: calc(100vh - 57px);
}
.content {
flex: 1;
}
...@@ -5,6 +5,8 @@ import { ...@@ -5,6 +5,8 @@ import {
ListItemText, ListItemText,
ListItemButton, ListItemButton,
} from "@mui/material"; } from "@mui/material";
// import CurrentProject from "./CurrentProject";
import CurrentProject from "../Project/components/CurrentProject";
import React from "react"; import React from "react";
import { Outlet, useNavigate } from "react-router-dom"; import { Outlet, useNavigate } from "react-router-dom";
import style from "./index.module.css"; import style from "./index.module.css";
...@@ -18,7 +20,8 @@ const MenuLayout = observer(() => { ...@@ -18,7 +20,8 @@ const MenuLayout = observer(() => {
return ( return (
<Box className={style.container}> <Box className={style.container}>
<Box sx={{ width: "10%" }}> <Box className={style.aside}>
<CurrentProject />
<List> <List>
{permissionStore.sidebarRouters.map((item, index) => { {permissionStore.sidebarRouters.map((item, index) => {
return ( return (
...@@ -33,7 +36,7 @@ const MenuLayout = observer(() => { ...@@ -33,7 +36,7 @@ const MenuLayout = observer(() => {
})} })}
</List> </List>
</Box> </Box>
<Box sx={{ width: "90%" }}> <Box className={style.content}>
<Outlet></Outlet> <Outlet></Outlet>
</Box> </Box>
</Box> </Box>
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-01 09:15:10
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo } from "react";
import { Box } from "@mui/system";
const BaseInfo = () => {
return <Box>基础信息</Box>;
};
export default memo(BaseInfo);
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-04 18:28:31
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import Dialog from "@/components/mui/Dialog";
import { memo } from "react";
interface IProps {
setAddMemberDialog: (val: boolean) => void;
addMemberDialog: boolean;
}
const AddMember = (props: IProps) => {
const { addMemberDialog, setAddMemberDialog } = props;
const onClose = () => {
setAddMemberDialog(false);
};
const onConfirm = () => {
setAddMemberDialog(false);
};
return (
<>
<Dialog
open={addMemberDialog}
onClose={onClose}
onConfirm={onConfirm}
title="移出项目"
>
<div>确认移出该成员吗?</div>
</Dialog>
</>
);
};
export default memo(AddMember);
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-05 18:15:22
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// import Dialog from "@/components/Material.Ui/Dialog";
import Select from "@/components/mui/Select";
import Dialog from "@/components/mui/Dialog";
import { memo } from "react";
interface IProps {
setPermissionDialog: (val: boolean) => void;
permissionDialog: boolean;
}
const ChangePermission = (props: IProps) => {
const { permissionDialog, setPermissionDialog } = props;
const onClose = () => {
setPermissionDialog(false);
};
const onConfirm = () => {
setPermissionDialog(false);
};
return (
<>
<Dialog
open={permissionDialog}
onClose={onClose}
onConfirm={onConfirm}
title="更改权限"
>
<Select title="项目权限" options={[]} />
</Dialog>
</>
);
};
export default memo(ChangePermission);
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-04 17:54:50
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// import Dialog from "@/components/Material.Ui/Dialog";
import Dialog from "@/components/mui/Dialog";
import { memo } from "react";
interface IProps {
setRemoveDialog: (val: boolean) => void;
removeDialog: boolean;
}
const RemoveItem = (props: IProps) => {
const { removeDialog, setRemoveDialog } = props;
const onClose = () => {
setRemoveDialog(false);
};
const onConfirm = () => {
setRemoveDialog(false);
};
return (
<>
<Dialog
open={removeDialog}
onClose={onClose}
onConfirm={onConfirm}
title="移出项目"
>
<div>确认移出该成员吗?</div>
</Dialog>
</>
);
};
export default memo(RemoveItem);
.headerBox {
display: flex;
justify-content: space-between;
align-items: center;
}
.removeItemBox {
color: #ff4e4e;
margin-left: 32px;
cursor: pointer;
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-04 18:33:02
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useEffect, useState } from "react";
import { Box } from "@mui/material";
import Button from "@mui/material/Button";
import SearchIcon from "@mui/icons-material/Search";
import Add from "@mui/icons-material/Add";
import Table from "@/components/Material.Ui/Table";
import { useHttp } from "@/api/http";
import Input from "@/components/Material.Ui/Input";
import RemoveItem from "./components/RemoveItem";
import ChangePermission from "./components/ChangePermission";
import AddMember from "./components/AddMember";
import styles from "./index.module.css";
const ProjectMembers = () => {
const http = useHttp();
const columns = [
{ id: "username", label: "成员名称", width: "20%" },
{ id: "projectRoleDesc", label: "项目权限", width: "20%" },
{ id: "phone", label: "联系方式", width: "20%" },
{
id: "operation",
label: "操作",
width: "20%",
render: (item: any) => {
console.log(item, "000000");
return (
<>
<span
style={{ color: "#1370FF", cursor: "pointer" }}
onClick={onPermissionBtn}
>
更改权限
</span>
<span className={styles.removeItemBox} onClick={onRemoveItemBtn}>
移出项目
</span>
</>
);
},
},
];
/** 删除成员 */
const [removeDialog, setRemoveDialog] = useState<boolean>(false);
/** 更改权限 */
const [permissionDialog, setPermissionDialog] = useState<boolean>(false);
/** 添加成员 */
const [addMemberDialog, setAddMemberDialog] = useState<boolean>(false);
useEffect(() => {
http
.get("/cpp/project/list", {
params: { product: "cadd" },
})
.then((res) => {
console.log(res);
});
}, [http]);
/** 点击添加成员 */
const onAddMember = () => {
setAddMemberDialog(true);
};
/** 点击删除成员 */
const onRemoveItemBtn = () => {
setRemoveDialog(true);
};
/** 点击更改权限 */
const onPermissionBtn = () => {
setPermissionDialog(true);
};
return (
<>
<Box className={styles.headerBox}>
<Input
onChange={(e: any) => {
console.log(e);
}}
size="xsmall"
placeholder="搜索项目成员"
endAdornment={<SearchIcon />}
/>
<Button
variant="contained"
onClick={onAddMember}
startIcon={<Add />}
size="small"
>
添加成员
</Button>
</Box>
<Table
rowHover={true}
stickyheader={true}
rows={[
{
username: "wuyongs",
phone: 2323424,
},
]}
rowsPerPage={"99"}
headCells={columns}
nopadding={true}
footer={false}
tableStyle={{ minWidth: "auto" }}
borderBottom={"none"}
/>
<RemoveItem
removeDialog={removeDialog}
setRemoveDialog={setRemoveDialog}
/>
<ChangePermission
permissionDialog={permissionDialog}
setPermissionDialog={setPermissionDialog}
/>
<AddMember
addMemberDialog={addMemberDialog}
setAddMemberDialog={setAddMemberDialog}
/>
</>
);
};
export default memo(ProjectMembers);
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-05 18:29:59
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useState, useMemo } from "react";
import { Box } from "@mui/system";
import { useStores } from "@/store/index";
import NoProject from "@/components/NoProject";
import { observer } from "mobx-react-lite";
import projectImg from "@/assets/project/projectIconSmall.svg";
import ProjectMembers from "./ProjectMembers";
import BaseInfo from "./BaseInfo";
import Tabs from "@/components/mui/Tabs";
const ProjectSetting = observer(() => {
const { currentProjectStore } = useStores();
const [value, setValue] = useState("projectMember");
const tabList = useMemo(() => {
return [
{
label: "项目成员",
value: "projectMember",
component: <ProjectMembers />,
},
{
label: "基础信息",
value: "baseInfo",
component: <BaseInfo />,
},
];
}, []);
const changeTabs = (val: string) => {
setValue(val);
};
if (currentProjectStore.currentProjectInfo.name) {
return (
<Box style={{ padding: 24 }}>
<div>
<img src={projectImg} alt="项目logo" />
<span>项目名称A</span>
</div>
<Box sx={{ width: "100%", typography: "body1" }}>
<Tabs value={value} onChange={changeTabs} tabList={tabList} />
</Box>
</Box>
);
} else {
return <NoProject />;
}
});
export default memo(ProjectSetting);
.formBox {
height: 300px;
width: 388px;
display: flex;
flex-direction: column;
padding: 10px 0;
justify-content: space-around;
}
This diff is collapsed.
.currentProject {
background-color: #f7f8fa;
padding: 17px 16px 17px 20px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
cursor: pointer;
}
.logo {
width: 32px;
border-radius: 4px;
background-color: #fff;
margin-right: 12px;
display: block;
}
.info {
flex: 1;
}
.name {
color: #1e2633;
line-height: 22px;
font-size: 14px;
font-weight: 600;
}
.desc {
color: #8a9099;
line-height: 20px;
font-size: 14px;
}
.showProjectList {
color: #c2c6cc;
font-size: 12px;
}
import logo from "@/assets/project/projectIcon.svg";
import style from "./index.module.css";
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
import { Popper, Fade } from "@mui/material";
import { useStores } from "@/store/index";
import ProjectListPopper from "../ProjectListPopper";
import { useState } from "react";
import { observer } from "mobx-react-lite";
const CurrentProject = observer(() => {
const { currentProjectStore } = useStores();
const [open, setOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const handleShowProjectList = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
setOpen((previousOpen) => !previousOpen);
};
const canBeOpen = open && Boolean(anchorEl);
const id = canBeOpen ? "spring-popper" : undefined;
const handleChangeCurrentProject = (project: any) => {
currentProjectStore.changeProject(project);
setOpen(!open);
};
return (
<div>
<div
className={style.currentProject}
aria-describedby={id}
onClick={handleShowProjectList}
>
<img src={logo} alt="" className={style.logo} />
<div className={style.info}>
<div className={style.name}>
{currentProjectStore.currentProductInfo.name || "CADD"}
</div>
<div className={style.desc}>
{currentProjectStore.currentProjectInfo.name || "暂无项目"}
</div>
</div>
<ArrowForwardIosIcon
className={style.showProjectList}
style={{ fontSize: 12 }}
/>
</div>
<Popper
id={id}
open={open}
anchorEl={anchorEl}
placement="right-start"
transition
>
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}>
<div>
<ProjectListPopper
handleChangeCurrentProject={handleChangeCurrentProject}
/>
</div>
</Fade>
)}
</Popper>
</div>
);
});
export default CurrentProject;
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