Commit 84a97fd0 authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20221012-environment' into 'release'

cn-Feat 20221012 environment

See merge request !145
parents 92032f79 567ba4cd
......@@ -1190,6 +1190,12 @@
"regenerator-runtime": "^0.13.4"
}
},
"@babel/standalone": {
"version": "7.19.5",
"resolved": "https://registry.npmmirror.com/@babel/standalone/-/standalone-7.19.5.tgz",
"integrity": "sha512-H2eXpo1ZfTZhBwsCbfSKHrjTb934laSas14hdjULLSKmLxU4B7kazQKm3mjpDuH/HyPmRq1cbrGL7223M7EDFw==",
"dev": true
},
"@babel/template": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
......@@ -1231,6 +1237,87 @@
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
},
"@codemirror/autocomplete": {
"version": "6.3.0",
"resolved": "https://registry.npmmirror.com/@codemirror/autocomplete/-/autocomplete-6.3.0.tgz",
"integrity": "sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0"
}
},
"@codemirror/commands": {
"version": "6.1.1",
"resolved": "https://registry.npmmirror.com/@codemirror/commands/-/commands-6.1.1.tgz",
"integrity": "sha512-ibDohwkk7vyu3VsnZNlQhwk0OETBtlkYV+6AHfn5Zgq0sxa+yGVX+apwtC3M4wh6AH7yU5si/NysoECs5EGS3Q==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0"
}
},
"@codemirror/language": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/@codemirror/language/-/language-6.2.1.tgz",
"integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"@codemirror/lint": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/@codemirror/lint/-/lint-6.0.0.tgz",
"integrity": "sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"@codemirror/search": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/@codemirror/search/-/search-6.2.1.tgz",
"integrity": "sha512-Q1JgUSBjQZRPIddlXzad/AVDigdhriLxQNFyP0gfrDTq6LDHNhr95U/tW3bpVssGenkaLzujtu/7XoK4kyvL3g==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"@codemirror/state": {
"version": "6.1.2",
"resolved": "https://registry.npmmirror.com/@codemirror/state/-/state-6.1.2.tgz",
"integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA=="
},
"@codemirror/theme-one-dark": {
"version": "6.1.0",
"resolved": "https://registry.npmmirror.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.0.tgz",
"integrity": "sha512-AiTHtFRu8+vWT9wWUWDM+cog6ZwgivJogB1Tm/g40NIpLwph7AnmxrSzWfvJN5fBVufsuwBxecQCNmdcR5D7Aw==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"@codemirror/view": {
"version": "6.3.1",
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.3.1.tgz",
"integrity": "sha512-NKPBphoV9W2Q6tKXk+ge4q5EhMOOC0rpwdGS80/slNSfsVqkN4gwXIEqSprXJFlf9aUKZU7WhPvqRBMNH+hJkQ==",
"requires": {
"@codemirror/state": "^6.0.0",
"style-mod": "^4.0.0",
"w3c-keyname": "^2.2.4"
}
},
"@csstools/normalize.css": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz",
......@@ -2109,6 +2196,27 @@
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz",
"integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg=="
},
"@lezer/common": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@lezer/common/-/common-1.0.1.tgz",
"integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw=="
},
"@lezer/highlight": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/@lezer/highlight/-/highlight-1.1.1.tgz",
"integrity": "sha512-duv9D23O9ghEDnnUDmxu+L8pJy4nYo4AbCOHIudUhscrLSazqeJeK1V50EU6ZufWF1zv0KJwu/frFRyZWXxHBQ==",
"requires": {
"@lezer/common": "^1.0.0"
}
},
"@lezer/lr": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/@lezer/lr/-/lr-1.2.3.tgz",
"integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==",
"requires": {
"@lezer/common": "^1.0.0"
}
},
"@mui/base": {
"version": "5.0.0-alpha.79",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.79.tgz",
......@@ -3191,6 +3299,43 @@
"eslint-visitor-keys": "^3.0.0"
}
},
"@uiw/codemirror-extensions-basic-setup": {
"version": "4.12.4",
"resolved": "https://registry.npmmirror.com/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.12.4.tgz",
"integrity": "sha512-owSCcRBtS2wYjxgBFkuIjfjWJHsR8AxgsQtqPpHB/6U0zCLuzKS/OM5ZRS2T3rdOizg0hCPztVvmshWeKjF+qw==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"@uiw/react-codemirror": {
"version": "4.12.4",
"resolved": "https://registry.npmmirror.com/@uiw/react-codemirror/-/react-codemirror-4.12.4.tgz",
"integrity": "sha512-92TAvN2z5snPjPtJDLmbqrqsXXYFYlBnWraXZuDc1XGaw80tB26ZkdEW79CD2QM4Y9LhFIt+sauwlmiAVDs/5A==",
"requires": {
"@babel/runtime": "^7.18.6",
"@codemirror/commands": "^6.1.0",
"@codemirror/state": "^6.1.1",
"@codemirror/theme-one-dark": "^6.0.0",
"@uiw/codemirror-extensions-basic-setup": "4.12.4",
"codemirror": "^6.0.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.4",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.19.4.tgz",
"integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"@webassemblyjs/ast": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
......@@ -4212,6 +4357,20 @@
"q": "^1.1.2"
}
},
"codemirror": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
......@@ -4410,6 +4569,11 @@
"yaml": "^1.10.0"
}
},
"crelt": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
......@@ -8367,9 +8531,9 @@
}
},
"js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz",
"integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
"version": "3.7.2",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.2.tgz",
"integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ=="
},
"js-cookie": {
"version": "2.2.1",
......@@ -10223,6 +10387,16 @@
}
}
},
"raw-loader": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/raw-loader/-/raw-loader-4.0.2.tgz",
"integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
"dev": true,
"requires": {
"loader-utils": "^2.0.0",
"schema-utils": "^3.0.0"
}
},
"react": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.1.0.tgz",
......@@ -11227,6 +11401,11 @@
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ=="
},
"style-mod": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/style-mod/-/style-mod-4.0.0.tgz",
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw=="
},
"stylehacks": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz",
......@@ -11655,6 +11834,11 @@
"version": "0.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-0.1.2.tgz",
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
},
"js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz",
"integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
}
}
},
......@@ -11842,6 +12026,11 @@
"browser-process-hrtime": "^1.0.0"
}
},
"w3c-keyname": {
"version": "2.2.6",
"resolved": "https://registry.npmmirror.com/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg=="
},
"w3c-xmlserializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
......
{
"name": "bkunyun-demo",
"version": "0.1.0",
"private": true,
"proxy": "",
"homepage": "/v3/",
"dependencies": {
"@babel/core": "^7.16.0",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.84",
"@mui/material": "^5.6.4",
"@mui/styles": "^5.8.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.0",
"@types/node": "^16.11.33",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"ahooks": "^3.3.12",
"axios": "^0.27.2",
"babel-jest": "^27.4.2",
"babel-loader": "^8.2.3",
"babel-plugin-named-asset-import": "^0.3.8",
"babel-preset-react-app": "^10.0.1",
"bfj": "^7.0.2",
"browserslist": "^4.18.1",
"camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"classnames": "^2.3.1",
"crypto-js": "^4.1.1",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"identity-obj-proxy": "^3.0.0",
"immer": "^9.0.12",
"jest": "^27.4.3",
"jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0",
"kekule": "^0.9.7",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.5",
"mobx": "^6.5.0",
"mobx-react": "^7.4.0",
"mobx-react-lite": "^3.4.0",
"mockjs": "^1.1.0",
"moment": "^2.29.3",
"ngl": "^0.10.4",
"postcss": "^8.4.4",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-loader": "^6.2.1",
"postcss-normalize": "^10.0.1",
"postcss-preset-env": "^7.0.1",
"prompts": "^2.4.2",
"qs": "^6.10.3",
"react": "^18.1.0",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.1",
"react-dom": "^18.1.0",
"react-dropzone": "^14.2.1",
"react-flow-renderer": "^10.3.7",
"react-refresh": "^0.11.0",
"react-router-dom": "^6.3.0",
"resolve": "^1.20.0",
"resolve-url-loader": "^4.0.0",
"sass-loader": "^12.3.0",
"semver": "^7.3.5",
"source-map-loader": "^3.0.0",
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5",
"tss-react": "^3.7.0",
"tus-js-client": "2.1.1",
"typescript": "^4.6.4",
"use-immer": "^0.7.0",
"web-vitals": "^2.1.4",
"webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2",
"workbox-webpack-plugin": "^6.4.1"
},
"scripts": {
"start:master": "set \"REACT_APP_ENV=master\" && npm start",
"start:dev-cn": "set \"REACT_APP_ENV=dev-cn\" && npm start",
"start:dev-en": "set \"REACT_APP_ENV=dev-en\" && npm start",
"start:release-cn": "set \"REACT_APP_ENV=release-cn\" && npm start",
"start:release-en": "set \"REACT_APP_ENV=release-en\" && npm start",
"start": "node scripts/start.js",
"build:master": "node --max-old-space-size=6144 scripts/build-master.js",
"build:dev-cn": "node --max-old-space-size=6144 scripts/build-dev-cn.js",
"build:dev-en": "node --max-old-space-size=6144 scripts/build-dev-en.js",
"build:release-cn": "node --max-old-space-size=6144 scripts/build-release-cn.js",
"build:release-en": "node --max-old-space-size=6144 scripts/build-release-en.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"jest": {
"roots": [
"<rootDir>/src"
],
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts"
],
"setupFiles": [
"react-app-polyfill/jsdom"
],
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.ts"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
],
"testEnvironment": "jsdom",
"transform": {
"^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/config/jest/babelTransform.js",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
"^.+\\.module\\.(css|sass|scss)$"
],
"modulePaths": [],
"moduleNameMapper": {
"^react-native$": "react-native-web",
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
],
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
],
"resetMocks": true
},
"babel": {
"presets": [
"react-app"
]
},
"devDependencies": {
"@types/crypto-js": "^4.1.1",
"@types/mockjs": "^1.0.6"
}
"name": "bkunyun-demo",
"version": "0.1.0",
"private": true,
"proxy": "",
"homepage": "/v3/",
"dependencies": {
"@babel/core": "^7.16.0",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.84",
"@mui/material": "^5.6.4",
"@mui/styles": "^5.8.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.0",
"@types/node": "^16.11.33",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"@uiw/react-codemirror": "^4.12.4",
"ahooks": "^3.3.12",
"axios": "^0.27.2",
"babel-jest": "^27.4.2",
"babel-loader": "^8.2.3",
"babel-plugin-named-asset-import": "^0.3.8",
"babel-preset-react-app": "^10.0.1",
"bfj": "^7.0.2",
"browserslist": "^4.18.1",
"camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"classnames": "^2.3.1",
"crypto-js": "^4.1.1",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"identity-obj-proxy": "^3.0.0",
"immer": "^9.0.12",
"jest": "^27.4.3",
"jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0",
"js-base64": "^3.7.2",
"kekule": "^0.9.7",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.5",
"mobx": "^6.5.0",
"mobx-react": "^7.4.0",
"mobx-react-lite": "^3.4.0",
"mockjs": "^1.1.0",
"moment": "^2.29.3",
"ngl": "^0.10.4",
"postcss": "^8.4.4",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-loader": "^6.2.1",
"postcss-normalize": "^10.0.1",
"postcss-preset-env": "^7.0.1",
"prompts": "^2.4.2",
"qs": "^6.10.3",
"react": "^18.1.0",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.1",
"react-dom": "^18.1.0",
"react-dropzone": "^14.2.1",
"react-flow-renderer": "^10.3.7",
"react-refresh": "^0.11.0",
"react-router-dom": "^6.3.0",
"resolve": "^1.20.0",
"resolve-url-loader": "^4.0.0",
"sass-loader": "^12.3.0",
"semver": "^7.3.5",
"source-map-loader": "^3.0.0",
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5",
"tss-react": "^3.7.0",
"tus-js-client": "2.1.1",
"typescript": "^4.6.4",
"use-immer": "^0.7.0",
"web-vitals": "^2.1.4",
"webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2",
"workbox-webpack-plugin": "^6.4.1"
},
"scripts": {
"start:master": "set \"REACT_APP_ENV=master\" && npm start",
"start:dev-cn": "set \"REACT_APP_ENV=dev-cn\" && npm start",
"start:dev-en": "set \"REACT_APP_ENV=dev-en\" && npm start",
"start:release-cn": "set \"REACT_APP_ENV=release-cn\" && npm start",
"start:release-en": "set \"REACT_APP_ENV=release-en\" && npm start",
"start": "node scripts/start.js",
"build:master": "node --max-old-space-size=6144 scripts/build-master.js",
"build:dev-cn": "node --max-old-space-size=6144 scripts/build-dev-cn.js",
"build:dev-en": "node --max-old-space-size=6144 scripts/build-dev-en.js",
"build:release-cn": "node --max-old-space-size=6144 scripts/build-release-cn.js",
"build:release-en": "node --max-old-space-size=6144 scripts/build-release-en.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"jest": {
"roots": [
"<rootDir>/src"
],
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts"
],
"setupFiles": [
"react-app-polyfill/jsdom"
],
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.ts"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
],
"testEnvironment": "jsdom",
"transform": {
"^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/config/jest/babelTransform.js",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
"^.+\\.module\\.(css|sass|scss)$"
],
"modulePaths": [],
"moduleNameMapper": {
"^react-native$": "react-native-web",
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
],
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
],
"resetMocks": true
},
"babel": {
"presets": [
"react-app"
]
},
"devDependencies": {
"@babel/standalone": "^7.19.5",
"@types/crypto-js": "^4.1.1",
"@types/mockjs": "^1.0.6",
"raw-loader": "^4.0.2"
}
}
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3701233" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe607;</span>
<div class="name">点赞</div>
<div class="code-name">&amp;#xe607;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9b2;</span>
<div class="name">搜索-223</div>
<div class="code-name">&amp;#xe9b2;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1665568301019') format('woff2'),
url('iconfont.woff?t=1665568301019') format('woff'),
url('iconfont.ttf?t=1665568301019') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-dianzan"></span>
<div class="name">
点赞
</div>
<div class="code-name">.icon-dianzan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-sousuo-223"></span>
<div class="name">
搜索-223
</div>
<div class="code-name">.icon-sousuo-223
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dianzan"></use>
</svg>
<div class="name">点赞</div>
<div class="code-name">#icon-dianzan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-sousuo-223"></use>
</svg>
<div class="name">搜索-223</div>
<div class="code-name">#icon-sousuo-223</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>
@font-face {
font-family: "iconfont"; /* Project id 3701233 */
src: url('iconfont.woff2?t=1665568301019') format('woff2'),
url('iconfont.woff?t=1665568301019') format('woff'),
url('iconfont.ttf?t=1665568301019') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-dianzan:before {
content: "\e607";
}
.icon-sousuo-223:before {
content: "\e9b2";
}
window._iconfont_svg_string_3701233='<svg><symbol id="icon-dianzan" viewBox="0 0 1064 1024"><path d="M204.8 440.32a30.72 30.72 0 0 0-30.72 30.72v368.64c0 16.95744 13.76256 30.72 30.72 30.72h51.2v-430.08H204.8z m-133.12 30.72A133.12 133.12 0 0 1 204.8 337.92h102.4c28.2624 0 51.2 22.9376 51.2 51.2v532.48c0 28.2624-22.9376 51.2-51.2 51.2H204.8a133.12 133.12 0 0 1-133.12-133.12v-368.64z" fill="#1D1D1F" ></path><path d="M512.94208 140.41088c-23.18336 71.35232-57.42592 138.89536-89.45664 190.0544-16.384 26.17344-32.80896 48.98816-47.59552 66.31424-7.3728 8.6016-14.99136 16.62976-22.65088 23.26528-6.10304 5.24288-18.0224 14.82752-33.5872 18.75968a51.2 51.2 0 0 1-33.01376-96.58368c2.4576-2.12992 6.26688-5.98016 11.38688-12.00128 10.6496-12.45184 24.1664-30.88384 38.66624-54.14912 29.12256-46.4896 60.2112-108.29824 80.32256-171.86816 7.08608-22.28224 23.7568-45.99808 52.18304-56.89344 47.5136-18.18624 125.7472-27.27936 172.60544 40.50944 21.01248 30.43328 30.22848 70.41024 30.3104 117.30944 0.08192 32.11264-4.096 69.30432-12.98432 112.31232h167.1168c46.61248 0 101.82656 19.0464 130.37568 70.8608 60.66176 110.01856 85.1968 302.4896-81.79712 521.17504-32.31744 42.27072-82.3296 63.32416-131.8912 63.32416H307.2a51.2 51.2 0 1 1 0-102.4h435.77344c21.34016 0 39.7312-9.0112 50.46272-23.10144 142.9504-187.14624 114.11456-335.91296 73.5232-409.6-4.87424-8.8064-18.0224-17.85856-40.67328-17.85856H593.92a51.2 51.2 0 0 1-49.31584-64.9216c18.432-66.27328 25.1904-114.85184 25.14944-149.54496-0.08192-35.06176-7.168-52.0192-12.20608-59.35104-4.99712-7.20896-16.67072-14.58176-44.60544-5.61152zM284.672 343.81824l0.69632-0.49152a4.096 4.096 0 0 1-0.69632 0.49152z" fill="#1D1D1F" ></path></symbol><symbol id="icon-sousuo-223" viewBox="0 0 1024 1024"><path d="M467.456 900.949333C228.522667 900.949333 34.133333 706.56 34.133333 467.456S228.522667 34.133333 467.456 34.133333s433.493333 194.389333 433.493333 433.322667-194.389333 433.493333-433.493333 433.493333z m0-815.616C256.853333 85.333333 85.333333 256.853333 85.333333 467.456s171.52 382.122667 382.122667 382.122667 382.293333-171.52 382.293333-382.122667S678.229333 85.333333 467.456 85.333333z" fill="#333333" ></path><path d="M331.776 333.482667c-6.485333 0-13.141333-2.56-18.090667-7.509334a25.429333 25.429333 0 0 1 0-36.181333c41.130667-41.130667 95.744-63.658667 153.770667-63.658667 58.197333 0 112.810667 22.698667 153.770667 63.658667 10.069333 10.069333 10.069333 26.282667 0 36.181333-10.069333 10.069333-26.282667 10.069333-36.181334 0a165.239467 165.239467 0 0 0-117.589333-48.64c-44.373333 0-86.186667 17.237333-117.589333 48.64-4.949333 4.949333-11.434667 7.509333-18.090667 7.509334zM964.266667 989.866667c-6.485333 0-13.141333-2.56-18.090667-7.509334L742.570667 778.752c-10.069333-10.069333-10.069333-26.282667 0-36.181333s26.282667-10.069333 36.181333 0l203.605333 203.605333c10.069333 10.069333 10.069333 26.282667 0 36.181333-4.949333 4.949333-11.605333 7.509333-18.090666 7.509334z" fill="#333333" ></path></symbol></svg>',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var i,o,c,a,d,s=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}i=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_3701233,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?s(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(c=i,a=n.document,d=!1,r(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,l())})}function l(){d||(d=!0,c())}function r(){try{a.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}}(window);
\ No newline at end of file
{
"id": "3701233",
"name": "云平台",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "北鲲云云平台",
"glyphs": [
{
"icon_id": "32228179",
"name": "点赞",
"font_class": "dianzan",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "28529168",
"name": "搜索-223",
"font_class": "sousuo-223",
"unicode": "e9b2",
"unicode_decimal": 59826
}
]
}
......@@ -23,6 +23,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="%PUBLIC_URL%/iconfont/iconfont.css" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
......
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 09:56:57
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 15:30:28
* @LastEditTime: 2022-10-19 21:14:11
* @FilePath: /bkunyun/src/api/api_manager.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -49,6 +49,12 @@ const RESTAPI = {
API_ADD_PROJECT_USER:`${BACKEND_API_URI_PREFIX}/cpp/project/updatemember`, // 添加项目成员
API_GET_PROJECT_POWER:`${BACKEND_API_URI_PREFIX}/cpp/project/listroles`, // 获取项目权限
API_GET_HARDWARE:`${BACKEND_API_URI_PREFIX}/cpp/cpce/hardware`, // 获取计算队列列表
API_GET_PUBLIC_ENV:`${BACKEND_API_URI_PREFIX}/cpp/common/public/env`, // 获取公共环境
API_GET_PUBLIC_PROJECT:`${BACKEND_API_URI_PREFIX}/cpp/common/public/project`, // 获取公共环境
API_ACTORENV_BUILDENV:`${BACKEND_API_URI_PREFIX}/cpp/actorenv/buildenv`, // 新增应用环境
API_ACTORENV_LIST:`${BACKEND_API_URI_PREFIX}/cpp/actorenv/list`, // 查询用户的应用环境(算子环境)
API_ACTORENV_DELETE:`${BACKEND_API_URI_PREFIX}/cpp/actorenv/delete`, // 删除用户算子环境
API_ACTORENV_DETAIL:`${BACKEND_API_URI_PREFIX}/cpp/actorenv/detail`, // 查询应用环境的详情信息
};
export default RESTAPI;
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-30 16:22:15
* @LastEditTime: 2022-10-17 11:51:35
* @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -36,7 +36,7 @@ switch (process.env.REACT_APP_ENV) {
BACKEND_API_URI_PREFIX = "https://www.cloudam.cn";
}
else {
BACKEND_API_URI_PREFIX = "http://47.75.104.171";
BACKEND_API_URI_PREFIX = "http://47.57.4.97";
}
break;
}
......
......@@ -105,7 +105,7 @@ class CloudEController {
headers["Cache-Control"] = "no-cache";
headers["delfilepath"] = Base64.stringify(Utf8.parse(urls));
let url = "";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(APIOPTION() + "/delete/" + url, {
......@@ -129,7 +129,7 @@ class CloudEController {
) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(
......@@ -151,7 +151,7 @@ class CloudEController {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
// headers['parentName'] = ''
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(
......@@ -172,7 +172,7 @@ class CloudEController {
) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url = urlToken(filetoken, projectId) + "&q=" + url;
}
return axios.get(
......@@ -188,7 +188,7 @@ class CloudEController {
// static JobOutFileListMove(url: any, filetoken: string, projectId: string) {
// if (ApiUtils.getAuthorizationHeaders(headers)) {
// headers["Cache-Control"] = "no-cache";
// if (getLoaclStorageOfKey("userinfo")) {
// if (getLoaclStorageOfKey("userInfo")) {
// url += urlToken(filetoken, projectId);
// }
// return axios.get(APIOPTION() + "/download" + url, {
......@@ -260,13 +260,14 @@ class CloudEController {
}
// 获取文件文本内容(字符串)
static JobFileDownloadText(url: any, filetoken: string, projectId: string) {
static JobFileDownloadText(url: any, filetoken: string, projectId: string, fileServerEndPoint: string = '') {
if (ApiUtils.getAuthorizationHeaders(headers)) {
url = url + urlToken(filetoken, projectId);
headers["Cache-Control"] = "no-cache";
headers["Content-Type"] = "multipart/form-data";
let origin = fileServerEndPoint ? fileServerEndPoint : APIOPTION()
return axios.get(
APIOPTION() + "/download" + url + "&showhidden=false",
origin + "/download" + url + "&showhidden=false",
{
headers: headers,
}
......
......@@ -30,14 +30,14 @@ const APIPORT = function () {
// 当前计算区
// let currentRegion = localStorage.getItem("current-region");
// let currentRegionJson = currentRegion && JSON.parse(currentRegion);
// let user = getLoaclStorageOfKey("userinfo");
// let user = getLoaclStorageOfKey("userInfo");
// 文件路径
// const FILEPATH =
// currentRegionJson &&
// currentRegionJson.location &&
// currentRegionJson.location === "ON_PREMISE" &&
// localStorage.getItem("userinfo")
// localStorage.getItem("userInfo")
// ? `/home/${user.name}`
// : "/home/cloudam";
const FILEPATH_SHARE = "/share";
......@@ -62,7 +62,7 @@ const urlToken = (filetoken: string, projectId: string) => {
};
const getUuid = () => {
const userInfo = getLoaclStorageOfKey("userinfo");
const userInfo = getLoaclStorageOfKey("userInfo");
// 是否共有文件系统
if (
localStorage.getItem("isShareFileSystem") &&
......@@ -75,12 +75,12 @@ const getUuid = () => {
};
const USERNAME = () => {
return getLoaclStorageOfKey("userinfo").name;
return getLoaclStorageOfKey("userInfo").name;
};
// 加密传输
const encryptTransfer = () => {
const userInfo = getLoaclStorageOfKey("userinfo");
const userInfo = getLoaclStorageOfKey("userInfo");
if (userInfo) {
let encryptTransfer = userInfo.encryptTransfer;
if (encryptTransfer) {
......
......@@ -354,7 +354,6 @@ const getHardwreList = (params: {zoneId: string, computeType: string}) => {
params,
});
}
//
export {
current,
......
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-19 17:09:23
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 21:14:35
* @FilePath: /bkunyun/src/api/resourceCenter.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import request from "@/utils/axios/service";
import Api from "./api_manager";
type addActorenvBuildenvParams = {
title: string,
desc: string,
baseEnvId: string,
type: "BATCH" | "FLOW",
filePaths: Array<string>,
bashScript: string,
computeType: string,
publicProjectId: string,
}
/** 获取算子列表请求参数 */
export interface IOperatorListParams {
keyword: string;
productId: string;
type: string;
}
// 获取公共项目
const getPublicProject = () => {
return request({
url: Api.API_GET_PUBLIC_PROJECT,
method: "get",
});
}
// 获取公共环境
const getPublicEnv = (params: {taskType: 'BATCH' | 'FLOW'}) => {
return request({
url: Api.API_GET_PUBLIC_ENV,
method: "get",
params,
});
};
// 新增应用环境
const addActorenvBuildenv = (params: addActorenvBuildenvParams) => {
return request({
url: Api.API_ACTORENV_BUILDENV,
method: "post",
data: params,
});
};
// 获取公共环境
const getActorenvList = (params: {
type: 'BATCH' | 'FLOW' | '',
page: number,
size: number,
title?: string,
}) => {
return request({
url: Api.API_ACTORENV_LIST,
method: "get",
params,
});
};
// 删除用户算子环境
const deleteActorenv = (params: {id: string}) => {
return request({
url:`${Api.API_ACTORENV_DELETE}/${params.id}`,
method: "delete",
});
};
// 获取算子列表
const getOperatorList = (data: IOperatorListParams) => {
return request({
url: Api.API_OPERATOR_LIST,
method: "get",
data
});
}
// 查询应用环境的详情信息
const getActorenvDetail = (params: {id: string}) => {
return request({
url:`${Api.API_ACTORENV_DETAIL}/${params.id}`,
method: "get",
});
};
export {
getPublicEnv,
getPublicProject,
addActorenvBuildenv,
getActorenvList,
deleteActorenv,
getOperatorList,
getActorenvDetail,
};
<?xml version="1.0" encoding="UTF-8"?>
<svg width="240px" height="249px" viewBox="0 0 240 249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 18</title>
<defs>
<rect id="path-1" x="0" y="0" width="240" height="249" rx="8"></rect>
<filter x="-16.1%" y="-19.6%" width="132.2%" height="139.2%" filterUnits="objectBoundingBox" id="filter-3">
<feOffset dx="0" dy="3" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.803607664 0 0 0 0 0.598314046 0 0 0 0 0.12907149 0 0 0 1 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<rect id="path-4" x="0" y="0" width="99.2784993" height="81.6780822" rx="4.95365079"></rect>
<rect id="path-6" x="0" y="0" width="37.2294372" height="27.2260274" rx="2.4768254"></rect>
<filter x="-21.5%" y="-25.7%" width="143.0%" height="158.8%" filterUnits="objectBoundingBox" id="filter-7">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 1 0 0 0 0 0.951385579 0 0 0 0 0.840266902 0 0 0 1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="新" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="个人资源-新建应用环境备份-6" transform="translate(-839.000000, -1033.000000)">
<g id="编组-20" transform="translate(106.000000, 996.000000)">
<g id="矩形备份-18" transform="translate(733.000000, 37.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="蒙版" fill="#FFFFFF" xlink:href="#path-1"></use>
<rect id="矩形备份-6" fill="#FFB919" mask="url(#mask-2)" x="0" y="0" width="240" height="165"></rect>
<g id="编组-8" mask="url(#mask-2)">
<g transform="translate(41.818182, 41.746575)">
<g id="编组-2" transform="translate(0.000000, 14.850560)">
<rect id="矩形" fill="#8C6713" x="0" y="0" width="38.4704185" height="25.9884807" rx="2.4768254"></rect>
<g id="baoguo_dabao_o" transform="translate(12.409812, 4.950187)" fill="#F7F8FA" fill-rule="nonzero">
<path d="M11.7329135,6.19484584 L14.8917749,8.04405355 L11.7329135,9.89326125 L14.8917749,11.742469 L7.49101403,16.0881071 L0,11.742469 L3.15886133,9.89326125 L0,8.04405355 L3.15886133,6.19484584 L0,4.34563812 L7.40076084,0 L14.8015217,4.43809851 L11.7329135,6.19484584 Z M4.06139315,6.74960816 L1.80506362,8.04405355 L7.40076084,11.3726274 L12.9964581,8.04405355 L10.8303817,6.74960816 L7.40076084,8.78373663 L4.06139315,6.74960816 L4.06139315,6.74960816 Z M10.8303817,10.4480236 L7.40076084,12.4821521 L3.97113996,10.4480236 L1.80506362,11.742469 L7.40076084,15.0710429 L12.9964581,11.742469 L10.8303817,10.4480236 L10.8303817,10.4480236 Z M7.40076084,1.10952463 L1.80506362,4.34563812 L7.40076084,7.674212 L12.9964581,4.34563812 L7.40076084,1.10952463 L7.40076084,1.10952463 Z" id="形状"></path>
</g>
</g>
<g id="编组-3" transform="translate(0.000000, 45.789228)">
<rect id="矩形备份-7" fill="#8C6713" x="0" y="0" width="38.4704185" height="25.9884807" rx="2.4768254"></rect>
<g id="jiaobendingyix" transform="translate(12.409812, 7.425280)" fill="#F7F8FA" fill-rule="nonzero">
<path d="M3.7866091,10.6317335 L10.2741601,0 L11.1787711,0.507996798 L4.69122013,11.1379203 L3.7866091,10.6311301 L3.7866091,10.6317335 Z M1.05203093,5.53366584 L3.89222039,2.83862819 L3.82055559,2.71856719 L3.34530476,1.94028231 L0.314009146,4.81993637 C-0.100219148,5.2154654 -0.105267035,5.85737409 0.30269365,6.25885841 L3.33398926,9.19824131 L3.88719128,8.29024229 L1.05203093,5.53366584 Z M14.5778203,4.81993637 L11.5465247,1.94028231 L11.0712739,2.71856719 L10.9989804,2.83983483 L13.8397985,5.53487248 L11.0046382,8.29144893 L11.5559543,9.19944796 L14.5885072,6.26006506 C14.9971223,5.85825286 14.9920932,5.21631867 14.5778203,4.81993637 Z" id="形状"></path>
</g>
</g>
<g id="编组-19" transform="translate(34.747475, 0.000000)">
<g id="矩形" filter="url(#filter-3)">
<mask id="mask-5" fill="white">
<use xlink:href="#path-4"></use>
</mask>
<use id="蒙版" fill="#FFFFFF" xlink:href="#path-4"></use>
<rect fill="#DBDCE5" mask="url(#mask-5)" x="0" y="0" width="99.2784993" height="14.8505604"></rect>
</g>
<ellipse id="椭圆形" fill="#FFFFFF" cx="7.44588745" cy="7.4252802" rx="2.48196248" ry="2.4750934"></ellipse>
<ellipse id="椭圆形备份" fill="#FFFFFF" cx="14.8917749" cy="7.4252802" rx="2.48196248" ry="2.4750934"></ellipse>
<ellipse id="椭圆形备份-2" fill="#FFFFFF" cx="22.3376623" cy="7.4252802" rx="2.48196248" ry="2.4750934"></ellipse>
<g id="编组-7" transform="translate(4.963925, 22.275841)">
<rect id="矩形" fill="#E0E2EA" x="0" y="19.8007472" width="22.3376623" height="9.9003736" rx="2.4768254"></rect>
<rect id="矩形备份-10" fill="#E0E2EA" x="34.7474747" y="0" width="22.3376623" height="9.9003736" rx="2.4768254"></rect>
<rect id="矩形备份-11" fill="#E0E2EA" x="34.7474747" y="19.8007472" width="22.3376623" height="9.9003736" rx="2.4768254"></rect>
<rect id="矩形备份-15" fill="#E0E2EA" x="70.7359307" y="19.8007472" width="22.3376623" height="9.9003736" rx="2.4768254"></rect>
<rect id="矩形备份-12" fill="#E0E2EA" x="34.7474747" y="39.6014944" width="22.3376623" height="9.9003736" rx="2.4768254"></rect>
<line x1="22.3376623" y1="24.750934" x2="34.7474747" y2="24.750934" id="路径-3" stroke="#979797" stroke-width="1.2384127"></line>
<path d="M34.7474747,4.9501868 L31.0193939,4.9501868 C29.651481,4.9501868 28.5425685,6.0590993 28.5425685,7.4270122 L28.5425685,42.0748558 C28.5425685,43.4427687 29.651481,44.5516812 31.0193939,44.5516812 L34.7474747,44.5516812 L34.7474747,44.5516812" id="路径-4" stroke="#979797" stroke-width="1.2384127"></path>
<path d="M57.0851371,44.5516812 L61.1437185,44.5516812 C62.5116314,44.5516812 63.6205439,43.4427687 63.6205439,42.0748558 L63.6205439,7.4270122 C63.6205439,6.0590993 62.5116314,4.9501868 61.1437185,4.9501868 L57.0851371,4.9501868 L57.0851371,4.9501868" id="路径-5" stroke="#979797" stroke-width="1.2384127"></path>
<line x1="57.0851371" y1="24.750934" x2="70.7359307" y2="24.750934" id="路径-6" stroke="#979797" stroke-width="1.2384127"></line>
</g>
<g id="编组-5" transform="translate(84.386724, 33.413761)">
<g id="矩形备份-14">
<use fill="black" fill-opacity="1" filter="url(#filter-7)" xlink:href="#path-6"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-6"></use>
</g>
<g id="chenggong" transform="translate(9.927850, 4.950187)" fill="#52C41A" fill-rule="nonzero">
<path d="M8.68686869,17.3256538 C3.88934802,17.3256538 0,13.4470699 0,8.6628269 C0,3.87858386 3.88934802,0 8.68686869,0 C13.4843894,0 17.3737374,3.87858386 17.3737374,8.6628269 C17.3737374,13.4470699 13.4843894,17.3256538 8.68686869,17.3256538 Z M7.75342516,11.3065642 L4.9594123,8.52107155 C4.7260437,8.30421831 4.36237985,8.310617 4.13682763,8.53554498 C3.91127541,8.76047296 3.90485898,9.12313034 4.12231405,9.35585306 L7.35619835,12.5815748 C7.35828851,12.5836905 7.36039448,12.5857906 7.36251607,12.587875 L7.36725436,12.5918127 C7.49616719,12.7203159 7.67723197,12.7824704 7.85814663,12.7603224 C8.03906128,12.7381744 8.19967399,12.6341909 8.29359045,12.4784084 L14.539449,5.47175649 C14.6799538,5.31391506 14.7253445,5.09331261 14.6585228,4.89304795 C14.5917012,4.69278329 14.422819,4.54328138 14.2154925,4.50085815 C14.0081661,4.45843492 13.7938932,4.52953546 13.6533884,4.68737689 L7.75342516,11.3065642 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
<text id="构建批式Actor环境备份-2" mask="url(#mask-2)" font-family="PingFangSC-Medium, PingFang SC" font-size="16" font-weight="400" line-spacing="24" fill="#1E2633">
<tspan x="51.512" y="198.000467">构建批式Actor环境</tspan>
</text>
<text id="仅支持shell脚本" mask="url(#mask-2)" font-family="PingFangSC-Regular, PingFang SC" font-size="12" font-weight="normal" line-spacing="20" fill="#8A9099">
<tspan x="77.484" y="222">仅支持shell脚本</tspan>
</text>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="240px" height="249px" viewBox="0 0 240 249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 40备份 4</title>
<defs>
<rect id="path-1" x="0" y="0" width="240" height="249" rx="8"></rect>
<rect id="path-3" x="0" y="0" width="99.047619" height="81" rx="4.9632"></rect>
<filter x="-10.1%" y="-9.9%" width="120.2%" height="124.7%" filterUnits="objectBoundingBox" id="filter-5">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="3" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.114151225 0 0 0 0 0.59037626 0 0 0 0 0.477660275 0 0 0 1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
<rect id="path-6" x="0" y="0" width="37.1428571" height="27.4153846" rx="2.4816"></rect>
<filter x="-25.6%" y="-31.0%" width="151.2%" height="169.3%" filterUnits="objectBoundingBox" id="filter-7">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="3" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.734082611 0 0 0 0 0.827260778 0 0 0 0 0.805206774 0 0 0 1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="新" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="个人资源-新建应用环境备份-6" transform="translate(-839.000000, -1414.000000)">
<g id="编组-20" transform="translate(106.000000, 996.000000)">
<g id="编组-40备份-4" transform="translate(733.000000, 418.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="蒙版" fill="#FFFFFF" xlink:href="#path-1"></use>
<rect id="矩形" fill="#02AB83" mask="url(#mask-2)" x="0" y="0" width="240" height="165"></rect>
<g id="编组-39" mask="url(#mask-2)">
<g transform="translate(41.000000, 43.000000)">
<g id="编组-9" stroke-width="1" fill="none">
<g id="编组-2" transform="translate(0.000000, 15.282378)">
<rect id="矩形" fill="#11886C" x="0" y="0" width="38.3809524" height="26.1692308" rx="2.4816"></rect>
<g id="wenjianjia-2" transform="translate(11.142857, 4.984615)" fill="#FFFFFF" fill-rule="nonzero">
<path d="M14.9852217,2.21538513 L6.58850246,2.21538513 L5.71491954,0.58541596 C5.52198545,0.224798567 5.14553694,-0.000299468679 4.73588506,2.99033411e-07 L1.11001642,2.99033411e-07 C0.497842365,2.99033411e-07 0,0.496800579 0,1.10769286 L0,13.8461539 C0,14.4570462 0.497842365,14.9538462 1.11001642,14.9538462 L14.9852217,14.9538462 C15.5973957,14.9538462 16.0952381,14.4570462 16.0952381,13.8461539 L16.0952381,3.32307739 C16.0952381,2.71218511 15.5973957,2.21538513 14.9852217,2.21538513 Z M1.11001642,1.10769286 L4.73588506,1.10769286 L5.92304762,3.32307739 L14.9852217,3.32307739 L14.9852217,5.01895424 C14.9780066,5.01895424 14.9713465,5.01673886 14.9641314,5.01673886 L1.13166174,5.01673886 C1.12444663,5.01673886 1.11778654,5.01895424 1.11001642,5.01895424 L1.11001642,1.10769286 Z M1.11001642,13.8461539 L1.11001642,12.1846155 L1.13166174,6.12443112 L14.9852217,6.14547728 L14.9852217,12.1846155 L14.9863317,12.1846155 L14.9863317,13.8461539 L1.11001642,13.8461539 Z" id="形状"></path>
</g>
</g>
<g id="编组-3" transform="translate(0.000000, 46.436224)">
<rect id="矩形备份-7" fill="#11886C" x="0" y="0" width="38.3809524" height="26.1692308" rx="2.4816"></rect>
<g id="python-file-" transform="translate(12.380952, 6.230769)" fill="#FFFFFF" fill-rule="nonzero">
<path d="M8.66666667,13.0846154 C8.66666667,13.4287313 8.94382373,13.7076923 9.28571429,13.7076923 C9.62760485,13.7076923 9.9047619,13.4287313 9.9047619,13.0846154 C9.9047619,12.7404995 9.62760485,12.4615385 9.28571429,12.4615385 C8.94382373,12.4615385 8.66666667,12.7404995 8.66666667,13.0846154 Z" id="路径"></path>
<path d="M6.19047619,1.86923077 C6.19047619,2.21334665 6.46763325,2.49230769 6.80952381,2.49230769 C7.15141437,2.49230769 7.42857143,2.21334665 7.42857143,1.86923077 C7.42857143,1.52511489 7.15141437,1.24615385 6.80952381,1.24615385 C6.46763325,1.24615385 6.19047619,1.52511489 6.19047619,1.86923077 Z" id="路径"></path>
<path d="M13.1768708,3.47142857 L11.4081633,3.47142857 L11.4081633,1.69120879 C11.4081633,0.758373626 10.6546939,0 9.72789116,0 L5.1292517,0 C4.20244898,0 3.44897959,0.758373626 3.44897959,1.69120879 L3.44897959,3.47142857 L1.6802721,3.47142857 C0.753469388,3.47142857 0,4.2298022 0,5.16263736 L0,9.7912088 C0,10.724044 0.753469388,11.4824176 1.6802721,11.4824176 L3.44897959,11.4824176 L3.44897959,13.2626374 C3.44897959,14.1954725 4.20244898,14.9538462 5.1292517,14.9538462 L9.72789116,14.9538462 C10.6546939,14.9538462 11.4081633,14.1954725 11.4081633,13.2626374 L11.4081633,11.4824176 L13.1768708,11.4824176 C14.1036735,11.4824176 14.8571429,10.724044 14.8571429,9.7912088 L14.8571429,5.16263736 C14.8571429,4.2298022 14.1036735,3.47142857 13.1768708,3.47142857 Z M1.6802721,10.4142857 C1.33891155,10.4142857 1.06122449,10.1347912 1.06122449,9.7912088 L1.06122449,5.16263736 C1.06122449,4.81905493 1.33891157,4.53956044 1.6802721,4.53956044 L6.85374149,4.53956044 C7.14734694,4.53956044 7.38435374,4.30101099 7.38435374,4.00549451 C7.38435374,3.70997802 7.14734694,3.47142857 6.85374149,3.47142857 L4.51020408,3.47142857 L4.51020408,1.69120879 C4.51020408,1.34762636 4.78789116,1.06813187 5.1292517,1.06813187 L9.72789116,1.06813187 C10.0692517,1.06813187 10.3469388,1.34762638 10.3469388,1.69120879 L10.3469388,6.48534066 C10.3469388,6.73813188 10.1435374,6.94285714 9.89238096,6.94285714 L4.9647619,6.94285714 C4.12816327,6.94285714 3.44897959,7.62824176 3.44897959,8.46850549 L3.44897959,10.4142857 L1.6802721,10.4142857 Z M13.7959184,9.7912088 C13.7959184,10.1347912 13.5182313,10.4142857 13.1768708,10.4142857 L8.00340137,10.4142857 C7.70979592,10.4142857 7.47278912,10.6528352 7.47278912,10.9483516 C7.47278912,11.2438681 7.70979592,11.4824176 8.00340137,11.4824176 L10.3469388,11.4824176 L10.3469388,13.2626374 C10.3469388,13.6062198 10.0692517,13.8857143 9.72789116,13.8857143 L5.1292517,13.8857143 C4.78789115,13.8857143 4.51020408,13.6062198 4.51020408,13.2626374 L4.51020408,8.46850549 C4.51020408,8.21571427 4.71360545,8.01098901 4.9647619,8.01098901 L9.89238096,8.01098901 C10.7289796,8.01098901 11.4081633,7.32560439 11.4081633,6.48534066 L11.4081633,4.53956044 L13.1768708,4.53956044 C13.5182313,4.53956044 13.7959184,4.81905495 13.7959184,5.16263736 L13.7959184,9.7912088 Z" id="形状"></path>
</g>
</g>
<g id="编组-19备份" transform="translate(34.666667, 0.000000)">
<g id="矩形">
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<g id="蒙版">
<use fill="black" fill-opacity="1" filter="url(#filter-5)" xlink:href="#path-3"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-3"></use>
</g>
<rect fill="#DBDCE5" mask="url(#mask-4)" x="0" y="0" width="99.047619" height="14.7272727"></rect>
</g>
<ellipse id="椭圆形" fill="#FFFFFF" cx="7.42857143" cy="7.36363636" rx="2.47619048" ry="2.45454545"></ellipse>
<ellipse id="椭圆形备份" fill="#FFFFFF" cx="14.8571429" cy="7.36363636" rx="2.47619048" ry="2.45454545"></ellipse>
<ellipse id="椭圆形备份-2" fill="#FFFFFF" cx="22.2857143" cy="7.36363636" rx="2.47619048" ry="2.45454545"></ellipse>
<rect id="矩形" fill="#E0E2EA" x="6.19047619" y="22.0909091" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
<rect id="矩形备份-11" fill="#E0E2EA" x="70.5714286" y="22.0909091" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
<line x1="28.4761905" y1="27" x2="70.5714286" y2="27" id="路径-9" stroke="#979797" stroke-width="1.2408"></line>
<rect id="矩形备份-10" fill="#E0E2EA" x="38.3809524" y="22.0909091" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
<path d="M81.7142857,31.9090909 L81.7142857,44.7414853 C81.7142857,46.1120351 80.6032355,47.2230853 79.2326857,47.2230853 L19.8149333,47.2230853 C18.4443835,47.2230853 17.3333333,48.3341354 17.3333333,49.7046853 L17.3333333,64.3197986 C17.3333333,65.6903484 18.4443835,66.8013986 19.8149333,66.8013986 L42.5488933,66.8013986 L42.5488933,66.8013986" id="路径-10" stroke="#979797" stroke-width="1.2408"></path>
<rect id="矩形备份-12" fill="#E0E2EA" x="54.4761905" y="41.7839161" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
<rect id="矩形备份-13" fill="#E0E2EA" x="24.7619048" y="41.7839161" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
<g id="编组-21" transform="translate(84.190476, 32.928671)">
<g id="矩形备份-14">
<use fill="black" fill-opacity="1" filter="url(#filter-7)" xlink:href="#path-6"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-6"></use>
</g>
<g id="chenggong" transform="translate(9.904762, 4.984615)" fill="#52C41A" fill-rule="nonzero">
<path d="M8.66666667,17.1818182 C3.88030303,17.1818182 0,13.3354339 0,8.59090909 C0,3.84638429 3.88030303,0 8.66666667,0 C13.4530303,0 17.3333333,3.84638429 17.3333333,8.59090909 C17.3333333,13.3354339 13.4530303,17.1818182 8.66666667,17.1818182 Z M7.73539394,11.2126983 L4.94787878,8.45033058 C4.7150529,8.23527763 4.35223478,8.24162319 4.1272071,8.46468385 C3.90217943,8.68774451 3.89577791,9.04739115 4.11272728,9.27818182 L7.33909091,12.477124 C7.34117621,12.4792221 7.34327728,12.4813048 7.34539394,12.4833719 L7.35012121,12.4872769 C7.47873425,12.6147132 7.65937794,12.6763518 7.83987187,12.6543876 C8.02036579,12.6324235 8.18060499,12.5293033 8.27430303,12.3748141 L14.5056364,5.42633058 C14.6458144,5.26979954 14.6910995,5.0510285 14.6244333,4.85242642 C14.557767,4.65382433 14.3892775,4.50556357 14.1824333,4.46349253 C13.975589,4.42142149 13.7618144,4.49193177 13.6216364,4.64846281 L7.73539394,11.2126983 Z" id="形状"></path>
</g>
</g>
</g>
</g>
<rect id="矩形备份-16" fill="#E0E2EA" x="73.047619" y="61.9678322" width="22.2857143" height="9.81818182" rx="2.4816"></rect>
</g>
</g>
<text id="构建流式Actor环境" mask="url(#mask-2)" font-family="PingFangSC-Medium, PingFang SC" font-size="16" font-weight="400" line-spacing="24" fill="#1E2633">
<tspan x="51.512" y="198">构建流式Actor环境</tspan>
</text>
<text id="仅支持Python脚本" mask="url(#mask-2)" font-family="PingFangSC-Regular, PingFang SC" font-size="12" font-weight="normal" line-spacing="20" fill="#8A9099">
<tspan x="70.836" y="222">仅支持Python脚本</tspan>
</text>
</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>编组 6备份 5</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#136EEF" offset="0%"></stop>
<stop stop-color="#084FC2" offset="100%"></stop>
</linearGradient>
</defs>
<g id="新" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="个人资源-新建应用环境备份-6" transform="translate(-642.000000, -2505.000000)">
<g id="编组-20" transform="translate(106.000000, 996.000000)">
<g id="编组-10备份" transform="translate(392.000000, 1479.000000)">
<g id="编组-18" transform="translate(97.000000, 30.000000)">
<g id="编组-6备份-5" transform="translate(47.000000, 0.000000)">
<rect id="矩形" x="0" y="0" width="32" height="32"></rect>
<g id="编组-12备份-1" transform="translate(4.000000, 1.000000)" fill-rule="nonzero">
<path d="M2.52631579,0 L21.4736842,0 C22.8689053,0 24,1.1192875 24,2.5 L24,22.5 L17.6842105,30 L2.52631579,30 C1.13106947,30 0,28.8806875 0,27.5 L0,2.5 C0,1.1192875 1.13106947,0 2.52631579,0 Z" id="矩形备份-11" fill="url(#linearGradient-1)"></path>
<path d="M13.5789474,15 L13.5789474,18.5 C13.5788842,18.7321875 13.4965263,18.95475 13.35,19.1186875 C13.2034105,19.282875 13.0047789,19.375 12.7976842,19.375 L11.2023158,19.375 C10.9952842,19.375 10.7966526,19.2829375 10.65,19.118875 C10.5034105,18.954875 10.4210526,18.732125 10.4210526,18.4998125 L10.4210526,15 L13.5789474,15 Z M12.9473684,16.875 L11.0526316,16.875 L11.0526316,18.75 L12.9473684,18.75 L12.9473684,16.875 Z M13.5789474,11.25 L13.5789474,13.125 L11.6842105,13.125 L11.6842105,11.25 L13.5789474,11.25 Z M12.0032842,0 L12.0032842,1.7237625 L13.5789474,1.7237625 L13.5789474,3.447525 L12.0031579,3.447525 L12.0031579,5.043575 L13.5789474,5.043575 L13.5789474,6.7673125 L12.0032842,6.7673125 L12.0032842,8.4699375 L13.5789474,8.4699375 L13.5789474,10.1725625 L12.0032842,10.1725625 L12.0032842,11.875 L10.4210526,11.875 L10.4210526,10.172375 L11.9967158,10.172375 L11.9967158,8.4698125 L10.4210526,8.4698125 L10.4210526,6.7673125 L11.9967158,6.7673125 L11.9967158,5.043575 L10.4210526,5.043575 L10.4210526,3.3198125 L11.9967158,3.3198125 L11.9967158,1.7237625 L10.4210526,1.7237625 L10.4210526,0 L12.0032842,0 Z" id="形状" fill="#FFFFFF"></path>
<polygon id="矩形备份-13" fill="#FFFFFF" opacity="0.5" points="17.6842105 22.5 24 22.5 20.8421053 26.25 17.6842105 30"></polygon>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
import CodeMirror from "@uiw/react-codemirror";
type ICodeType = {
value: string;
onChange: any;
height?: string;
theme?: "light" | "dark";
};
const Code = (props: ICodeType) => {
const { value, onChange, height, theme = "dark" } = props;
return (
<CodeMirror
height={height || "100%"}
value={value}
onChange={(e) => onChange(e)}
theme={theme}
/>
);
};
export default Code;
......@@ -7,9 +7,10 @@ import NotFound from "@/views/404";
import useMyRequest from "@/hooks/useMyRequest";
import { useEffect } from "react";
import { menu } from "@/api/routes_api";
import { IProductOption } from "@/store/modules/productList";
const useMyRouter = () => {
const { permissionStore, menuStore } = useStores();
const { permissionStore, menuStore, productListStore } = useStores();
const userInfo = useMyRequest(current);
const menuInfo = useMyRequest(menu);
......@@ -42,16 +43,42 @@ const useMyRouter = () => {
}
});
}
for (let item of menuInfo.res.data) {
let childrenRoutes: any = []
for (let route of item.routes) {
route.element = elements[route.element] || NotFound;
route.path = `/product/${item.id}${route.path}`;
if (Array.isArray(route.children)) {
route.children.forEach((childrenItem: any, index: number) => {
if (childrenItem.path) {
childrenRoutes.push({
...childrenItem,
element: elements[childrenItem.element] || NotFound,
path: `${route.path}${childrenItem.path}`,
show: false
})
}
})
route.children = route.children.filter((childrenItem: any) => !childrenItem.path)
}
}
permissionStore.setAddRoutes(item.routes);
// permissionStore.setAddRoutes(item.routes);
permissionStore.setAddRoutes([...childrenRoutes, ...item.routes]);
}
menuStore.initMenu(menuInfo.res.data);
permissionStore.initAllRoutes();
// /** 所有产品列表 */
const newProductList:IProductOption[] = [];
for (let item of menuInfo.res.data) {
if (item.type === "product") {
newProductList.push({
label: item.name,
value: item.id,
});
}
}
productListStore.setProductList(newProductList)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
......
.is_require::after {
display: inline-block;
content: "*";
color: #ff4e4e;
margin-right: 4px;
}
.dynamicFormItem_label {
display: block;
font-size: 14px;
font-weight: 600;
color: #1e2633;
}
.dynamicFormItem_col {
position: relative;
margin-bottom: 20px;
}
.dynamicFormItem_col_helpText {
margin-bottom: 46px;
}
.dynamicFormItem_content {
font-size: 14px;
color: #736f7f;
}
.dynamicFormitem_child {
position: relative;
flex: 1;
width: 100%;
text-align: left;
}
.dynamicFormitem_helpText {
position: absolute;
bottom: -36px;
font-size: 13px;
line-height: 1.15;
color: #9894a5;
}
.dynamicFormitem_helpText_warning {
color: #ff4e4e;
}
.dynamicFormitem_errorTips {
position: absolute;
bottom: -20px;
font-size: 13px;
color: #ff4e4e;
}
import React from "react";
import classNames from "classnames";
import styles from "./index.module.css";
import "./label.css";
// import { Control, ValidationRules } from 'react-hook-form/dist/types/form';
export interface IHelpText {
value: string /** 帮助文字内容 */;
className?: string;
type?: "normal" | "warning" /** 默认normal */;
}
export interface IFormItemBoxProps {
/** label 标签的文本 */
label?: string;
/** 标签宽度 */
labelWidth?: number;
/** 标签文本对齐方式 */
labelAlign?: "left" | "center" | "right";
/** 标签文本的className */
labelClassName?: string;
/** 是否必填 */
require?: boolean;
/** */
children: React.ReactNode;
className?: string;
/** 最外层class */
mainClass?: string;
/** 校验信息 */
errorMessage?: string;
errorClassName?: string;
itemFlex?: "row" | "column";
/** 帮助文字提示信息 */
helpText?: IHelpText;
}
const FormItemBox: React.FunctionComponent<IFormItemBoxProps> = (
props: IFormItemBoxProps
) => {
const {
className,
label,
children,
require,
labelWidth,
labelAlign,
errorMessage,
itemFlex,
mainClass,
helpText,
labelClassName,
errorClassName,
} = props;
return (
<div
className={classNames(
styles.dynamicFormItem_div,
mainClass,
helpText && helpText.value && styles.dynamicFormItem_col_helpText
)}
>
<div
className={classNames(
styles.dynamicFormItem_content,
`dynamicFormItem-${itemFlex}`,
className
)}
>
<span
style={{ width: `${labelWidth}px` }}
className={classNames(
styles.dynamicFormItem_label,
{ [styles.is_require]: require },
`align-${itemFlex === "row" ? labelAlign : "left"}`,
labelClassName
)}
>
{label}
</span>
<div className={styles.dynamicFormitem_child}>
{children}
{errorMessage && (
<div
className={classNames(
styles.dynamicFormitem_errorTips,
errorClassName
)}
>
{errorMessage}
</div>
)}
<div
className={classNames(
styles.dynamicFormitem_helpText,
helpText &&
helpText.type === "warning" &&
styles.dynamicFormitem_helpText_warning,
helpText && helpText.className
)}
>
{helpText?.value}
</div>
</div>
</div>
</div>
);
};
FormItemBox.defaultProps = {
labelWidth: 100,
labelAlign: "right",
itemFlex: "row",
};
export default FormItemBox;
.dynamicFormItem-row {
display: flex;
align-items: center;
}
.dynamicFormItem-column {
display: flex;
flex-direction: column;
align-items: flex-start;
}
......@@ -121,6 +121,13 @@ const MyInput = (props: MyInputProps) => {
},
},
},
MuiFormHelperText: {
styleOverrides: {
root: {
marginLeft: "0px",
},
},
},
},
});
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2021-12-04 15:46:25
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-21 18:00:58
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 18:41:04
* @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
*/
......@@ -13,6 +13,7 @@ import FormHelperText from "@mui/material/FormHelperText";
import Select, { SelectChangeEvent, SelectProps } from "@mui/material/Select";
import { createTheme, ThemeProvider } from "@mui/material";
import selectActive from "@/assets/project/selectActive.svg";
import { useState } from "react";
export interface IOption {
label: string;
......@@ -192,7 +193,10 @@ export default function MySelect(props: IProps) {
},
});
const [insideValue, setInsideValue] = useState<string>("");
const handleChange = (e: SelectChangeEvent<unknown>) => {
setInsideValue(e.target.value as string);
onChange && onChange(e.target.value as string);
};
......@@ -200,7 +204,10 @@ export default function MySelect(props: IProps) {
<ThemeProvider theme={theme}>
<FormControl fullWidth={fullWidth} variant={variant} error={error}>
{isTitle ? (
<InputLabel id="demo-simple-select-label">
<InputLabel
id="demo-simple-select-label"
sx={{ color: "rgba(194, 198, 204, 1)" }}
>
{title || "请选择"}
</InputLabel>
) : null}
......@@ -211,7 +218,7 @@ export default function MySelect(props: IProps) {
size="small"
multiple={multiple}
{...other}
value={value || ""}
value={value || insideValue || ""}
onChange={handleChange}
>
{options.length
......
......@@ -40,7 +40,7 @@ interface IMyTableProps {
totalElements?: number; // 数据总量 不止是列表渲染的长度
sortState?: sortState; // 排序状态
setSortState?: any; // 设置排序状态
paginationType?: "simple" | "complex"; // 分页组件的类型 simple简式 complex复杂、带每页数量切换、总数等
paginationType?: "simple" | "complex"; // 分页组件的类型 simple简式 complex复杂、带每页数量切换、总数等
rowsPerPage?: number; // 每页多少条数据
handleChangeRowsPerPage?: any; // 每页多少条数据变化
nodataText?: any; // 无数据文案
......
.titleBox {
font-size: 18px;
padding-left: 24px;
line-height: 26px;
font-weight: 600;
color: #1e2633;
line-height: 48px;
}
.titleBox::after {
content: "|";
padding: 0 24px;
color: #dde1e6;
}
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 19:34:35
* @LastEditTime: 2022-10-17 16:16:42
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -14,6 +14,9 @@ import Tab from "@mui/material/Tab";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Typography } from "@mui/material";
import classNames from "classnames";
import styles from "./index.module.css";
interface ITabList {
label: string;
......@@ -27,12 +30,22 @@ interface ITabList {
}
interface IProps {
/** 标题 */
title?: string;
/** title样式class */
titleClass?: any;
/** 选中值 */
value?: string;
/** 值 */
onChange?: (val: string) => void;
/** tab页面数组 */
tabList: ITabList[];
/** 默认选中tab */
defaultValue?: string;
/** 面板样式 */
tabPanelSx?: any;
allowNullValue?: boolean; // 是否允许空值
/** 是否允许空值 */
allowNullValue?: boolean;
}
const theme = createTheme({
......@@ -78,6 +91,8 @@ const Tabs = (props: IProps) => {
onChange,
allowNullValue = false,
tabPanelSx = { padding: "24px 0 0 0" },
title,
titleClass,
} = props;
const [tabValue, setTabValue] = useState(
......@@ -148,6 +163,16 @@ const Tabs = (props: IProps) => {
onTabChange(val);
}}
>
{title ? (
<span
className={classNames({
[styles.titleBox]: true,
[titleClass]: titleClass,
})}
>
{title}
</span>
) : null}
{tabList
?.filter((item) => !item.hide)
.map((item, key) => {
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-24 14:32:32
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-18 10:54:54
* @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";
......@@ -13,12 +13,14 @@ import MenuLayout from "@/views/MenuLayout";
import * as React from "react";
import NotFound from "@/views/404";
import Demo from "@/views/demo";
import SeeEnv from "@/views/ResourceCenter/UserResources/UserResourcesEnvironment/SeeEnv";
import ProjectSetting from "@/views/Project/ProjectSetting";
import ProjectData from "@/views/Project/ProjectData";
import ProjectWorkbench from "@/views/Project/ProjectWorkbench";
import ProjectSubmitWork from "@/views/Project/ProjectSubmitWork";
import ProjectJobDetail from "@/views/Project/ProjectJobDetail";
import ProjectOverview from "@/views/Project/ProjectOverview";
import UserResources from "@/views/ResourceCenter/UserResources";
export type route = {
id?: string;
......@@ -51,6 +53,9 @@ export const elements: {
}) => JSX.Element | any;
} = {
Demo: Demo,
SeeTemplate: Demo,
UserResources: UserResources,
SeeEnv: SeeEnv,
ProjectSetting: ProjectSetting,
ProjectData: ProjectData,
ProjectWorkbench: ProjectWorkbench,
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-09 20:41:05
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 20:55:22
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 16:21:50
* @FilePath: /bkunyun/src/store/index.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -12,10 +12,11 @@ import permissionStore from "./modules/permission";
import menuStore from "./modules/menu";
import currentProjectStore from "./modules/currentProject";
import fileListStore from "./modules/fileList";
import productListStore from './modules/productList'
configure({ enforceActions: "always" });
export const stores = { permissionStore, menuStore, currentProjectStore, fileListStore };
export const stores = { permissionStore, menuStore, currentProjectStore, fileListStore, productListStore };
/** Store类型 */
export type Stores = typeof stores;
......
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-07-11 11:49:55
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 16:25:27
* @FilePath: /bkunyun/src/store/modules/currentProject.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { makeAutoObservable } from "mobx";
export interface IProductOption{
label: string;
value: string;
}
class newProductList {
constructor() {
makeAutoObservable(this);
}
// 产品列表
productList: IProductOption[] = [];
setProductList = (list: IProductOption[]) => {
this.productList = list;
};
}
const productListStore = new newProductList();
export default productListStore;
......@@ -90,7 +90,7 @@ export const storageUnitFromB = (b: number) => {
} else if (b < 1024 * 1024 * 1024 * 1024) {
return `${(b / (1024 * 1024 * 1024)).toFixed(2)}G`;
} else {
return `${(b / (1024 * 1024 * 1024 * 1024)).toFixed(2)}t`;
return `${(b / (1024 * 1024 * 1024 * 1024)).toFixed(2)}T`;
}
};
......
......@@ -164,10 +164,10 @@ const OperatorList = observer((props: IProps) => {
const dom = document.getElementById("customOperatorFlow");
const clientX = e.clientX;
const clientY = e.clientY;
const upperLeftPointX = Number(dom?.offsetLeft);
const upperLeftPointY = Number(dom?.offsetTop);
const lowerRightX = Number(upperLeftPointX) + Number(dom?.offsetWidth);
const lowerRightY = Number(upperLeftPointY) + Number(dom?.offsetHeight);
const upperLeftPointX = Number(dom?.getBoundingClientRect()?.left);
const upperLeftPointY = Number(dom?.getBoundingClientRect()?.top);
const lowerRightX = Number(upperLeftPointX) + Number(dom?.clientWidth);
const lowerRightY = Number(upperLeftPointY) + Number(dom?.clientHeight);
if (
clientX > upperLeftPointX &&
clientY > upperLeftPointY &&
......@@ -178,7 +178,7 @@ const OperatorList = observer((props: IProps) => {
const newOperatorItem = getNewOperatorItem(
newDragItem,
clientX - upperLeftPointX,
clientY - upperLeftPointY - 42
clientY - upperLeftPointY
);
const newVal = cloneDeep(operatorList);
newVal.push(newOperatorItem);
......
......@@ -46,3 +46,11 @@
background-color: #e6eaf0;
font-weight: 500;
}
.asideTop {
padding: 19px 24px 13px;
line-height: 24px;
font-size: 16px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
}
......@@ -8,7 +8,7 @@
*/
import { Box, List } from "@mui/material";
import CurrentProject from "../Project/components/CurrentProject";
import React from "react";
import React, { useMemo } from "react";
import { Outlet, useNavigate, useLocation } from "react-router-dom";
import style from "./index.module.css";
import { observer } from "mobx-react-lite";
......@@ -44,10 +44,34 @@ const MenuLayout = observer(() => {
}
};
// // 左侧菜单顶部是否显示当前项目组件
// const showCurrentProject = useMemo(() => {
// const noCurrentProjectRouterApp = ["userCenter", "resourceCenter"];
// return noCurrentProjectRouterApp.every((item) => {
// return pathname.indexOf(item) === -1;
// });
// }, [pathname]);
const renderAsideTop = useMemo(() => {
const noCurrentProjectRouterApp = ["userCenter", "resourceCenter"];
if (
noCurrentProjectRouterApp.every((item) => {
return pathname.indexOf(item) === -1;
})
) {
return <CurrentProject />;
}
if (pathname.indexOf("resourceCenter") !== -1) {
return <div className={style.asideTop}>资源中心</div>;
}
return null;
}, [pathname]);
return (
<Box className={style.container}>
<Box className={style.aside}>
{pathname.indexOf("userCenter") < 0 && <CurrentProject />}
{renderAsideTop}
{/* {showCurrentProject && <CurrentProject />} */}
<List
sx={{
paddingTop: 0,
......@@ -61,7 +85,8 @@ const MenuLayout = observer(() => {
key={"sidebar" + index}
className={classnames({
[style.listItem]: true,
[style.active]: `/v3${item.path}` === pathname,
[style.active]: pathname.indexOf(`/v3${item.path}`) !== -1,
// [style.active]: `/v3${item.path}` === pathname,
})}
style={
`/v3${item.path}` === pathname
......
......@@ -28,6 +28,7 @@ type IMoveFileProps = {
const UpLoaderFile = observer((props: IMoveFileProps) => {
const { path, list, uploaderDialogOpen, setUploaderDialogOpen } = props;
console.log(path);
const { fileListStore } = useStores();
const message = useMessage();
......@@ -41,6 +42,7 @@ const UpLoaderFile = observer((props: IMoveFileProps) => {
const currentProjectStore = toJS(useGlobalStore("currentProjectStore"));
const uploadInfoStore = toJS(useGlobalStore("fileListStore"));
console.log(uploadInfoStore);
const { uploadFile } = UseTusUpload(uploadInfoStore);
const onDrop = useCallback(
......
......@@ -8,168 +8,184 @@ import CloudEController from "@/api/fileserver/CloudEController";
import { useStores } from "@/store";
import { toJS } from "mobx";
import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer";
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import useWindowSize from '@/hooks/useWindowSize'
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import useWindowSize from "@/hooks/useWindowSize";
type LogViewProps = {
logs: any[];
setShowLogView: any;
logs: any[];
setShowLogView: any;
};
const LogView = (props: LogViewProps) => {
const { logs, setShowLogView } = props;
const { currentProjectStore } = useStores();
const { width, height } = useWindowSize();
const fileToken = toJS(currentProjectStore.currentProjectInfo.filetoken);
const projectId = toJS(currentProjectStore.currentProjectInfo.id);
// 当前选择的日志
const [logCurrent, setLogCurrent] = useState<number>(0);
// 当前日志的内容文本
const [logText, setLogText] = useState('')
// 当前日志路径
const [logPath, setLogPath] = useState('')
const [displacement, setDisplacement] = useState(0)
const [middleDynamicWidth, setMiddleDynamicWidth] = useState(0)
const [leftButtonColor, setLeftButtonColor] = useState('#585D62')
const [rightButtonColor, setRightButtonColor] = useState('#585D62')
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath)
}, [logs]);
// 请求日志文本
useEffect(() => {
if (logPath) {
const path = logPath.slice(12)
CloudEController.JobFileDownloadText(
path,
fileToken as string,
projectId as string
)?.then((res) => {
setLogText(res.data)
})
} else {
setLogText("")
}
}, [logPath]);
// 选择日志时改变日志路径
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath)
}, [logCurrent]);
//获取盒子的总宽度,用于滑动效果判断
useEffect(() => {
const box = document.getElementById('middleDynamic')
setMiddleDynamicWidth(box ? box.offsetWidth : 0)
}, [])
useEffect(() => {
if (middleDynamicWidth < width - 97) {
setLeftButtonColor('#585D62')
setRightButtonColor('#585D62')
}
if (displacement === 0) {
setLeftButtonColor('#585D62')
} else {
setLeftButtonColor('#C0C5CD')
}
if (middleDynamicWidth > width - 97 && displacement !== -middleDynamicWidth + width - 97) {
setRightButtonColor('#C0C5CD')
} else {
setRightButtonColor('#585D62')
}
}, [width, middleDynamicWidth, displacement])
// 下载当前日志
const handleDownLoad = () => {
const path = logPath.slice(12)
CloudEController.JobFileDownload(
path,
fileToken as string,
projectId as string
);
}
const rightClick = () => {
if (middleDynamicWidth < width - 97) {
return
}
if (-displacement > middleDynamicWidth - width * 1.8 + 97) {
setDisplacement(-middleDynamicWidth + width - 97)
return
}
const newDisplacement = displacement - width * 0.8;
setDisplacement(newDisplacement)
}
const leftClick = () => {
if (-displacement < width * 0.8) {
setDisplacement(0)
return
}
const newDisplacement = displacement + width * 0.8;
setDisplacement(newDisplacement)
}
return (
<FullScreenDrawer handleClose={setShowLogView} zIndex={1002}>
<div className={style.logViewBox}>
<div className={style.logViewContentMask}></div>
<div className={style.logViewTop}>
<div
className={style.leftButton}
onClick={leftClick}
style={{ color: leftButtonColor, cursor: leftButtonColor === '#585D62' ? 'default' : 'pointer' }}
>
<ChevronLeftIcon />
</div>
<div className={style.middleFixed}>
<div className={style.middleDynamic} id='middleDynamic' style={{ left: `${displacement}px` }}>
{logs.map((item: any, index: number) => {
return <MyTooltip
title={item.logName}
placement="bottom"
arrow={false}
enterDelay={1000}
>
<div
key={index}
onClick={() => { setLogCurrent(index) }}
className={classnames({
[style.logTitle]: true,
[style.logTitleSelected]: index === logCurrent,
})}>
<InsertDriveFileOutlinedIcon className={style.fileIcon} />
<span className={style.logName}>{item.logName}</span>
</div>
</MyTooltip>
})}
</div>
</div>
<div className={style.gradientBox}></div>
<div
className={style.rightButton}
onClick={rightClick}
style={{ color: rightButtonColor, cursor: rightButtonColor === '#585D62' ? 'default' : 'pointer' }}
>
<ChevronRightIcon />
</div>
</div>
<div className={style.logViewContent}>
{logText}
</div>
<div className={style.logViewBottom}>
<MyButton text='下载当前日志' onClick={handleDownLoad} />
</div>
</div>
</FullScreenDrawer>
)
}
const { logs, setShowLogView } = props;
console.log(logs);
const { currentProjectStore } = useStores();
const { width, height } = useWindowSize();
const fileToken = toJS(currentProjectStore.currentProjectInfo.filetoken);
const projectId = toJS(currentProjectStore.currentProjectInfo.id);
// 当前选择的日志
const [logCurrent, setLogCurrent] = useState<number>(0);
// 当前日志的内容文本
const [logText, setLogText] = useState("");
// 当前日志路径
const [logPath, setLogPath] = useState("");
const [displacement, setDisplacement] = useState(0);
const [middleDynamicWidth, setMiddleDynamicWidth] = useState(0);
const [leftButtonColor, setLeftButtonColor] = useState("#585D62");
const [rightButtonColor, setRightButtonColor] = useState("#585D62");
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logs]);
// 请求日志文本
useEffect(() => {
if (logPath) {
const path = logPath.slice(12);
CloudEController.JobFileDownloadText(
path,
fileToken as string,
projectId as string
)?.then((res) => {
setLogText(res.data);
});
} else {
setLogText("");
}
}, [logPath]);
// 选择日志时改变日志路径
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logCurrent]);
//获取盒子的总宽度,用于滑动效果判断
useEffect(() => {
const box = document.getElementById("middleDynamic");
setMiddleDynamicWidth(box ? box.offsetWidth : 0);
}, []);
useEffect(() => {
if (middleDynamicWidth < width - 97) {
setLeftButtonColor("#585D62");
setRightButtonColor("#585D62");
}
if (displacement === 0) {
setLeftButtonColor("#585D62");
} else {
setLeftButtonColor("#C0C5CD");
}
if (
middleDynamicWidth > width - 97 &&
displacement !== -middleDynamicWidth + width - 97
) {
setRightButtonColor("#C0C5CD");
} else {
setRightButtonColor("#585D62");
}
}, [width, middleDynamicWidth, displacement]);
// 下载当前日志
const handleDownLoad = () => {
const path = logPath.slice(12);
CloudEController.JobFileDownload(
path,
fileToken as string,
projectId as string
);
};
const rightClick = () => {
if (middleDynamicWidth < width - 97) {
return;
}
if (-displacement > middleDynamicWidth - width * 1.8 + 97) {
setDisplacement(-middleDynamicWidth + width - 97);
return;
}
const newDisplacement = displacement - width * 0.8;
setDisplacement(newDisplacement);
};
const leftClick = () => {
if (-displacement < width * 0.8) {
setDisplacement(0);
return;
}
const newDisplacement = displacement + width * 0.8;
setDisplacement(newDisplacement);
};
return (
<FullScreenDrawer handleClose={setShowLogView} zIndex={1002}>
<div className={style.logViewBox}>
<div className={style.logViewContentMask}></div>
<div className={style.logViewTop}>
<div
className={style.leftButton}
onClick={leftClick}
style={{
color: leftButtonColor,
cursor: leftButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronLeftIcon />
</div>
<div className={style.middleFixed}>
<div
className={style.middleDynamic}
id="middleDynamic"
style={{ left: `${displacement}px` }}
>
{logs.map((item: any, index: number) => {
return (
<MyTooltip
title={item.logName}
placement="bottom"
arrow={false}
enterDelay={1000}
>
<div
key={index}
onClick={() => {
setLogCurrent(index);
}}
className={classnames({
[style.logTitle]: true,
[style.logTitleSelected]: index === logCurrent,
})}
>
<InsertDriveFileOutlinedIcon className={style.fileIcon} />
<span className={style.logName}>{item.logName}</span>
</div>
</MyTooltip>
);
})}
</div>
</div>
<div className={style.gradientBox}></div>
<div
className={style.rightButton}
onClick={rightClick}
style={{
color: rightButtonColor,
cursor: rightButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronRightIcon />
</div>
</div>
<div className={style.logViewContent}>{logText}</div>
<div className={style.logViewBottom}>
<MyButton text="下载当前日志" onClick={handleDownLoad} />
</div>
</div>
</FullScreenDrawer>
);
};
export default LogView
\ No newline at end of file
export default LogView;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-13 16:51:56
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-17 15:36:29
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -15,7 +15,7 @@ import NoProject from "@/components/BusinessComponents/NoProject";
import { observer } from "mobx-react-lite";
import ProjectMembers from "./ProjectMembers";
import BaseInfo from "./BaseInfo";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import usePass from "@/hooks/usePass";
const ProjectSetting = observer(() => {
......
......@@ -2,7 +2,7 @@
* @Author: rocosen
* @Date: 2022-06-12 10:05:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 11:51:16
* @LastEditTime: 2022-10-17 15:36:38
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -14,7 +14,7 @@ import { useStores } from "@/store/index";
import WorkbenchTemplate from "./workbenchTemplate";
import WorkbenchList from "./workbenchList";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import usePass from "@/hooks/usePass";
import NoProject from "@/components/BusinessComponents/NoProject";
import Template from "@/assets/project/workbenchTemplate.svg";
......
.addEnvironment {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #fff;
display: flex;
}
.left {
/* width: 412px; */
box-sizing: border-box;
background-color: rgba(247, 248, 250, 1);
}
.right {
flex: 1;
padding: 64px 44px 40px;
min-height: 100vh;
overflow: overlay;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.title {
color: rgba(30, 38, 51, 1);
margin-bottom: 40px;
font-size: 24px;
line-height: 32px;
font-weight: 550;
}
.content {
display: flex;
border-radius: 4px;
margin-bottom: 24px;
height: 580px;
}
.form {
width: 368px;
box-sizing: border-box;
padding: 16px 24px;
border: 1px solid #ebedf0;
border-right: none;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.codeBox {
flex: 1;
display: flex;
flex-direction: column;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.codeTitle {
background-color: rgba(230, 233, 237, 1);
padding: 11px 20px;
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
font-weight: 550;
border-top-right-radius: 4px;
}
.code {
background-color: rgba(247, 248, 250, 1);
flex: 1;
}
.label {
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
font-weight: 550;
margin-bottom: 8px;
position: relative;
}
.zipText {
color: rgba(138, 144, 153, 1);
font-weight: 400;
}
.required {
color: rgba(255, 78, 78, 1);
}
.download {
position: absolute;
right: 0;
cursor: pointer;
color: rgba(19, 112, 255, 1);
font-weight: 400;
}
.formItem {
position: relative;
margin-bottom: 24px;
}
.tips {
color: rgba(255, 78, 78, 1);
margin-top: 2px;
line-height: 20px;
font-size: 12px;
}
.uploadBox {
border-radius: 4px;
border: 1px dashed #dde1e6;
height: 153px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 14px;
line-height: 22px;
color: rgba(194, 198, 204, 1);
}
.uploaderIcon {
margin-bottom: 8px;
}
.progressContent {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 7px;
}
.progressBox {
width: 200px;
border-radius: 3px;
background-color: rgba(235, 237, 240, 1);
margin-right: 12px;
height: 6px;
}
.progress {
border-radius: 3px;
background-color: rgba(19, 110, 250, 1);
height: 6px;
}
.isDragActive {
border: 1px dashed #000;
}
.formItemHaveHelperText {
margin-bottom: 10px;
}
.uploadAgain {
cursor: pointer;
color: rgba(19, 110, 250, 1);
font-size: 12px;
line-height: 20px;
margin-top: 12px;
}
import { useEffect, useState, useCallback } from "react";
import MyInput from "@/components/mui/MyInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import style from "./index.module.css";
import useMyRequest from "@/hooks/useMyRequest";
import { urlToken } from "@/api/fileserver/raysyncApi";
import * as tus from "tus-js-client";
import { useDropzone } from "react-dropzone";
import SwitchBatchFolw from "@/views/ResourceCenter/components/SwitchBatchFolw";
import { getLoaclStorageOfKey } from "@/api/fileserver/utils";
import Code from "@/components/CommonComponents/Code";
import { useMessage } from "@/components/MySnackbar";
import * as Base64 from "js-base64";
import CloseIcon from "@mui/icons-material/Close";
import { getDataFileToken, hpczone } from "@/api/project_api";
import { checkIsNumberLetterChinese } from "@/utils/util";
import uploaderIcon from "@/assets/project/uploaderIcon.svg";
import zip from "@/assets/resourceCenter/zip.svg";
import {
getPublicEnv,
getPublicProject,
addActorenvBuildenv,
} from "@/api/resourceCenter";
import classNames from "classnames";
import { getTokenInfo } from "@/utils/util";
type IAddEnvironmentProps = {
setAddopen: any;
};
const AddEnvironment = (props: IAddEnvironmentProps) => {
const { setAddopen } = props;
const Message = useMessage();
let tokenInfo = getTokenInfo();
const [hpczoneList, setHpczoneList] = useState<Array<any>>([]);
const [publicProjectId, setPublicProjectId] = useState("");
const [publicZoneId, setPublicZoneId] = useState("");
const [computeType, setComputeType] = useState("");
const [fileToken, setFileToken] = useState("");
const [taskType, setTaskType] = useState<"BATCH" | "FLOW">("BATCH");
const [name, setName] = useState("");
const [desc, setDesc] = useState("");
const [baseEnvId, setBaseEnvId] = useState("");
const [filePaths, setFilePaths] = useState<Array<string>>([]);
const [isUploading, setIsUploading] = useState(false);
const [fileName, setFileName] = useState("");
// const [bashScript, setBashScript] = useState('');
const [envList, setEnvList] = useState<Array<any>>([]);
const [progress, setProgress] = useState("0%");
const [code, setCode] = useState("");
const [upload, setUpload] = useState<any>(() => {});
const [nameHelper, setNameHelper] = useState({
error: false,
text: "30字符以内,仅限字母、数字、中文",
});
const [descHelper, setDescHelper] = useState({
error: false,
text: "",
});
const [filePathsHelper, setFilePathsHelper] = useState({
error: false,
text: "",
});
const onDrop = useCallback(
(acceptedFiles: any) => {
let origin = "";
hpczoneList.forEach((item) => {
if (item.id === publicZoneId) {
origin = item?.storageConfig?.fileServerEndPoint;
}
});
const fileInfo = acceptedFiles[0];
const { path } = fileInfo;
if (path.indexOf(".zip") === -1) {
Message.error("请上传压缩文件");
return;
}
const userInfo = getLoaclStorageOfKey("userInfo");
const homeDirectoryMountPoint = userInfo?.homeDirectoryMountPoint;
const url =
origin + "/parallelupload/" + urlToken(fileToken, publicProjectId);
let headers = {
username: publicProjectId,
token: tokenInfo?.access_token || "",
filetoken: fileToken,
share: false,
project: true,
};
let upload = new tus.Upload(fileInfo, {
endpoint: url,
parallelUploads: 1,
chunkSize: 5 * 1024 * 1024,
metadata: {
filepath: "/" + homeDirectoryMountPoint + "/" + path,
},
retryDelays: [0, 3000, 5000, 10000, 20000],
headers: headers,
onbeforeunload: () => {
setProgress(`0%`);
},
onError: function (error: string) {
setIsUploading(false);
console.log("Failed because: " + error);
},
onProgress: function (bytesUploaded: number, bytesTotal: number) {
setProgress(`${(bytesUploaded * 100) / bytesTotal}%`);
},
onSuccess: function () {
setIsUploading(false);
setFilePaths([`/ProjectData/${homeDirectoryMountPoint}/${path}`]);
setFileName(path);
},
});
setIsUploading(true);
upload.start();
setUpload(upload);
},
[
fileToken,
publicProjectId,
tokenInfo?.access_token,
hpczoneList,
publicZoneId,
Message,
]
);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
const { run: getPublicEnvFn } = useMyRequest(getPublicEnv, {
onSuccess: (res: any) => {
let arr = res.data.map((item: any) => {
return {
label: item.title,
value: item.id,
computeType: item.computeType,
};
});
setEnvList(arr);
if (arr.length >= 1) {
setBaseEnvId(arr[0].value);
setComputeType(arr[0].computeType);
}
},
});
const { run: getPublicProjectFn } = useMyRequest(getPublicProject, {
onSuccess: (res: any) => {
setPublicProjectId(res.data[0].id);
setPublicZoneId(res.data[0].zoneId);
getDataFileTokenFn({ id: res.data[0].id });
},
});
const { run: getDataFileTokenFn } = useMyRequest(getDataFileToken, {
onSuccess: (res: any) => {
setFileToken(res.data);
},
});
const { run: addActorenvBuildenvFn, loading } = useMyRequest(
addActorenvBuildenv,
{
onSuccess: () => {
Message.success("开始构建应用环境");
setAddopen(false);
},
}
);
useEffect(() => {
getPublicProjectFn();
}, [getPublicProjectFn]);
useEffect(() => {
getPublicEnvFn({ taskType });
}, [getPublicEnvFn, taskType]);
const { run: hpczoneFn } = useMyRequest(hpczone, {
onSuccess: (res: any) => {
setHpczoneList(res.data);
},
});
useEffect(() => {
hpczoneFn();
}, [hpczoneFn]);
const handleNameChange = (e: any) => {
setName(e.target.value);
checkName(e.target.value);
};
const handleDescChange = (e: any) => {
setDesc(e.target.value);
checkDesc(e.target.value);
};
const handelBaseEnvIdChange = (e: any) => {
setBaseEnvId(e);
let index = envList.findIndex((item) => {
return item.value === e;
});
setComputeType(envList[index].computeType);
};
const checkName = (name: string) => {
if (!name) {
setNameHelper({
error: true,
text: "环境名称不能为空",
});
return true;
} else if (name.length > 30) {
setNameHelper({
error: true,
text: "格式不正确,30字符以内,仅限字母、数字、中文",
});
return true;
} else if (!checkIsNumberLetterChinese(name)) {
setNameHelper({
error: true,
text: "格式不正确,30字符以内,仅限字母、数字、中文",
});
return true;
} else {
setNameHelper({
error: false,
text: "30字符以内,仅限字母、数字、中文",
});
return false;
}
};
const checkDesc = (desc: string) => {
if (!desc) {
setDescHelper({
error: true,
text: "环境描述不能为空",
});
return true;
} else if (desc.length > 300) {
setDescHelper({
error: true,
text: "描述限300字",
});
return true;
} else {
setDescHelper({
error: false,
text: "",
});
return false;
}
};
const checkFile = (filePaths: any) => {
if (filePaths.length === 0) {
setFilePathsHelper({
error: true,
text: "请上传环境压缩包",
});
return true;
} else {
setFilePathsHelper({
error: false,
text: "",
});
return false;
}
};
const handleSubmit = () => {
if (
!checkName(name) &&
!checkDesc(desc) &&
!checkFile(filePaths) &&
baseEnvId &&
code
) {
addActorenvBuildenvFn({
title: name,
desc,
baseEnvId,
type: taskType,
filePaths,
bashScript: Base64.encode(code),
publicProjectId,
computeType,
});
} else {
Message.error("请完善环境信息");
}
};
const handleAbort = () => {
upload.abort(true);
setIsUploading(false);
setFilePaths([]);
};
return (
<div className={style.addEnvironment}>
<div className={style.left}>
<SwitchBatchFolw
active={taskType}
setActive={setTaskType}
goBack={() => setAddopen(false)}
></SwitchBatchFolw>
</div>
<div className={style.right}>
<div className={style.title}>
{taskType === "BATCH" ? "批式环境信息" : "流式环境信息"}
</div>
<div className={style.content}>
<div className={style.form}>
<div className={style.label}>
环境名称<span className={style.required}>*</span>
</div>
<div
className={classNames({
[style.formItem]: true,
[style.formItemHaveHelperText]: nameHelper.text,
})}
>
<MyInput
value={name}
onChange={handleNameChange}
error={nameHelper.error}
helperText={nameHelper.text}
placeholder="给环境起个名称"
></MyInput>
</div>
<div className={style.label}>
描述<span className={style.required}>*</span>
</div>
<div className={style.formItem}>
<MyInput
value={desc}
id="desc"
multiline
rows={4}
placeholder="请输入项目描述"
onChange={handleDescChange}
error={descHelper.error}
helperText={descHelper.text}
/>
<span
style={{
position: "absolute",
fontSize: "14px",
bottom: "7px",
right: "12px",
color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC",
}}
>
{desc.length}/300
</span>
</div>
<div className={style.label}>
基础环境<span className={style.required}>*</span>
</div>
<div className={style.formItem}>
<MySelect
options={envList}
fullWidth
value={baseEnvId}
onChange={(e) => handelBaseEnvIdChange(e)}
></MySelect>
</div>
<div className={style.label}>
上传环境压缩包<span className={style.zipText}>(.zip)</span>
<span className={style.required}>*</span>
<span className={style.download}>下载模板</span>
</div>
<div className={style.formItem}>
{filePaths.length === 0 && !isUploading && (
<div
className={classNames({
[style.uploadBox]: true,
[style.isDragActive]: isDragActive,
})}
{...getRootProps()}
>
<input {...getInputProps()} />
<img
className={style.uploaderIcon}
src={uploaderIcon}
alt=""
/>
<span>点击选择环境包或将文件</span>
<span>拖到此处上传</span>
</div>
)}
{isUploading && (
<div
className={classNames({
[style.uploadBox]: true,
})}
>
<div className={style.progressContent}>
<div className={style.progressBox}>
<div
className={style.progress}
style={{ width: progress }}
></div>
</div>
<CloseIcon
onClick={() => handleAbort()}
sx={{
fontSize: "16px",
color: "#C2C6CC",
cursor: "pointer",
":hover": {
background: "#f0f2f5",
borderRadius: "2px",
},
}}
/>
</div>
<span>上传中,请稍等...</span>
</div>
)}
{filePaths.length !== 0 && !isUploading && (
<div
className={classNames({
[style.uploadBox]: true,
})}
>
<img className={style.uploaderIcon} src={zip} alt="" />
<span>{fileName}</span>
<span
onClick={() => setFilePaths([])}
className={style.uploadAgain}
>
重新上传
</span>
</div>
)}
{filePathsHelper.text && (
<div className={style.tips}>{filePathsHelper.text}</div>
)}
</div>
</div>
<div className={style.codeBox}>
<div className={style.codeTitle}>
{taskType === "BATCH" ? "Shell脚本" : "Python脚本"}
</div>
<div className={style.code}>
<Code
value={code}
onChange={(e: string) => setCode(e)}
height="535px"
/>
</div>
</div>
</div>
<div className={style.button}>
<MyButton
text="开始构建"
onClick={() => handleSubmit()}
loading={loading}
></MyButton>
</div>
</div>
</div>
);
};
export default AddEnvironment;
import { deleteActorenv } from "@/api/resourceCenter";
import useMyRequest from "@/hooks/useMyRequest";
import { useMessage } from "@/components/MySnackbar";
import MyDialog from "@/components/mui/MyDialog";
interface IDeleteEnvironmentProps {
id: string;
open: boolean;
setDeleteOpen: any;
}
const DeleteEnvironment = (props: IDeleteEnvironmentProps) => {
const { open, id, setDeleteOpen } = props;
const Message = useMessage();
const { run, loading } = useMyRequest(deleteActorenv, {
onSuccess: () => {
setDeleteOpen(false);
Message.success("删除成功");
},
});
const handleConfirm = () => {
console.log(id);
run({ id });
};
return (
<MyDialog
okColor="error"
open={open}
onClose={() => setDeleteOpen(false)}
title="删除环境"
okText="删除"
onConfirm={() => handleConfirm()}
loading={loading}
>
<span>删除后无法恢复,确认删除吗?</span>
</MyDialog>
);
};
export default DeleteEnvironment;
.titleBox {
padding: 14px 24px;
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid rgba(235, 237, 240, 1);
}
.goBackIcon {
width: 22px;
height: 22px;
/* background-color: #fff; */
/* border-radius: 4px; */
/* margin-right: 12px; */
/* box-shadow: 0px 2px 5px 0px rgba(3, 47, 105, 0.09); */
cursor: pointer;
}
.title {
margin-left: 2px;
font-size: 18px;
line-height: 26px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
margin-right: 16px;
}
.type {
background-color: rgba(235, 237, 240, 1);
font-size: 12px;
line-height: 20px;
padding: 1px 9px;
color: #565c66;
border-radius: 2px;
}
.baseTitle {
padding: 19px 24px 16px;
line-height: 24px;
font-size: 16px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
}
.basicInfoBox {
border: 1px solid #ebedf0;
border-radius: 4px;
margin: 0 24px;
}
.logsTitle {
padding: 24px 24px 16px;
line-height: 24px;
font-size: 16px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
}
.statusBox {
display: flex;
justify-content: flex-start;
align-items: center;
}
.status {
margin-left: 4px;
}
.LogViewBox {
margin: 0 24px;
position: relative;
}
import style from "./index.module.css";
import React, { useState, useEffect, useMemo } from "react";
import LogView from "@/views/ResourceCenter/components/LogView";
import { useNavigate } from "react-router-dom";
import BasicInfo, {
IInfoItem,
} from "@/views/ResourceCenter/components/BasinInfo";
import { getActorenvDetail } from "@/api/resourceCenter";
import useMyRequest from "@/hooks/useMyRequest";
import goback from "@/assets/project/goback.svg";
import { useLocation } from "react-router-dom";
import jobFail from "@/assets/project/jobFail.svg";
import jobRun from "@/assets/project/jobRun.svg";
import jobSue from "@/assets/project/jobSue.svg";
const SeeEnv = () => {
const navigate = useNavigate();
const location = useLocation();
const [id, setId] = useState("");
const [info, setInfo] = useState<any>({});
const [infoListTop, setInfoListTop] = useState<Array<IInfoItem>>([]);
const [infoListBot, setInfoListBot] = useState<Array<IInfoItem>>([]);
const [logs, setLogs] = useState<Array<any>>([]);
const getStatus = (item: any) => {
if (item.status === "PENDING") {
return (
<span className={style.statusBox}>
<img src={jobRun} alt="" />
<span className={style.status}>准备构建</span>
</span>
);
} else if (item.status === "CREATING") {
return (
<span className={style.statusBox}>
<img src={jobRun} alt="" />
<span className={style.status}>正在构建</span>
</span>
);
} else if (item.status === "FAILED") {
return (
<span className={style.statusBox}>
<img src={jobFail} alt="" />
<span className={style.status}>构建失败</span>
</span>
);
} else if (item.status === "CREATED") {
return (
<span className={style.statusBox}>
<img src={jobSue} alt="" />
<span className={style.status}>构建完成</span>
</span>
);
} else {
return "";
}
};
const { run, loading } = useMyRequest(getActorenvDetail, {
onSuccess: (res) => {
console.log(res);
setInfo(res.data);
let data = res.data;
setInfoListTop([
{
label: "构建状态",
value: getStatus(data),
},
{
label: "创建时间",
value: data.createdTime,
},
{
label: "构建时长",
value: data.costTime,
},
{
label: "构建成本",
value: "¥" + data.feeCost,
},
{
label: "基础环境",
value: data.baseEnvName,
},
]);
setInfoListBot([
{
label: "描述",
value: data.desc,
},
]);
setLogs(
data.tasks
.filter((task: any) => task.outLog)
.map((task: any) => ({
logName: `${task.title}.log`,
logPath: task.outLog,
}))
);
},
});
useEffect(() => {
if (id) {
run({ id });
}
}, [id, run]);
useEffect(() => {
const locationInfo: any = location?.state;
console.log(locationInfo);
setId(locationInfo.id);
}, [location, setId]);
return (
<div className={style.seeEnv}>
<div className={style.titleBox}>
<img
className={style.goBackIcon}
src={goback}
alt=""
onClick={() => navigate("/product/resourceCenter/userResources")}
/>
<div className={style.title}>{info.title}</div>
<div className={style.type}>
{info.type === "BATCH" ? "批式环境" : "流式环境"}
</div>
</div>
<div className={style.infoBox}>
<div className={style.baseTitle}>基础信息</div>
<div className={style.basicInfoBox}>
<BasicInfo infoList={infoListTop} />
<BasicInfo infoList={infoListBot} />
</div>
</div>
<div className={style.logsBox}>
<div className={style.logsTitle}>日志</div>
<div className={style.LogViewBox}>
<LogView logs={logs}></LogView>
</div>
</div>
</div>
);
};
export default SeeEnv;
.environment {
padding: 19px 24px 0;
}
.top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.tableBox {
height: calc(100vh - 177px);
}
.statusBox {
display: flex;
justify-content: flex-start;
align-items: center;
}
.status {
margin-left: 4px;
}
// 应用环境
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import style from "./index.module.css";
import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import MyTable from "@/components/mui/MyTableNew";
import useMyRequest from "@/hooks/useMyRequest";
import { getActorenvList } from "@/api/resourceCenter";
import Add from "@mui/icons-material/Add";
import moment from "moment";
import jobFail from "@/assets/project/jobFail.svg";
import jobRun from "@/assets/project/jobRun.svg";
import jobSue from "@/assets/project/jobSue.svg";
import AddEnvironment from "./AddEnvironment";
import DeleteEnvironment from "./DeleteEnvironment";
const UserResourcesEnvironment = () => {
const navigate = useNavigate();
const [addOpen, setAddopen] = useState(false);
const [title, setTitle] = useState("");
const [type, setType] = useState<"BATCH" | "FLOW" | "">("");
const [list, setList] = useState([]);
const [page, setPage] = useState(0);
const [count, setCount] = useState(0);
const [size, setSize] = useState(20);
const [id, setId] = useState("");
const [deleteOpen, setDeleteOpen] = useState(false);
const [totalElements, setTotalElements] = useState(0);
const headCells: Array<any> = [
{
id: "title",
label: "环境名称",
},
{
id: "type",
label: "环境类型",
width: 100,
},
{
id: "createdTime",
label: "创建时间",
width: 180,
},
{
id: "status",
label: "构建状态",
width: 150,
},
{
id: "caozuo",
label: "操作",
width: 140,
},
];
const { run: getList } = useMyRequest(getActorenvList, {
onSuccess: (res) => {
setList(res.data.content);
setCount(res.data.totalPages - 1);
setTotalElements(res.data.totalElements);
},
});
const pageChange = (value: number) => {
setPage(value - 1);
};
useEffect(() => {
if (!addOpen && !deleteOpen) {
getList({
page,
size,
title,
type,
});
}
}, [getList, page, size, title, type, addOpen, deleteOpen]);
const renderType = (item: any) => {
if (item.type === "BATCH") {
return "批式";
} else if (item.type === "FLOW") {
return "流式";
} else {
return "";
}
};
const renderStatus = (item: any) => {
if (item.status === "PENDING") {
return (
<div className={style.statusBox}>
<img src={jobRun} alt="" />
<span className={style.status}>准备构建</span>
</div>
);
} else if (item.status === "CREATING") {
return (
<div className={style.statusBox}>
<img src={jobRun} alt="" />
<span className={style.status}>正在构建</span>
</div>
);
} else if (item.status === "FAILED") {
return (
<div className={style.statusBox}>
<img src={jobFail} alt="" />
<span className={style.status}>构建失败</span>
</div>
);
} else if (item.status === "CREATED") {
return (
<div className={style.statusBox}>
<img src={jobSue} alt="" />
<span className={style.status}>构建完成</span>
</div>
);
} else {
return "";
}
};
const renderCreatedTime = (item: any) => {
return moment(new Date(item.createdTime)).format("yyyy-MM-DD hh:mm:ss");
};
const handleDelete = (item: any) => {
setId(item.id);
setDeleteOpen(true);
};
const hanleToSeeEnv = (item: any) => {
console.log("hanleToSeeEnv");
console.log(item.id);
navigate("/product/resourceCenter/userResources/seeEnv", {
state: { id: item.id },
});
};
const renderButtons = (item: any) => {
if (item.status === "FAILED") {
return (
<>
<MyButton
text="详情"
style={{
position: "relative",
left: "-10px",
minWidth: "10px",
height: "22px",
padding: "0 10px",
}}
variant="text"
size="medium"
onClick={() => hanleToSeeEnv(item)}
/>
<MyButton
onClick={() => handleDelete(item)}
text="删除"
style={{
position: "relative",
left: "-10px",
minWidth: "10px",
height: "22px",
padding: "0 10px",
}}
variant="text"
size="medium"
color="error"
/>
</>
);
} else {
return (
<MyButton
text="详情"
style={{
position: "relative",
left: "-10px",
minWidth: "10px",
height: "22px",
padding: "0 10px",
}}
variant="text"
size="medium"
onClick={() => hanleToSeeEnv(item)}
/>
);
}
};
return (
<div className={style.environment}>
<div className={style.top}>
<div className={style.topLeft}>
<SearchInput
sx={{ width: 340, marginRight: "16px" }}
onKeyUp={(e: any) => {
if (e.keyCode === 13) {
setTitle(e.target.value);
}
}}
></SearchInput>
{!addOpen && (
<MySelect
title="环境类型"
isTitle={true}
options={[
{
label: "批式",
value: "BATCH",
},
{
label: "流式",
value: "FLOW",
},
]}
value={type}
onChange={(e: any) => setType(e)}
sx={{ width: "150px", height: "32px" }}
></MySelect>
)}
</div>
<div className={style.topRight}>
<MyButton
text="构建应用环境"
onClick={() => setAddopen(true)}
startIcon={<Add />}
></MyButton>
</div>
</div>
<div className={style.tableBox}>
<MyTable
rows={list.map((item: any) => ({
...item,
type: renderType(item),
status: renderStatus(item),
caozuo: renderButtons(item),
createdTime: renderCreatedTime(item),
}))}
headCells={headCells}
fixedHead={true}
hasTableFooter={true}
page={page}
count={count}
pageChange={pageChange}
rowsPerPage={size}
handleChangeRowsPerPage={(e: number) => {
setSize(e);
setPage(0);
}}
nodataText="暂无应用环境"
paginationType="complex"
totalElements={totalElements}
></MyTable>
</div>
{addOpen && <AddEnvironment setAddopen={setAddopen}></AddEnvironment>}
{deleteOpen && (
<DeleteEnvironment
id={id}
open={deleteOpen}
setDeleteOpen={setDeleteOpen}
></DeleteEnvironment>
)}
</div>
);
};
export default UserResourcesEnvironment;
.addOperatorBox {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #fff;
display: flex;
}
.left {
/* width: 412px; */
box-sizing: border-box;
background-color: rgba(247, 248, 250, 1);
}
.right {
flex: 1;
padding: 64px 44px 40px;
position: relative;
min-height: 100vh;
overflow: overlay;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.title {
color: rgba(30, 38, 51, 1);
margin-bottom: 32px;
font-size: 24px;
line-height: 32px;
font-weight: 550;
}
.content {
display: flex;
border-radius: 4px;
margin-bottom: 20px;
height: 600px;
}
.form {
width: 368px;
box-sizing: border-box;
padding: 16px 24px;
border: 1px solid #ebedf0;
border-right: none;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.newForm {
width: 368px;
box-sizing: border-box;
padding: 16px 32px 0px 0;
border-right: 1px solid #ebedf0;
}
.codeBox {
flex: 1;
display: flex;
flex-direction: column;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.codeTitle {
background-color: rgba(230, 233, 237, 1);
padding: 11px 20px;
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
font-weight: 550;
border-top-right-radius: 4px;
}
.code {
background-color: rgba(247, 248, 250, 1);
flex: 1;
}
.parameterConfigBox {
border: 1px solid #ebedf0;
margin-bottom: 24px;
}
.labelClassName {
line-height: 36px;
}
.operatorFormItem {
margin-bottom: 24px;
}
.descBox {
padding-left: 32px;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-18 16:12:55
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 21:27:03
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/components/AddOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { useEffect, useState, useCallback, useMemo } from "react";
import classNames from "classnames";
import { observer } from "mobx-react";
import MyInput from "@/components/mui/MyInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import style from "./index.module.css";
import SwitchBatchFolw from "@/views/ResourceCenter/components/SwitchBatchFolw";
import Code from "@/components/CommonComponents/Code";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { ITask } from "@/views/Project/ProjectSubmitWork/interface";
import BatchOperatorFlow from "@/views/Project/components/Flow/components/BatchOperatorFlow";
import OperatorList from "@/views/CustomOperator/components/OperatorList";
import FormItemBox from "@/components/mui/FormItemBox";
import { useStores } from "@/store";
interface IAddOperator {
setAddOpen: (val: boolean) => void;
}
type IBuildType = "ENVIRONMENT" | "OPERATOR";
const AddOperator = observer((props: IAddOperator) => {
const { setAddOpen } = props;
/** 创建类型 BATCH - 批算子; FLOW - 流算子*/
const [taskType, setTaskType] = useState<"BATCH" | "FLOW">("BATCH");
/** 创建类型 ENVIRONMENT - 基于环境; OPERATOR - 基于算子*/
const [batchBuildType, setBatchBuildType] =
useState<IBuildType>("ENVIRONMENT");
/** 算子数组 */
const [operatorList, setOperatorList] = useState<ITask[]>([]);
/** 流程编排 算子是否选中 */
const [inputActive, setInputActive] = useState(false);
/** 产品store */
const { productListStore } = useStores();
const [code, setCode] = useState("");
// const [formData, setFormData] = useState<any>();
const buildTypeList = useMemo(() => {
return [
{ value: "ENVIRONMENT", label: "基于应用环境" },
{ value: "OPERATOR", label: "基于流式算子" },
];
}, []);
/** 切换类型 */
const handleRadio = (val: IBuildType) => {
setBatchBuildType(val);
};
const handleSubmit = () => {
console.log(33);
};
return (
<div className={style.addOperatorBox}>
<div className={style.left}>
<SwitchBatchFolw
active={taskType}
setActive={setTaskType}
goBack={() => setAddOpen(false)}
></SwitchBatchFolw>
</div>
<div className={style.right}>
<div className={style.title}>
{taskType === "BATCH" ? "批式算子信息" : "流式算子信息"}
</div>
<div style={{ paddingBottom: "20px" }}>
<RadioGroupOfButtonStyle
RadiosBoxStyle={{ width: 236 }}
value={batchBuildType}
radioOptions={buildTypeList}
handleRadio={handleRadio}
/>
</div>
<div className={style.content}>
<div
className={classNames({
[style.form]: batchBuildType === "ENVIRONMENT",
[style.newForm]: batchBuildType != "ENVIRONMENT",
})}
>
<FormItemBox
label="算子名称"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
require
>
<MyInput
helperText="30字符以内,仅限字母、数字、中文"
placeholder="请输入算子名称"
/>
</FormItemBox>
<FormItemBox
label="算子版本"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
require
>
<MyInput />
</FormItemBox>
<FormItemBox
label="所属产品"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
require
>
<MySelect
fullWidth
options={productListStore?.productList || []}
/>
</FormItemBox>
{batchBuildType === "ENVIRONMENT" ? (
<FormItemBox
label="应用环境"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
require
>
<MySelect
fullWidth
options={[{ label: "cadd", value: "CADD" }]}
/>
</FormItemBox>
) : null}
{batchBuildType === "ENVIRONMENT" ? (
<FormItemBox
label="描述"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
>
<MyInput multiline rows={4} placeholder="请输入算子描述" />
</FormItemBox>
) : null}
</div>
{batchBuildType === "ENVIRONMENT" ? (
<div className={style.codeBox}>
<div className={style.codeTitle}>参数配置</div>
<div className={style.code}>
<Code
value={code}
onChange={(e: string) => setCode(e)}
height="535px"
/>
</div>
</div>
) : (
<div className={style.descBox}>
<FormItemBox
label="描述"
labelClassName={style.labelClassName}
className={style.operatorFormItem}
itemFlex="column"
>
<MyInput
style={{ width: "420px" }}
multiline
rows={10}
placeholder="请输入算子描述"
/>
</FormItemBox>
</div>
)}
</div>
<div className={style.parameterConfigBox}>
<div className={style.codeTitle}>
{batchBuildType === "ENVIRONMENT" ? "运行脚本" : "流程编排"}
</div>
{batchBuildType === "ENVIRONMENT" ? (
<div className={style.code}>
<Code
value={code}
onChange={(e: string) => setCode(e)}
height="350px"
/>
</div>
) : (
<div
id="customOperatorFlow"
style={{ position: "relative", height: 400 }}
>
<OperatorList
operatorList={operatorList}
setOperatorList={setOperatorList}
setInputActive={setInputActive}
/>
<BatchOperatorFlow
tasks={operatorList}
setTasks={setOperatorList}
type="edit"
// onFlowNodeClick={handleNodeClick}
flowNodeDraggable={true}
ListenState={!inputActive}
showVersion={true}
showControls={false}
/>
</div>
)}
</div>
<div className={style.buttonBox}>
<MyButton text="开始构建"></MyButton>
</div>
</div>
</div>
);
});
export default AddOperator;
.itemBox {
width: 334px;
height: 108px;
padding: 20px;
margin: 0 20px 20px 0;
background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
box-shadow: 0px 3px 12px 0px rgba(3, 47, 105, 0.09);
border-radius: 6px;
border: 2px solid #ffffff;
}
.itemBox:hover {
box-shadow: 0px 6px 24px 0px rgba(3, 47, 105, 0.14);
}
.itemHeaderBox {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.itemContentBox {
display: flex;
flex-wrap: wrap;
}
.titleBox {
display: block;
font-size: 16px;
color: #1e2633;
}
.titleBox {
display: block;
font-size: 16px;
color: #1e2633;
}
.operatorTypeBox {
display: block;
color: #8a9099;
font-size: 12px;
}
.infoBox {
width: 50%;
font-weight: 400;
color: #8a9099;
font-size: 14px;
line-height: 26px;
}
.infoBox > span {
color: #1e2633;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 21:08:31
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import styles from "./index.module.css";
import { IOperatorInfo } from "../../interface";
interface IProps {
operatorInfo: IOperatorInfo;
}
const OperatorCard = (props: IProps) => {
const {
operatorInfo: { title = "", type, version },
} = props;
return (
<div className={styles.itemBox}>
<div className={styles.itemHeaderBox}>
<img alt="" style={{ width: 36, height: 36 }} />
<div>
<b className={styles.titleBox}>{title}</b>
<span className={styles.operatorTypeBox}>批算子</span>
</div>
</div>
<div className={styles.itemContentBox}>
<p className={styles.infoBox}>
所属产品:<span>{type}</span>
</p>
<p className={styles.infoBox}>
算子版本:<span>{`V${version}`}</span>
</p>
<p className={styles.infoBox}>
创建时间:<span>2022-10-11</span>
</p>
</div>
</div>
);
};
export default OperatorCard;
.detailsBox {
padding: 0 24px;
}
.titleBox {
font-size: 16px;
color: #1e2633;
line-height: 24px;
padding: 20px 0;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 10:30:55
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import styles from "./index.module.css";
import BasicInfo from "../../../../components/BasinInfo";
import { useMemo, useState } from "react";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
const OperatorDetails = () => {
const contentTypeList = useMemo(() => {
return [
{ value: "flowChart", label: "流程图" },
{ value: "parameterList", label: "参数列表" },
{ value: "runScript", label: "运行脚本" },
];
}, []);
/** 详情类型 */
const [contentType, setContentType] = useState<string>("flowChart");
/** 切换类型 */
const handleRadio = (val: string) => {
setContentType(val);
};
return (
<div className={styles.detailsBox}>
<h2 className={styles.titleBox}>基础信息</h2>
<div style={{ border: "1px solid #EBEDF0" }}>
<BasicInfo
infoList={[
{ label: "33333331", value: "1" },
{
label: "1",
value: "42543253245325325432452345235432452323542352354235235321",
},
{ label: "1", value: "1" },
{ label: "1", value: "1" },
{ label: "1", value: "1" },
]}
/>
<BasicInfo infoList={[{ label: "2", value: "2" }]} />
</div>
<div style={{ padding: "26px 0 16px 0" }}>
<RadioGroupOfButtonStyle
RadiosBoxStyle={{ width: 254 }}
value={contentType}
radioOptions={contentTypeList}
handleRadio={handleRadio}
/>
</div>
<div>11</div>
</div>
);
};
export default OperatorDetails;
.indexBox {
padding: 0 4px;
}
.headerBox {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
}
.searchSelectBox {
margin-right: 12px;
}
.contentBox {
display: flex;
flex-wrap: wrap;
padding-left: 20px;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 21:11:50
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 应用环境
import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import OperatorCard from "./components/OperatorCard";
import AddOperator from "./components/AddOperator";
import { useStores } from "@/store";
import { getOperatorList, IOperatorListParams } from "@/api/resourceCenter";
import styles from "./index.module.css";
import useMyRequest from "@/hooks/useMyRequest";
import { IOperatorInfo } from "./interface";
const WorkflowOperator = observer(() => {
const [addOpen, setAddOpen] = useState<boolean>(false);
/** 产品store */
const { productListStore } = useStores();
/** 算子列表参数 */
const [searchParams, setSearchParams] = useState<IOperatorListParams>({
keyword: "",
productId: "",
type: "",
});
const [list, setList] = useState<IOperatorInfo[]>();
const { run: getList } = useMyRequest(getOperatorList, {
onSuccess: (res) => {
console.log(res);
setList(res?.data);
},
});
useEffect(() => {
getList();
}, []);
return (
<>
<div className={styles.indexBox}>
<div className={styles.headerBox}>
<div>
<SearchInput
sx={{ width: 340, marginRight: "16px" }}
placeholder="输入关键词搜索"
value={searchParams.keyword}
onChange={(e) => {
setSearchParams({ ...searchParams, keyword: e.target.value });
}}
/>
<MySelect
title="所属产品"
isTitle={true}
options={productListStore?.productList || []}
value={searchParams.keyword}
onChange={(e) => {
setSearchParams({ ...searchParams, productId: e });
}}
className={styles.searchSelectBox}
sx={{ width: "150px", height: "32px" }}
/>
<MySelect
title="环境类型"
isTitle={true}
value={searchParams.keyword}
onChange={(e) => {
setSearchParams({ ...searchParams, type: e });
}}
options={[
{
label: "批式",
value: "BATCH",
},
{
label: "流式",
value: "FLOW",
},
]}
sx={{ width: "150px", height: "32px" }}
/>
</div>
<MyButton
text="构建算子"
img={
<span
style={{ fontSize: "14px", marginRight: "8px" }}
className="iconfont icon-dianzan"
></span>
}
onClick={() => setAddOpen(true)}
></MyButton>
</div>
<div className={styles.contentBox}>
{list?.map((item) => {
return <OperatorCard operatorInfo={item} />;
})}
</div>
</div>
{addOpen && <AddOperator setAddOpen={setAddOpen} />}
</>
);
});
export default WorkflowOperator;
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-19 20:50:18
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-19 21:09:14
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export type IOperatorType = 'BATCH' | 'FLOW'
export interface IOperatorInfo{
title: string;
type: IOperatorType;
version: string;
productId: string;
}
\ No newline at end of file
.userResources {
height: calc(100vh - 57px);
width: 100%;
}
.top {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid rgba(235, 237, 240, 1);
}
.title {
padding: 14px 24px;
color: rgba(30, 38, 51, 1);
font-size: 18px;
line-height: 26px;
font-weight: 550;
}
.line {
width: 1px;
height: 20px;
background-color: rgba(221, 225, 230, 1);
}
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
}
.tab {
margin-left: 24px;
font-size: 16px;
line-height: 24px;
color: rgba(138, 144, 153, 1);
border-bottom: 2px solid transparent;
padding: 14px 0;
cursor: pointer;
}
.activeTab {
color: rgba(19, 112, 255, 1);
border-bottom: 2px solid rgba(19, 112, 255, 1);
}
.content {
padding: 20px 24px;
height: calc(100% - 55px);
box-sizing: border-box;
}
import style from "./index.module.css";
import usePass from "@/hooks/usePass";
import UserResourcesEnvironment from "./UserResourcesEnvironment";
import { useMemo, useState } from "react";
import classNames from "classnames";
import Tabs from "@/components/mui/MyTabs";
import WorkflowOperator from "./WorkflowOperator";
import OperatorDetails from "./WorkflowOperator/components/OperatorDetails";
const UserResources = () => {
const isPass = usePass();
const tabList = useMemo(() => {
return [
{
label: "工作流模版",
value: "USERRESOURCES_TEMPLATE",
component: <div />,
hide: !isPass("USERRESOURCES_TEMPLATE"),
},
{
label: "工作流算子",
value: "USERRESOURCES_FLOE",
component: <WorkflowOperator />,
hide: !isPass("USERRESOURCES_FLOE"),
},
{
label: "应用环境",
value: "USERRESOURCES_ENVIRONMENT",
component: <UserResourcesEnvironment />,
hide: !isPass("USERRESOURCES_ENVIRONMENT"),
},
];
}, [isPass]);
return (
<div className={style.userResources}>
<Tabs
title="个人资源"
tabList={tabList}
defaultValue={"USERRESOURCES_ENVIRONMENT"}
tabPanelSx={{ padding: "0" }}
/>
{/* <OperatorDetails /> */}
</div>
);
};
export default UserResources;
.trHeaderBox {
display: flex;
}
.trHeaderBox > div {
position: relative;
padding-left: 24px;
height: 44px;
background: #f5f6f7;
color: #565c66;
line-height: 44px;
width: calc(100% / 5);
}
.trHeaderBox > div::after {
position: absolute;
top: 12px;
right: 0px;
content: "";
height: 20px;
width: 0;
border-left: 1px solid #dde1e6;
}
.trHeaderBox > div:last-child::after {
content: "";
border: none;
}
.trBodyBox {
display: flex;
}
.trBodyBox > div {
overflow: hidden;
text-overflow: ellipsis;
display: "-webkit-box";
padding-left: 24px;
height: 44px;
color: #1e2633;
background: #fff;
line-height: 44px;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-18 14:52:48
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import MyTooltip from "@/components/mui/MyTooltip";
import { ReactElement, ReactNode } from "react";
import styles from "./index.module.css";
interface IProps {
infoList: IInfoItem[];
}
export interface IInfoItem {
label: string;
value: string | ReactNode | ReactElement;
flex?: number;
}
const BasicInfo = (props: IProps) => {
const { infoList } = props;
return (
<div className={styles.basicInfoBox}>
<div className={styles.trHeaderBox}>
{infoList.map((item) => {
return (
<div
style={{
width:
infoList?.length > 1
? `calc(100% / ${infoList.length})`
: "100%",
}}
>
{item.label}
</div>
);
})}
</div>
<div className={styles.trBodyBox}>
{infoList.map((item) => {
return (
<div
style={{
width:
infoList?.length > 1
? `calc(100% / ${infoList.length})`
: "100%",
}}
>
<MyTooltip
title={typeof item.value === "string" ? item.value : ""}
>
<span>{item.value}</span>
</MyTooltip>
</div>
);
})}
</div>
</div>
);
};
export default BasicInfo;
.logView {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1002;
}
.logViewBox {
background: #282c34;
}
.close {
position: absolute;
right: 0;
top: -28px;
cursor: pointer;
color: #fff;
}
.logViewTop {
position: relative;
width: 100%;
background-color: #1d2126;
display: flex;
font-size: 12px;
color: #8a9099;
overflow: hidden;
}
.leftButton {
width: 48px;
height: 32px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-right: 1px solid #10141a;
background-color: #1d2126;
}
.rightButton {
width: 48px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-left: 1px solid #10141a;
background-color: #1d2126;
}
.middleFixed {
width: calc(100% - 98px);
position: relative;
overflow: hidden;
}
.middleDynamic {
display: flex;
position: absolute;
left: 0;
transition: left 0.4s ease-in-out;
}
.logTitle {
display: flex;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex-shrink: 0;
align-items: center;
height: 32px;
line-height: 20px;
padding: 0 20px;
cursor: pointer;
border-right: 1px solid #10141a;
}
.logTitle:hover {
background-color: #23272e;
}
.logName {
max-width: 90px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.logTitleSelected {
background: #282c34;
color: #ffffff;
}
.fileIcon {
width: 14px !important;
margin-right: 4px;
}
.logViewContent {
position: relative;
box-sizing: border-box;
height: calc(100vh - 148px);
padding: 24px 32px 0;
color: #d1d6de;
white-space: pre-wrap;
word-break: break-word;
overflow: overlay;
font-size: 14px;
line-height: 22px;
}
.logViewContentMask {
height: 24px;
width: calc(100% - 64px);
background-color: #282c34;
position: absolute;
top: 32px;
left: 32px;
z-index: 1005;
}
.logViewContent::-webkit-scrollbar-track {
background-color: #282c34;
}
.logViewBottom {
display: flex;
align-items: center;
justify-content: end;
height: 76px;
padding-right: 24px;
}
.gradientBox {
position: absolute;
right: 49px;
width: 28px;
height: 32px;
background: linear-gradient(90deg, rgba(29, 33, 38, 0) 0%, #1d2126 100%);
}
import { useState, useEffect } from "react";
import classnames from "classnames";
import style from "./index.module.css";
import MyTooltip from "@/components/mui/MyTooltip";
import InsertDriveFileOutlinedIcon from "@mui/icons-material/InsertDriveFileOutlined";
import CloudEController from "@/api/fileserver/CloudEController";
import useMyRequest from "@/hooks/useMyRequest";
import { getPublicProject } from "@/api/resourceCenter";
import { getDataFileToken, hpczone } from "@/api/project_api";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import useWindowSize from "@/hooks/useWindowSize";
type LogViewProps = {
logs: any[];
};
const LogView = (props: LogViewProps) => {
const { logs } = props;
const [hpczoneList, setHpczoneList] = useState<Array<any>>([]);
const [publicProjectId, setPublicProjectId] = useState("");
const [publicZoneId, setPublicZoneId] = useState("");
const [fileToken, setFileToken] = useState("");
const { width, height } = useWindowSize();
// 当前选择的日志
const [logCurrent, setLogCurrent] = useState<number>(0);
// 当前日志的内容文本
const [logText, setLogText] = useState("");
// 当前日志路径
const [logPath, setLogPath] = useState("");
const [displacement, setDisplacement] = useState(0);
const [middleDynamicWidth, setMiddleDynamicWidth] = useState(0);
const [leftButtonColor, setLeftButtonColor] = useState("#585D62");
const [rightButtonColor, setRightButtonColor] = useState("#585D62");
const { run: getPublicProjectFn } = useMyRequest(getPublicProject, {
onSuccess: (res: any) => {
setPublicProjectId(res.data[0].id);
setPublicZoneId(res.data[0].zoneId);
getDataFileTokenFn({ id: res.data[0].id });
},
});
const { run: getDataFileTokenFn } = useMyRequest(getDataFileToken, {
onSuccess: (res: any) => {
setFileToken(res.data);
},
});
useEffect(() => {
getPublicProjectFn();
}, [getPublicProjectFn]);
const { run: hpczoneFn } = useMyRequest(hpczone, {
onSuccess: (res: any) => {
setHpczoneList(res.data);
},
});
useEffect(() => {
hpczoneFn();
}, [hpczoneFn]);
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logs, logCurrent]);
// 请求日志文本
useEffect(() => {
if (logPath) {
const path = logPath.slice(12);
let origin = "";
hpczoneList.forEach((item) => {
if (item.id === publicZoneId) {
origin = item?.storageConfig?.fileServerEndPoint;
}
});
if (path && fileToken && publicProjectId && origin) {
CloudEController.JobFileDownloadText(
path,
fileToken as string,
publicProjectId as string,
origin
)?.then((res) => {
setLogText(res.data);
});
} else {
setLogText("");
}
} else {
setLogText("");
}
}, [logPath, fileToken, hpczoneList, publicProjectId, publicZoneId]);
// 选择日志时改变日志路径
useEffect(() => {
setLogPath(logs[logCurrent]?.logPath);
}, [logCurrent, logs]);
//获取盒子的总宽度,用于滑动效果判断
useEffect(() => {
const box = document.getElementById("middleDynamic");
setMiddleDynamicWidth(box ? box.offsetWidth : 0);
}, []);
useEffect(() => {
if (middleDynamicWidth < width - 97) {
setLeftButtonColor("#585D62");
setRightButtonColor("#585D62");
}
if (displacement === 0) {
setLeftButtonColor("#585D62");
} else {
setLeftButtonColor("#C0C5CD");
}
if (
middleDynamicWidth > width - 97 &&
displacement !== -middleDynamicWidth + width - 97
) {
setRightButtonColor("#C0C5CD");
} else {
setRightButtonColor("#585D62");
}
}, [width, middleDynamicWidth, displacement]);
// 下载当前日志
// const handleDownLoad = () => {
// const path = logPath.slice(12);
// CloudEController.JobFileDownload(
// path,
// fileToken as string,
// publicProjectId as string
// );
// };
const rightClick = () => {
if (middleDynamicWidth < width - 97) {
return;
}
if (-displacement > middleDynamicWidth - width * 1.8 + 97) {
setDisplacement(-middleDynamicWidth + width - 97);
return;
}
const newDisplacement = displacement - width * 0.8;
setDisplacement(newDisplacement);
};
const leftClick = () => {
if (-displacement < width * 0.8) {
setDisplacement(0);
return;
}
const newDisplacement = displacement + width * 0.8;
setDisplacement(newDisplacement);
};
return (
<div className={style.logViewBox}>
<div className={style.logViewContentMask}></div>
<div className={style.logViewTop}>
<div
className={style.leftButton}
onClick={leftClick}
style={{
color: leftButtonColor,
cursor: leftButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronLeftIcon />
</div>
<div className={style.middleFixed}>
<div
className={style.middleDynamic}
id="middleDynamic"
style={{ left: `${displacement}px` }}
>
{logs.map((item: any, index: number) => {
return (
<MyTooltip
title={item.logName}
placement="bottom"
arrow={false}
enterDelay={1000}
>
<div
key={index}
onClick={() => {
setLogCurrent(index);
}}
className={classnames({
[style.logTitle]: true,
[style.logTitleSelected]: index === logCurrent,
})}
>
<InsertDriveFileOutlinedIcon className={style.fileIcon} />
<span className={style.logName}>{item.logName}</span>
</div>
</MyTooltip>
);
})}
</div>
</div>
<div className={style.gradientBox}></div>
<div
className={style.rightButton}
onClick={rightClick}
style={{
color: rightButtonColor,
cursor: rightButtonColor === "#585D62" ? "default" : "pointer",
}}
>
<ChevronRightIcon />
</div>
</div>
<div className={style.logViewContent}>{logText}</div>
{/* <div className={style.logViewBottom}>
<MyButton text="下载当前日志" onClick={handleDownLoad} />
</div> */}
</div>
);
};
export default LogView;
.switchBatchFolw {
height: 100vh;
width: 50vh;
background-color: rgba(247, 248, 250, 1);
display: flex;
flex-direction: column;
}
.goBackBox {
box-sizing: border-box;
height: 110px;
padding: 64px 0 14px 25%;
line-height: 32px;
font-size: 18px;
color: #8a9099;
display: flex;
justify-content: flex-start;
align-items: center;
}
.goBackIcon {
width: 32px;
height: 32px;
background-color: #fff;
border-radius: 4px;
margin-right: 12px;
box-shadow: 0px 2px 5px 0px rgba(3, 47, 105, 0.09);
cursor: pointer;
}
.goBackText {
line-height: 32px;
font-size: 18px;
color: #8a9099;
}
.switchBox {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-end;
position: relative;
}
.switchItem {
width: 100%;
position: relative;
padding-right: 44px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.activeSwitchItem {
padding-right: 34px;
}
.itemImg {
width: 58%;
cursor: pointer;
}
.itemImg:hover {
box-shadow: 0px 8px 20px -6px rgba(3, 47, 105, 0.14);
}
.activeImg {
width: 64%;
box-shadow: 0px 12px 30px -8px rgba(3, 47, 105, 0.18);
}
.activeImg:hover {
box-shadow: 0px 12px 30px -8px rgba(3, 47, 105, 0.18);
}
.arrow {
width: 0px;
height: 0px;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 25px solid #fff;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
import batchImg from "@/assets/resourceCenter/batchImg.svg";
import flowImg from "@/assets/resourceCenter/flowImg.svg";
import classNames from "classnames";
import goback from "@/assets/project/goback.svg";
import style from "./index.module.css";
type ISwitchBatchFolwProps = {
active: "BATCH" | "FLOW";
setActive: any;
goBack: any;
};
const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
const { active, setActive, goBack } = props;
return (
<div className={style.switchBatchFolw}>
<div className={style.goBackBox}>
<img
className={style.goBackIcon}
src={goback}
alt=""
onClick={() => goBack()}
/>
<span className={style.goBackText}>返回</span>
</div>
<div className={style.switchBox}>
<div
className={classNames({
[style.switchItem]: true,
[style.activeSwitchItem]: active === "BATCH",
})}
>
<img
onClick={() => setActive("BATCH")}
className={classNames({
[style.itemImg]: true,
[style.activeImg]: active === "BATCH",
})}
src={batchImg}
alt=""
/>
{active === "BATCH" && <div className={style.arrow}></div>}
</div>
<div
className={classNames({
[style.switchItem]: true,
[style.activeSwitchItem]: active === "FLOW",
})}
>
<img
onClick={() => setActive("FLOW")}
className={classNames({
[style.itemImg]: true,
[style.activeImg]: active === "FLOW",
})}
src={flowImg}
alt=""
/>
{active === "FLOW" && <div className={style.arrow}></div>}
</div>
</div>
</div>
);
};
export default SwitchBatchFolw;
......@@ -19,7 +19,7 @@ import MyRadio from "@/components/mui/MyRadio";
import questionMark from "@/assets/project/questionMark.svg";
import fileSelectIcon from "@/assets/project/fileSelect.svg";
import MySwitch from "@/components/mui/MySwitch";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import { getCustomTemplateParameterCheckResult } from "../../util";
import MyTooltip from "@/components/mui/MyTooltip";
import { useSize } from "ahooks";
......
const IconfontDemo = () => {
return (
<div>
IconfontDemo
<div style={{ fontSize: "50px", color: "red" }}>
<svg className="icon" aria-hidden="true">
<use xlinkHref="#icon-sousuo-223"></use>
</svg>
</div>
<div style={{ fontSize: "50px", color: "red" }}>
<svg className="icon" aria-hidden="true">
<use xlinkHref="#icon-dianzan"></use>
</svg>
</div>
<span
style={{ fontSize: "50px", color: "red" }}
className="iconfont icon-dianzan"
></span>
</div>
);
};
export default IconfontDemo;
import MyTableDemo from "./MyTableDemo";
import QueueSelectDemo from "./QueueSelectDemo";
import IconfontDemo from "./IconfontDemo";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { useState } from "react";
import styles from "./index.module.css";
const Demo = () => {
const radioOptionsArr = [
{
value: "iconfont",
label: "iconfont",
},
{
value: "队列选择器",
label: "队列选择器",
......@@ -22,7 +27,7 @@ const Demo = () => {
const handleRadio = (e: string) => {
setSelectDemo(e);
};
const [selectDemo, setSelectDemo] = useState("队列选择器");
const [selectDemo, setSelectDemo] = useState("iconfont");
return (
<div className={styles.demoBox}>
......@@ -32,6 +37,7 @@ const Demo = () => {
handleRadio={handleRadio}
/>
<div className={styles.demoContentBox}>
{selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>}
{selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>}
{selectDemo === "表格" && <MyTableDemo></MyTableDemo>}
{selectDemo === "box" && <div>box</div>}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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