Merge branch 'dev_m_copy' into dev_military

# Conflicts:
#	src/forge/Merge/MessageCount.js
This commit is contained in:
caishi 2021-03-01 10:11:48 +08:00
commit 0a39ed80da
143 changed files with 6868 additions and 2449 deletions

16
.babelrc Normal file
View File

@ -0,0 +1,16 @@
{
"presets": [
"es2015",
"react",
"stage-2"
],
"plugins": [[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}

View File

@ -141,7 +141,6 @@ module.exports = {
name: "static/media/[name].[hash:8].[ext]",
},
},
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
@ -161,10 +160,8 @@ module.exports = {
],
},
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,

248
package-lock.json generated
View File

@ -1254,6 +1254,55 @@
"ast-types-flow": "0.0.7"
}
},
"babel-cli": {
"version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-cli/download/babel-cli-6.26.0.tgz",
"integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=",
"dev": true,
"requires": {
"babel-core": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-register": "^6.26.0",
"babel-runtime": "^6.26.0",
"chokidar": "^1.6.1",
"commander": "^2.11.0",
"convert-source-map": "^1.5.0",
"fs-readdir-recursive": "^1.0.0",
"glob": "^7.1.2",
"lodash": "^4.17.4",
"output-file-sync": "^1.1.2",
"path-is-absolute": "^1.0.1",
"slash": "^1.0.0",
"source-map": "^0.5.6",
"v8flags": "^2.1.1"
},
"dependencies": {
"chokidar": {
"version": "1.7.0",
"resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz?cache=0&sync_timestamp=1602585438968&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-1.7.0.tgz",
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
"dev": true,
"optional": true,
"requires": {
"anymatch": "^1.3.0",
"async-each": "^1.0.0",
"fsevents": "^1.0.0",
"glob-parent": "^2.0.0",
"inherits": "^2.0.1",
"is-binary-path": "^1.0.0",
"is-glob": "^2.0.0",
"path-is-absolute": "^1.0.0",
"readdirp": "^2.0.0"
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@ -1273,7 +1322,7 @@
},
"babel-core": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
"resolved": "https://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz",
"integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
"requires": {
"babel-code-frame": "^6.26.0",
@ -1299,8 +1348,8 @@
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1605791507452&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
}
@ -1345,6 +1394,17 @@
}
}
},
"babel-helper-bindify-decorators": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-helper-bindify-decorators/download/babel-helper-bindify-decorators-6.24.1.tgz",
"integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
"babel-traverse": "^6.24.1",
"babel-types": "^6.24.1"
}
},
"babel-helper-builder-binary-assignment-operator-visitor": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
@ -1397,6 +1457,18 @@
"babel-types": "^6.24.1"
}
},
"babel-helper-explode-class": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-helper-explode-class/download/babel-helper-explode-class-6.24.1.tgz",
"integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=",
"dev": true,
"requires": {
"babel-helper-bindify-decorators": "^6.24.1",
"babel-runtime": "^6.22.0",
"babel-traverse": "^6.24.1",
"babel-types": "^6.24.1"
}
},
"babel-helper-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
@ -1585,11 +1657,23 @@
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
},
"babel-plugin-syntax-async-generators": {
"version": "6.13.0",
"resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-async-generators/download/babel-plugin-syntax-async-generators-6.13.0.tgz",
"integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
"dev": true
},
"babel-plugin-syntax-class-properties": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="
},
"babel-plugin-syntax-decorators": {
"version": "6.13.0",
"resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-decorators/download/babel-plugin-syntax-decorators-6.13.0.tgz",
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
"dev": true
},
"babel-plugin-syntax-dynamic-import": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
@ -1620,6 +1704,17 @@
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
"integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
},
"babel-plugin-transform-async-generator-functions": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-async-generator-functions/download/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
"integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=",
"dev": true,
"requires": {
"babel-helper-remap-async-to-generator": "^6.24.1",
"babel-plugin-syntax-async-generators": "^6.5.0",
"babel-runtime": "^6.22.0"
}
},
"babel-plugin-transform-async-to-generator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
@ -1641,6 +1736,19 @@
"babel-template": "^6.24.1"
}
},
"babel-plugin-transform-decorators": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-decorators/download/babel-plugin-transform-decorators-6.24.1.tgz",
"integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=",
"dev": true,
"requires": {
"babel-helper-explode-class": "^6.24.1",
"babel-plugin-syntax-decorators": "^6.13.0",
"babel-runtime": "^6.22.0",
"babel-template": "^6.24.1",
"babel-types": "^6.24.1"
}
},
"babel-plugin-transform-es2015-arrow-functions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
@ -1935,7 +2043,7 @@
},
"babel-plugin-transform-runtime": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-runtime/download/babel-plugin-transform-runtime-6.23.0.tgz",
"integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
"requires": {
"babel-runtime": "^6.22.0"
@ -1950,6 +2058,25 @@
"babel-types": "^6.24.1"
}
},
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"core-js": "^2.5.0",
"regenerator-runtime": "^0.10.5"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
"dev": true
}
}
},
"babel-preset-env": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
@ -1987,6 +2114,38 @@
"semver": "^5.3.0"
}
},
"babel-preset-es2015": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-preset-es2015/download/babel-preset-es2015-6.24.1.tgz",
"integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
"dev": true,
"requires": {
"babel-plugin-check-es2015-constants": "^6.22.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
"babel-plugin-transform-es2015-block-scoping": "^6.24.1",
"babel-plugin-transform-es2015-classes": "^6.24.1",
"babel-plugin-transform-es2015-computed-properties": "^6.24.1",
"babel-plugin-transform-es2015-destructuring": "^6.22.0",
"babel-plugin-transform-es2015-duplicate-keys": "^6.24.1",
"babel-plugin-transform-es2015-for-of": "^6.22.0",
"babel-plugin-transform-es2015-function-name": "^6.24.1",
"babel-plugin-transform-es2015-literals": "^6.22.0",
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
"babel-plugin-transform-es2015-modules-systemjs": "^6.24.1",
"babel-plugin-transform-es2015-modules-umd": "^6.24.1",
"babel-plugin-transform-es2015-object-super": "^6.24.1",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
"babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-es2015-sticky-regex": "^6.24.1",
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
"babel-plugin-transform-es2015-typeof-symbol": "^6.22.0",
"babel-plugin-transform-es2015-unicode-regex": "^6.24.1",
"babel-plugin-transform-regenerator": "^6.24.1"
}
},
"babel-preset-flow": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz",
@ -2005,7 +2164,7 @@
},
"babel-preset-react": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz",
"resolved": "https://registry.npm.taobao.org/babel-preset-react/download/babel-preset-react-6.24.1.tgz",
"integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=",
"requires": {
"babel-plugin-syntax-jsx": "^6.3.13",
@ -2036,6 +2195,31 @@
"babel-preset-react": "6.24.1"
}
},
"babel-preset-stage-2": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-preset-stage-2/download/babel-preset-stage-2-6.24.1.tgz",
"integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=",
"dev": true,
"requires": {
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators": "^6.24.1",
"babel-preset-stage-3": "^6.24.1"
}
},
"babel-preset-stage-3": {
"version": "6.24.1",
"resolved": "https://registry.npm.taobao.org/babel-preset-stage-3/download/babel-preset-stage-3-6.24.1.tgz",
"integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=",
"dev": true,
"requires": {
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
"babel-plugin-transform-async-generator-functions": "^6.24.1",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-exponentiation-operator": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.22.0"
}
},
"babel-register": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
@ -3704,6 +3888,11 @@
"randomfill": "^1.0.3"
}
},
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz",
"integrity": "sha1-KQSrJnep0EKFai6i74DekuSjbcw="
},
"crypto-random-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
@ -4778,6 +4967,11 @@
"domelementtype": "1"
}
},
"dompurify": {
"version": "2.0.15",
"resolved": "https://registry.npm.taobao.org/dompurify/download/dompurify-2.0.15.tgz?cache=0&sync_timestamp=1607352578938&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdompurify%2Fdownload%2Fdompurify-2.0.15.tgz",
"integrity": "sha1-gOMA/D6JVHvQrxr/LrqIzhf8neo="
},
"domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
@ -6888,6 +7082,12 @@
"minipass": "^3.0.0"
}
},
"fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npm.taobao.org/fs-readdir-recursive/download/fs-readdir-recursive-1.1.0.tgz",
"integrity": "sha1-4y/AMKLM7kSmtTcTCNpUvgs5fSc=",
"dev": true
},
"fs-write-stream-atomic": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
@ -11339,6 +11539,17 @@
"os-tmpdir": "^1.0.0"
}
},
"output-file-sync": {
"version": "1.1.2",
"resolved": "https://registry.npm.taobao.org/output-file-sync/download/output-file-sync-1.1.2.tgz",
"integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.4",
"mkdirp": "^0.5.1",
"object-assign": "^4.1.0"
}
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
@ -14939,8 +15150,8 @@
},
"react-player": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-1.15.3.tgz",
"integrity": "sha512-8fc0R1AipFIy7l4lKgnIg+gMU2IY32ZMxxBlINjXAq/YnN3HUP3hOaE+aQ0lQv+a1/MMZgbekWD86ZGDO7kB8g==",
"resolved": "https://registry.npm.taobao.org/react-player/download/react-player-1.15.3.tgz",
"integrity": "sha1-0AzxRfnIYYTLCgcaH7+Oy3tomH8=",
"requires": {
"deepmerge": "^4.0.0",
"load-script": "^1.0.0",
@ -14949,8 +15160,8 @@
"dependencies": {
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
"resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-4.2.2.tgz",
"integrity": "sha1-RNLqNnm49NT/ujPwPYZfwee/SVU="
}
}
},
@ -17010,8 +17221,8 @@
},
"source-map-support": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
"resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.4.18.tgz?cache=0&sync_timestamp=1587719517036&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.4.18.tgz",
"integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
"requires": {
"source-map": "^0.5.6"
},
@ -18666,6 +18877,12 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"user-home": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz",
"integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=",
"dev": true
},
"util": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
@ -18717,6 +18934,15 @@
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
"integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w=="
},
"v8flags": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/v8flags/download/v8flags-2.1.1.tgz?cache=0&sync_timestamp=1590964281452&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8flags%2Fdownload%2Fv8flags-2.1.1.tgz",
"integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=",
"dev": true,
"requires": {
"user-home": "^1.1.1"
}
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",

View File

@ -1,5 +1,5 @@
{
"name": "educoder",
"name": "forge",
"version": "0.1.0",
"private": true,
"dependencies": {
@ -10,11 +10,9 @@
"array-flatten": "^2.1.2",
"autoprefixer": "7.1.6",
"axios": "^0.18.1",
"babel-core": "6.26.0",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"code-prettify": "^0.1.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
@ -24,9 +22,11 @@
"chalk": "1.1.3",
"classnames": "^2.2.5",
"clipboard": "^2.0.6",
"code-prettify": "^0.1.0",
"codemirror": "^5.53.0",
"connected-react-router": "4.4.1",
"css-loader": "^3.5.2",
"dompurify": "^2.0.15",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"echarts": "^4.7.0",
@ -182,7 +182,13 @@
"port": "3007",
"devDependencies": {
"@babel/runtime": "7.0.0-beta.51",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-plugin-import": "^1.13.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"compression-webpack-plugin": "^1.1.12",
"concat": "^1.0.3",
"happypack": "^5.0.1",

View File

@ -1,6 +1,5 @@
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader {
background: #24292D !important;
width: 100%;
height: 60px !important;
min-width: 1200px;

View File

@ -1498,9 +1498,6 @@ a.edu-txt-w80,
.font-bd {
font-weight: bold;
}
.fwt-500{
font-weight: 500 !important;
}
.font-n {
font-weight: normal;
@ -2328,6 +2325,9 @@ input::-ms-clear {
background-color: #F5F5F5;
}
.ant-modal-close{
top:8px!important;
}
.newContainer {
min-height: 100%;
@ -2348,7 +2348,6 @@ input::-ms-clear {
margin: 0 auto;
padding-bottom: 110px;
min-width: 1200px;
padding-top: 60px;
}
@ -2662,7 +2661,7 @@ a.color-green:hover {
/*百分比宽度*/
.width100 {
width: 100%;
width: 100% !important;
}
.width89 {
@ -3948,74 +3947,53 @@ html>body #ajax-indicator {
.head-nav {
text-align: center;
height: 60px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
padding: 0 70px;
/* text-align: center;
height: 60px;
height: 70px;
box-sizing: border-box;
min-width: 780px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1; */
flex: 1;
}
.head-nav ul#header-nav {
position: absolute;
top: 0px;
z-index: 3;
height: 60px;
height: 70px;
box-sizing: border-box;
}
.head-nav ul#header-nav li {
float: left;
height: 60px;
line-height: 60px;
padding: 0 24px;
height: 70px;
line-height: 70px;
cursor: pointer;
position: relative;
font-size: 16px;
padding:0px 20px;
}
.head-nav ul#header-nav li.active a, .head-nav ul#header-nav li:hover a{
color: #1484ef;
}
.head-nav ul#header-nav li.active a:after{
content: "";
width: 100%;
height: 2px;
background-color: #1484ef;
left: 0;
bottom: 12px;
position: absolute;
}
.head-nav ul#header-nav li a {
display: block;
height: 100%;
width: 100%;
color: #333333;
color: #333;
font-size: 16px;
position: relative;
}
/* .head-nav ul#header-nav li a:hover {
.head-nav ul#header-nav li a:hover,.head-nav ul#header-nav li.active a {
color: #5091FF;
} */
}
.head-nav ul#header-nav li:last-child {
margin-right: 0px
}
.head-nav ul#header-nav li.active a:first-child {
color: #1484ef !important;
.head-nav ul#header-nav li.active{
/* background-color: #3B3B3B; */
}
.head-nav ul#header-nav li.active p {
color: #1484ef !important;
}
.head-nav ul#header-nav li p:hover {
color: #cccccc;
@ -4028,21 +4006,21 @@ html>body #ajax-indicator {
color: #fff
}
.head-nav ul#header-nav li.active div ul li a {
/* .head-nav ul#header-nav li.active div ul li a {
color: #000 !important;
}
} */
.head-nav ul#header-nav li.active div ul li a:hover {
/* .head-nav ul#header-nav li.active div ul li a:hover {
color: #FFF !important;
}
.head-nav ul#header-nav li.active ul li a {
color: #000 !important;
}
} */
.head-nav ul#header-nav li.active ul li a:hover {
/* .head-nav ul#header-nav li.active ul li a:hover {
color: #FFF !important;
}
} */
/* .head-nav ul#header-nav li.active:after {
content: '';

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,559 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "17567215",
"name": "主页",
"font_class": "zhuye1",
"unicode": "e7e4",
"unicode_decimal": 59364
},
{
"icon_id": "17542255",
"name": "项目简介",
"font_class": "xiangmujianjie",
"unicode": "e7e7",
"unicode_decimal": 59367
},
{
"icon_id": "17542254",
"name": "参与成员",
"font_class": "canyuchengyuan",
"unicode": "e7e6",
"unicode_decimal": 59366
},
{
"icon_id": "17542253",
"name": "使用文档",
"font_class": "shiyongwendang",
"unicode": "e7e5",
"unicode_decimal": 59365
},
{
"icon_id": "17541348",
"name": "代码库",
"font_class": "daimaku",
"unicode": "e7d9",
"unicode_decimal": 59353
},
{
"icon_id": "17541349",
"name": "forc",
"font_class": "forc",
"unicode": "e7da",
"unicode_decimal": 59354
},
{
"icon_id": "17541350",
"name": "点赞",
"font_class": "dianzan3",
"unicode": "e7dd",
"unicode_decimal": 59357
},
{
"icon_id": "17541351",
"name": "里程碑",
"font_class": "lichengbei",
"unicode": "e7de",
"unicode_decimal": 59358
},
{
"icon_id": "17541352",
"name": "取消点赞",
"font_class": "quxiaodianzan",
"unicode": "e7df",
"unicode_decimal": 59359
},
{
"icon_id": "17541353",
"name": "fork2",
"font_class": "fork2",
"unicode": "e7e0",
"unicode_decimal": 59360
},
{
"icon_id": "17541354",
"name": "合并请求",
"font_class": "hebingqingqiu1",
"unicode": "e7e1",
"unicode_decimal": 59361
},
{
"icon_id": "17541355",
"name": "任务",
"font_class": "renwu",
"unicode": "e7e2",
"unicode_decimal": 59362
},
{
"icon_id": "17541356",
"name": "通知",
"font_class": "tongzhi",
"unicode": "e7e3",
"unicode_decimal": 59363
},
{
"icon_id": "17481990",
"name": "金币",
"font_class": "jinbi",
"unicode": "e7c5",
"unicode_decimal": 59333
},
{
"icon_id": "17468131",
"name": "未开摄像头",
"font_class": "weikaishexiangtou1",
"unicode": "e7d8",
"unicode_decimal": 59352
},
{
"icon_id": "17435144",
"name": "关卡菜单",
"font_class": "guankacaidan",
"unicode": "e7ce",
"unicode_decimal": 59342
},
{
"icon_id": "17416333",
"name": "重置实训",
"font_class": "zhongzhishixun",
"unicode": "e7d5",
"unicode_decimal": 59349
},
{
"icon_id": "17416337",
"name": "复制粘贴",
"font_class": "fuzhiniantie",
"unicode": "e7d6",
"unicode_decimal": 59350
},
{
"icon_id": "17416342",
"name": "共享桌面",
"font_class": "gongxiangzhuomian",
"unicode": "e7d7",
"unicode_decimal": 59351
},
{
"icon_id": "17415865",
"name": "退出全屏",
"font_class": "tuichuquanping",
"unicode": "e7d4",
"unicode_decimal": 59348
},
{
"icon_id": "17415856",
"name": "全屏",
"font_class": "quanping",
"unicode": "e7d2",
"unicode_decimal": 59346
},
{
"icon_id": "17415080",
"name": "复制版本库地址",
"font_class": "fuzhibanbenkudizhi1",
"unicode": "e7d3",
"unicode_decimal": 59347
},
{
"icon_id": "17400088",
"name": "实验环境倒计时",
"font_class": "shiyanhuanjingdaojishi",
"unicode": "e7d1",
"unicode_decimal": 59345
},
{
"icon_id": "17399931",
"name": "vnc实训界面-工具栏",
"font_class": "vncshixunjiemian-gongjulan",
"unicode": "e7d0",
"unicode_decimal": 59344
},
{
"icon_id": "17399816",
"name": "vnc实训界面-展开",
"font_class": "vncshixunjiemian-zhankai",
"unicode": "e7cf",
"unicode_decimal": 59343
},
{
"icon_id": "17399289",
"name": "vnc实训界面-收起",
"font_class": "vncshixunjiemian-shouqi",
"unicode": "e7cd",
"unicode_decimal": 59341
},
{
"icon_id": "17393121",
"name": "撤销分组",
"font_class": "chexiaofenzu",
"unicode": "e7ca",
"unicode_decimal": 59338
},
{
"icon_id": "17393122",
"name": "撤销共享",
"font_class": "chexiaogongxiang",
"unicode": "e7cb",
"unicode_decimal": 59339
},
{
"icon_id": "17393123",
"name": "选中",
"font_class": "xuanzhong1",
"unicode": "e7cc",
"unicode_decimal": 59340
},
{
"icon_id": "17347836",
"name": "警示",
"font_class": "jingshi1",
"unicode": "e7c9",
"unicode_decimal": 59337
},
{
"icon_id": "17338109",
"name": "删除",
"font_class": "shanchu21",
"unicode": "e7c8",
"unicode_decimal": 59336
},
{
"icon_id": "17338062",
"name": "收藏",
"font_class": "shoucang3",
"unicode": "e7c7",
"unicode_decimal": 59335
},
{
"icon_id": "17320656",
"name": "搜索",
"font_class": "sousuo2",
"unicode": "e7c6",
"unicode_decimal": 59334
},
{
"icon_id": "17272329",
"name": "光标",
"font_class": "guangbiao",
"unicode": "e7c4",
"unicode_decimal": 59332
},
{
"icon_id": "17215358",
"name": "QQ",
"font_class": "QQ",
"unicode": "e7c3",
"unicode_decimal": 59331
},
{
"icon_id": "675739",
"name": "用户",
"font_class": "yonghu",
"unicode": "e7c2",
"unicode_decimal": 59330
},
{
"icon_id": "12703761",
"name": "oschina",
"font_class": "oschina",
"unicode": "e7c1",
"unicode_decimal": 59329
},
{
"icon_id": "17189615",
"name": "右",
"font_class": "you",
"unicode": "e7bf",
"unicode_decimal": 59327
},
{
"icon_id": "17189616",
"name": "左",
"font_class": "zuo",
"unicode": "e7c0",
"unicode_decimal": 59328
},
{
"icon_id": "17126010",
"name": "编程语言",
"font_class": "bianchengyuyan",
"unicode": "e7bd",
"unicode_decimal": 59325
},
{
"icon_id": "4550494",
"name": "箭头",
"font_class": "jiantou",
"unicode": "e7bc",
"unicode_decimal": 59324
},
{
"icon_id": "17078373",
"name": "自用试卷",
"font_class": "ziyongshijuan",
"unicode": "e7b3",
"unicode_decimal": 59315
},
{
"icon_id": "17078374",
"name": "已公开试卷",
"font_class": "yigongkaishijuan",
"unicode": "e7bb",
"unicode_decimal": 59323
},
{
"icon_id": "17077771",
"name": "视频",
"font_class": "shipin",
"unicode": "e7b4",
"unicode_decimal": 59316
},
{
"icon_id": "17077772",
"name": "实训",
"font_class": "shixun2",
"unicode": "e7be",
"unicode_decimal": 59326
},
{
"icon_id": "17060498",
"name": "放大",
"font_class": "fangda2",
"unicode": "e7ba",
"unicode_decimal": 59322
},
{
"icon_id": "17060439",
"name": "开启防作弊",
"font_class": "fangzuobi",
"unicode": "e7b9",
"unicode_decimal": 59321
},
{
"icon_id": "17027771",
"name": "闹钟",
"font_class": "shizhong",
"unicode": "e7b8",
"unicode_decimal": 59320
},
{
"icon_id": "16923000",
"name": "上传视频 (1)",
"font_class": "shangchuanshipin1",
"unicode": "e7b7",
"unicode_decimal": 59319
},
{
"icon_id": "16922942",
"name": "对勾",
"font_class": "duigou1",
"unicode": "e7b2",
"unicode_decimal": 59314
},
{
"icon_id": "16922946",
"name": "链接 (1)",
"font_class": "lianjie1",
"unicode": "e7b5",
"unicode_decimal": 59317
},
{
"icon_id": "16922947",
"name": "章节",
"font_class": "zhangjie",
"unicode": "e7b6",
"unicode_decimal": 59318
},
{
"icon_id": "16771382",
"name": "模版管理2",
"font_class": "mobanguanli2",
"unicode": "e7b1",
"unicode_decimal": 59313
},
{
"icon_id": "16771348",
"name": "分组作业",
"font_class": "fenzuzuoye2",
"unicode": "e7b0",
"unicode_decimal": 59312
},
{
"icon_id": "16771344",
"name": "毕业作业",
"font_class": "biyezuoye1",
"unicode": "e7af",
"unicode_decimal": 59311
},
{
"icon_id": "16771343",
"name": "统计",
"font_class": "tongji3",
"unicode": "e7ae",
"unicode_decimal": 59310
},
{
"icon_id": "16771339",
"name": "签到",
"font_class": "qiandao1",
"unicode": "e7ad",
"unicode_decimal": 59309
},
{
"icon_id": "16771338",
"name": "分班",
"font_class": "fenban2",
"unicode": "e7ac",
"unicode_decimal": 59308
},
{
"icon_id": "16771329",
"name": "讨论",
"font_class": "taolun2",
"unicode": "e7ab",
"unicode_decimal": 59307
},
{
"icon_id": "16771324",
"name": "视频直播",
"font_class": "shipinzhibo1",
"unicode": "e7aa",
"unicode_decimal": 59306
},
{
"icon_id": "16771321",
"name": "考试试卷",
"font_class": "kaoshishijuan1",
"unicode": "e7a9",
"unicode_decimal": 59305
},
{
"icon_id": "16771320",
"name": "考试问卷",
"font_class": "kaoshiwenjuan1",
"unicode": "e7a7",
"unicode_decimal": 59303
},
{
"icon_id": "16768917",
"name": "学习资源",
"font_class": "xuexiziyuan1",
"unicode": "e7a8",
"unicode_decimal": 59304
},
{
"icon_id": "16767292",
"name": "普通作业",
"font_class": "putongzuoye1",
"unicode": "e782",
"unicode_decimal": 59266
},
{
"icon_id": "16766394",
"name": "实训作业",
"font_class": "shixunzuoye1",
"unicode": "e7a6",
"unicode_decimal": 59302
},
{
"icon_id": "15852679",
"name": "Last updated",
"font_class": "Lastupdated",
"unicode": "e7a5",
"unicode_decimal": 59301
},
{
"icon_id": "15852678",
"name": "CONTACTS",
"font_class": "CONTACTS",
"unicode": "e7a4",
"unicode_decimal": 59300
},
{
"icon_id": "15852677",
"name": "SPONSORS",
"font_class": "SPONSORS",
"unicode": "e7a3",
"unicode_decimal": 59299
},
{
"icon_id": "15852676",
"name": "FINAL REPORTS",
"font_class": "FINALREPORTS",
"unicode": "e7a2",
"unicode_decimal": 59298
},
{
"icon_id": "15852675",
"name": "STEERING COMMITTEE",
"font_class": "STEERINGCOMMITTEE",
"unicode": "e7a1",
"unicode_decimal": 59297
},
{
"icon_id": "15852674",
"name": "ORGANIZING ICSE - MOU",
"font_class": "ORGANIZINGICSE-MOU",
"unicode": "e7a0",
"unicode_decimal": 59296
},
{
"icon_id": "15852673",
"name": "INFLUENTIAL PAPERS",
"font_class": "INFLUENTIALPAPERS",
"unicode": "e79f",
"unicode_decimal": 59295
},
{
"icon_id": "15852672",
"name": "BIBLIOGRAPHIES",
"font_class": "BIBLIOGRAPHIES",
"unicode": "e79e",
"unicode_decimal": 59294
},
{
"icon_id": "15852671",
"name": "PROCEEDINGS",
"font_class": "PROCEEDINGS",
"unicode": "e79d",
"unicode_decimal": 59293
},
{
"icon_id": "15852670",
"name": "HISTORY",
"font_class": "HISTORY",
"unicode": "e79c",
"unicode_decimal": 59292
},
{
"icon_id": "15852669",
"name": "CONDUCT & SAFETY",
"font_class": "CONDUCTSAFETY",
"unicode": "e79b",
"unicode_decimal": 59291
},
{
"icon_id": "15852667",
"name": "EDI STATEMENT",
"font_class": "EDISTATEMENT",
"unicode": "e79a",
"unicode_decimal": 59290
},
{
"icon_id": "15852666",
"name": "MAILING LIST",
"font_class": "MAILINGLIST",
"unicode": "e799",
"unicode_decimal": 59289
},
{
"icon_id": "15852665",
"name": "HOME",
"font_class": "HOME",
"unicode": "e798",
"unicode_decimal": 59288
},
{
"icon_id": "15792809",
"name": "准备中",
@ -131,13 +684,6 @@
"unicode": "e783",
"unicode_decimal": 59267
},
{
"icon_id": "15590916",
"name": "普通作业",
"font_class": "putongzuoye1",
"unicode": "e782",
"unicode_decimal": 59266
},
{
"icon_id": "15590913",
"name": "实训作业",

View File

@ -20,6 +20,243 @@ Created by iconfont
/>
<missing-glyph />
<glyph glyph-name="zhuye1" unicode="&#59364;" d="M992.192 559.616L546.816 882.304A73.6 73.6 0 0 1 503.808 896c-15.104 0-30.336-4.48-42.88-13.568L27.712 570.368a62.272 62.272 0 0 1-26.752-50.432V-128h1017.792V509.44a62.08 62.08 0 0 1-26.496 50.176z m-363.584-615.616H390.976V256.576h237.632v-312.576z m311.808 0h-233.6V292.608c0 19.84-17.472 35.968-39.04 35.968H351.808c-21.632 0-39.168-16.064-39.168-35.968v-348.608h-233.6v572.16L503.808 821.76l436.608-316.416v-561.408z" horiz-adv-x="1024" />
<glyph glyph-name="xiangmujianjie" unicode="&#59367;" d="M399.847619-93.866667H175.542857C97.52381-93.866667 34.133333-30.47619 34.133333 47.542857V744.838095C34.133333 822.857143 97.52381 886.247619 175.542857 886.247619h653.409524c78.019048 0 141.409524-63.390476 141.409524-141.409524v-263.314285h-78.019048V744.838095c0 34.133333-29.257143 63.390476-63.390476 63.390476H175.542857c-34.133333 0-63.390476-29.257143-63.390476-63.390476v-702.171428c0-34.133333 29.257143-63.390476 63.390476-63.390477h229.180953v-73.142857zM785.066667 408.380952l-180.419048 146.285715L414.47619 408.380952V822.857143h78.019048v-253.561905L604.647619 652.190476 707.047619 569.295238V822.857143h78.019048zM575.390476-15.847619h385.219048v-78.019048h-385.219048zM575.390476 369.371429h385.219048v-78.019048h-385.219048zM575.390476 164.571429h385.219048v-78.019048h-385.219048z" horiz-adv-x="1024" />
<glyph glyph-name="canyuchengyuan" unicode="&#59366;" d="M307.2-118.690909H116.363636c-60.509091 0-107.054545 46.545455-107.054545 107.054545v791.272728C9.309091 840.145455 55.854545 886.690909 116.363636 886.690909h758.690909c60.509091 0 107.054545-46.545455 107.054546-107.054545v-167.563637h-74.472727V779.636364c0 18.618182-13.963636 32.581818-32.581819 32.581818H116.363636c-18.618182 0-32.581818-13.963636-32.581818-32.581818v-791.272728c0-18.618182 13.963636-32.581818 32.581818-32.581818h190.836364v-74.472727zM716.8 123.345455c-102.4 0-190.836364 83.781818-190.836364 190.836363 0 102.4 83.781818 190.836364 190.836364 190.836364s190.836364-83.781818 190.836364-190.836364c0-102.4-83.781818-190.836364-190.836364-190.836363z m0 307.2c-65.163636 0-116.363636-51.2-116.363636-116.363637S651.636364 197.818182 716.8 197.818182s116.363636 51.2 116.363636 116.363636-51.2 116.363636-116.363636 116.363637zM1014.690909-114.036364h-74.472727c0 130.327273-107.054545 237.381818-237.381818 237.381819S465.454545 16.290909 465.454545-114.036364H386.327273c0 172.218182 139.636364 311.854545 311.854545 311.854546s316.509091-139.636364 316.509091-311.854546zM162.909091 695.854545h386.327273v-74.472727H162.909091zM162.909091 453.818182h246.690909v-74.472727H162.909091z" horiz-adv-x="1024" />
<glyph glyph-name="shiyongwendang" unicode="&#59365;" d="M861.090909-118.690909H162.909091c-69.818182 0-130.327273 55.854545-130.327273 121.018182V719.127273C32.581818 784.290909 93.090909 840.145455 162.909091 840.145455h121.018182c18.618182 0 37.236364-18.618182 37.236363-37.236364s-18.618182-37.236364-37.236363-37.236364H162.909091c-32.581818 0-55.854545-23.272727-55.854546-46.545454v-716.8c0-27.927273 23.272727-46.545455 55.854546-46.545455h698.181818c32.581818 0 55.854545 23.272727 55.854546 46.545455V719.127273c0 27.927273-23.272727 46.545455-55.854546 46.545454h-116.363636c-18.618182 0-37.236364 18.618182-37.236364 37.236364s18.618182 37.236364 37.236364 37.236364H861.090909c69.818182 0 130.327273-55.854545 130.327273-121.018182v-716.8c0-65.163636-60.509091-121.018182-130.327273-121.018182zM242.036364 584.145455h539.927272v-74.472728H242.036364zM242.036364 211.781818h539.927272v-74.472727H242.036364zM242.036364 397.963636h539.927272v-74.472727H242.036364zM581.818182 779.636364H442.181818c-27.927273 0-46.545455 18.618182-46.545454 46.545454s18.618182 46.545455 46.545454 46.545455h139.636364c27.927273 0 46.545455-18.618182 46.545454-46.545455s-18.618182-46.545455-46.545454-46.545454z" horiz-adv-x="1024" />
<glyph glyph-name="daimaku" unicode="&#59353;" d="M1024-128H0V561.664L512 896l512-334.336zM72-53.184h880V521.984L512 807.744 72 521.984zM307.136 105.344l-60.928 40.896L376.576 293.76l-146.56 128.768 55.552 47.616 193.664-171.008z m206.784 96h254.592v-67.072H514.048z" horiz-adv-x="1024" />
<glyph glyph-name="forc" unicode="&#59354;" d="M796.376006 894.867675a171.32651 171.32651 0 0 0 169.950598-142.687158 169.695799 169.695799 0 0 0-116.035236-188.550889 342.60206 342.60206 0 0 0-340.410792-291.5914h-229.318648v-66.24761a170.256356 170.256356 0 0 0 114.353565-150.229194l0.305759-10.19194a171.683228 171.683228 0 1 0-229.318648 160.268255V564.750742a169.695799 169.695799 0 0 0-112.111339 188.907606 172.345704 172.345704 0 0 0 339.034881 0 169.695799 169.695799 0 0 0-112.111339-189.009526v-179.378142h229.318648a228.605212 228.605212 0 0 1 224.630355 181.263651 169.491961 169.491961 0 0 0-107.423046 189.672002A171.32651 171.32651 0 0 0 796.376006 894.867675zM223.283225 102.138589a56.616226 56.616226 0 1 1 57.329662-56.616226 56.972944 56.972944 0 0 1-57.329662 56.616226z m0 679.496634a56.616226 56.616226 0 1 1 57.329662-56.616226 56.972944 56.972944 0 0 1-57.329662 56.616226z m573.092781 0a56.616226 56.616226 0 1 1 57.329662-56.616226 56.972944 56.972944 0 0 1-57.329662 56.616226z" horiz-adv-x="1024" />
<glyph glyph-name="dianzan3" unicode="&#59357;" d="M1068.085662 794.870057a352.143618 352.143618 0 0 1-482.689072 10.604533 352.143618 352.143618 0 0 1-482.689072-10.604533 343.733127 343.733127 0 0 1-3.364196-486.784615l3.217927-3.217927 404.288665-400.119987a109.702062 109.702062 0 0 1 155.04558-1.462694l1.462695 1.389559 404.288665 399.827448a343.733127 343.733127 0 0 1 3.437331 486.784616l-3.437331 3.510466z m-52.364451-438.808247l-404.21553-399.754313a36.567354 36.567354 0 0 0-51.706239 0L154.998834 356.427484a271.476036 271.476036 0 0 0-2.559714 384.396024l2.559714 2.559715a277.91189 277.91189 0 0 0 380.739289 6.21645l49.731602-42.783804 49.292793 42.710669a277.91189 277.91189 0 0 0 380.885558-7.898548 271.69544 271.69544 0 0 0 0.731347-384.688563l-0.658212-0.585078z" horiz-adv-x="1171" />
<glyph glyph-name="lichengbei" unicode="&#59358;" d="M677.82464 694.784a97.6 97.6 0 1 0 0-192h-345.6a97.6 97.6 0 1 0 0 192z m0-68.608h-345.6a27.904 27.904 0 1 1 0-54.848h345.6a27.904 27.904 0 1 1 0 54.848zM521.28064-128a39.232 39.232 0 0 0-13.696 2.496l-323.264 120.512C173.12064-1.28 63.87264 37.696 63.87264 122.56V673.344a21.632 21.632 0 0 0 0 2.752 24.96 24.96 0 0 1 0 3.072C64.12864 802.752 256.44864 896 512.12864 896s448-93.248 448-216.832a22.016 22.016 0 0 0 0-2.816 24.192 24.192 0 0 1 0-2.944v-550.848c0-66.752-78.912-111.616-94.784-119.872a35.072 35.072 0 0 0-4.032-1.856l-325.632-126.144a39.36 39.36 0 0 0-14.208-2.624zM140.92864 671.68v-549.12c0-23.872 45.44-48.96 69.824-57.088l310.528-115.776 309.376 119.872c25.152 13.888 52.608 38.976 52.608 52.992V671.424v6.08 3.52c-2.88 66.496-160.64 140.096-371.2 140.096S143.55264 747.52 140.92864 680.96a41.024 41.024 0 0 0 0-9.344zM741.69664 233.344H281.98464a34.048 34.048 0 1 0 0 65.664h459.712a34.048 34.048 0 1 0 0-65.664z" horiz-adv-x="1024" />
<glyph glyph-name="quxiaodianzan" unicode="&#59359;" d="M511.851263 19.736907a32.884449 32.884449 0 0 0 16.186315-4.222516l247.784965-137.999528a45.871887 45.871887 0 0 1 48.047124 2.687056 43.504719 43.504719 0 0 1 17.84973 42.673011L793.352386 221.330098a36.211281 36.211281 0 0 0 9.596629 30.901146l208.310831 215.092449a43.568696 43.568696 0 0 1 10.108449 44.208471 44.272449 44.272449 0 0 1-35.507528 29.749551l-284.124201 43.760629a34.291955 34.291955 0 0 0-25.591011 19.641101L552.540971 869.998253a44.78427 44.78427 0 0 1-81.123505 0l-123.476629-265.250831a34.291955 34.291955 0 0 0-25.591011-19.641101l-284.188179-43.760629a44.78427 44.78427 0 0 1-35.507528-29.813528 43.440741 43.440741 0 0 1 10.108449-44.080516l208.246853-215.156427a36.275258 36.275258 0 0 0 9.59663-30.901146l-48.303034-298.327212a43.568696 43.568696 0 0 1 17.977685-42.800966 45.80791 45.80791 0 0 1 48.047124-2.495124l247.65701 137.871573A32.820472 32.820472 0 0 0 511.851263 19.736907z" horiz-adv-x="1024" />
<glyph glyph-name="fork2" unicode="&#59360;" d="M808.294199 889.365588a139.04645 139.04645 0 0 1-140.75293-137.466377 137.655986 137.655986 0 0 1 90.506599-128.365155v-33.876771L506.626604 274.021842 255.268544 589.657285v33.876771a137.655986 137.655986 0 0 1 90.506598 128.365155 140.816133 140.816133 0 1 1-181.013197-131.71491v-42.219559a53.406478 53.406478 0 0 1 11.692542-33.118336l284.918818-357.855001v-41.208312a140.816133 140.816133 0 1 1 90.506598 0v41.208312l284.918818 357.855001a53.406478 53.406478 0 0 1 11.692542 33.118336v42.219559a137.08716 137.08716 0 0 1-40.197064 269.118084z m-663.630787-137.466377a60.3588 60.3588 0 1 0 60.358801-58.905133 59.600365 59.600365 0 0 0-60.358801 58.905133z m422.321992-736.314158A60.3588 60.3588 0 1 0 506.626604 74.490186a59.600365 59.600365 0 0 0 60.3588-58.905133z m241.308795 677.409025a58.905133 58.905133 0 1 0 60.3588 58.905133 59.600365 59.600365 0 0 0-60.3588-58.905133z" horiz-adv-x="1024" />
<glyph glyph-name="hebingqingqiu1" unicode="&#59361;" d="M724.710387 544.712656a22.806357 22.806357 0 0 0-37.511352-17.291984L492.221699 691.626445a22.602121 22.602121 0 0 0 0 34.583969L687.199035 890.416187a22.874436 22.874436 0 0 0 32.133137-2.655069 22.602121 22.602121 0 0 0 5.378215-14.636916v-123.494723h77.473537a145.484136 145.484136 0 0 0 145.892608-142.965225v-374.432733a182.38278 182.38278 0 1 0-82.034808 0V604.553815a63.653565 63.653565 0 0 1-62.768542 63.449328h-78.562795z m182.382781-389.00157a99.735264 99.735264 0 1 1 100.279893-99.735265 100.007579 100.007579 0 0 1-100.279893 99.667186zM182.599868 890.143872a181.293521 181.293521 0 0 0 40.847208-358.09385v-299.546187a182.38278 182.38278 0 1 0-82.034808 0v299.546187a181.293521 181.293521 0 0 0 40.847207 358.09385z m0-734.500865a99.735264 99.735264 0 1 1 100.279894-99.735264 100.007579 100.007579 0 0 1-100.279894 99.735264z m0 652.942608a99.735264 99.735264 0 1 1 100.279894-99.735264 100.007579 100.007579 0 0 1-100.279894 99.599107z" horiz-adv-x="1092" />
<glyph glyph-name="renwu" unicode="&#59362;" d="M983.055019-128H40.975019a42.325333 42.325333 0 0 0-40.96 43.281067V754.2784a42.325333 42.325333 0 0 0 40.96 43.4176h214.903466v-77.277867H73.196885v-771.413333h877.636267v771.413333h-182.749867V797.764267H983.055019a42.325333 42.325333 0 0 0 40.96-43.4176v-838.929067a42.3936 42.3936 0 0 0-40.96-43.4176z m-217.770667 441.7536L427.023019 72.704a39.799467 39.799467 0 0 0-58.231467 0l-132.642133 139.810133a44.714667 44.714667 0 0 0-12.014934 30.651734 42.325333 42.325333 0 0 0 40.96 43.4176 39.936 39.936 0 0 0 29.149867-12.765867l103.492267-109.226667 309.111466 210.466134a40.072533 40.072533 0 0 0 29.0816 12.629333 42.257067 42.257067 0 0 0 40.96-43.4176 44.032 44.032 0 0 0-11.810133-30.5152z m-362.973867 484.010667h219.477334v-77.277867H402.310485z m0 0M49.644885 502.3744h875.042134v-98.372267H49.644885zM312.130219 896h35.0208c9.6256 0 17.544533-10.990933 17.544533-24.644267v-196.744533c0-13.653333-7.850667-24.644267-17.544533-24.644267h-35.0208c-9.6256 0-17.544533 10.990933-17.544534 24.644267V871.355733c0.136533 13.653333 7.645867 24.644267 17.544534 24.644267zM662.201685 896h35.0208c9.6256 0 17.544533-10.990933 17.544534-24.644267v-196.744533c0-13.653333-7.850667-24.644267-17.544534-24.644267H662.201685c-9.6256 0-17.544533 10.990933-17.544533 24.644267V871.355733c0 13.653333 7.918933 24.644267 17.544533 24.644267z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="tongzhi" unicode="&#59363;" d="M965.27314 383.870204a285.184828 285.184828 0 0 1-146.24863 248.622671c-7.312431 0-14.624863 7.312431-21.937295 7.312432a34.075931 34.075931 0 0 1-36.562157-35.538418 36.562157 36.562157 0 0 1 14.624863-28.445358A211.183021 211.183021 0 0 0 884.836393 391.182636a207.234308 207.234308 0 0 0-116.998904-191.951327 36.562157 36.562157 0 0 1-14.624863-28.445358 34.075931 34.075931 0 0 1 36.562158-35.538417 25.739759 25.739759 0 0 1 14.624863 7.312431A266.757501 266.757501 0 0 1 965.27314 383.870204z m-43.874589 419.441071c-7.312431 0-14.624863 7.312431-21.937295 7.312431a34.075931 34.075931 0 0 1-36.562157-35.538417c0-14.186117 7.312431-21.3523 21.937294-28.445358a416.004227 416.004227 0 0 0 0-725.173831c-14.624863-7.312431-21.937294-14.186117-21.937294-28.445359a34.075931 34.075931 0 0 1 36.562157-35.538417 27.348494 27.348494 0 0 1 21.937295 7.312432 478.159895 478.159895 0 0 1 0 838.88214zM87.781361 618.453007h175.498356c21.937294 0 58.499452 7.312431 212.060513 120.874492a557.865398 557.865398 0 0 0 80.436746 56.890717v-440.79337a36.562157 36.562157 0 0 1 73.124315 0v504.557773a38.97526 38.97526 0 0 1-21.937294 35.538417 111.222083 111.222083 0 0 1-51.187021-7.312432L424.153209 789.125158a567.810305 567.810305 0 0 0-160.873492-99.522193h-219.372945c-29.249726 0-43.874589-14.186117-43.874589-35.538417v-540.315563a34.075931 34.075931 0 0 1 36.562157-35.538417H292.529442c7.312431 0 36.562157-14.186117 146.24863-99.522193L555.776976-120.687569c7.312431-7.312431 14.624863-7.312431 29.249726-7.312431 7.312431 0 14.624863 0 14.624863 7.312431a38.97526 38.97526 0 0 1 21.937295 35.538418v191.731953A33.198439 33.198439 0 0 1 585.026702 135.247534a34.075931 34.075931 0 0 1-36.562157-35.538417v-120.874493a333.373752 333.373752 0 0 0-51.187021 49.797659c-138.936198 113.781434-175.498356 120.874493-197.43565 120.874492H109.718655c-21.937294 0-29.249726 7.312431-29.249726 28.445359V590.007648c-14.624863 21.3523-7.312431 28.445358 7.312432 28.445359z" horiz-adv-x="1170" />
<glyph glyph-name="jinbi" unicode="&#59333;" d="M0 384c0-283.29 228.71-512 512-512s512 228.71 512 512S795.29 896 512 896 0 667.29 0 384zM119.45 384c0-139.93 75.11-269.67 194.56-337.92 119.5-68.25 269.67-71.68 392.55 0S901.12 244.07 901.12 384c0 215.04-174.08 392.55-392.55 392.55-218.42 0-389.12-177.51-389.12-392.55zM904.55 384c0 85.35-27.34 167.27-78.54 232.09-61.44 47.82-146.74 75.11-228.66 75.11A390.4 390.4 0 0 1 204.8 298.65c0-85.3 27.29-167.22 78.49-232.09 61.44-47.77 146.79-78.49 232.14-78.49A394.854 394.854 0 0 1 904.55 384zM552.96 609.28l85.35-170.65 180.89-34.15-126.31-139.93 20.48-187.75-160.41 81.92-167.27-81.92 27.34 187.75-126.31 139.93 177.51 34.15 88.73 170.65M512 650.24l92.16-167.27 174.08-37.53-126.31-139.93 20.48-187.75L512 203.11l-160.41-85.35 20.48 187.75-126.31 139.93 174.08 37.53L512 650.24" horiz-adv-x="1024" />
<glyph glyph-name="weikaishexiangtou1" unicode="&#59352;" d="M516.877174 39.855494A428.075239 428.075239 0 1 1 94.646693 467.930733a425.046204 425.046204 0 0 1 422.230481-428.075239z m0 781.149854a354.098514 354.098514 0 1 0-346.7819-354.098514A350.57886 350.57886 0 0 0 516.877174 820.984017z m0 0M937.721124 173.026399a45.179557 45.179557 0 0 1-42.065197-79.650834c30.780973-16.553039 37.9696-28.967818 38.993499-31.996854-3.071698-29.991717-149.787938-98.273003-422.699768-98.273003-268.773571 0-419.606739 70.393078-421.675868 98.273003 0 2.133124 7.188626 14.483909 36.9457 31.036948a45.712838 45.712838 0 0 1 16.425052 62.073896 44.795595 44.795595 0 0 1-59.514148 17.576938C15.401152 134.822156 0 91.370429 0 61.378711c0-130.333851 265.723204-189.314717 511.949658-189.314717s511.949658 58.959536 511.949659 189.314717c0 29.927724-14.355922 73.379451-86.178193 111.647688zM511.949658 728.534441a222.420795 222.420795 0 1 1 220.586309-222.399464A221.162252 221.162252 0 0 1 511.949658 728.534441z m-75.917868-223.53002a91.041714 91.041714 0 1 0 90.27379 91.020383 91.468339 91.468339 0 0 0-90.27379-91.020383z m0 0M983.668606 837.409068L50.640354-73.925317a13.694653 13.694653 0 0 0-19.006131 0l-21.331236 20.883279a12.94806 12.94806 0 0 0 0 18.558176L943.331239 876.850523a13.694653 13.694653 0 0 0 19.006131 0l21.331236-20.88328a12.94806 12.94806 0 0 0 0-18.558175z" horiz-adv-x="1024" />
<glyph glyph-name="guankacaidan" unicode="&#59342;" d="M0-128V896h1024v-1024H0z m731.428571 694.857143H292.571429v-36.571429h438.857142v36.571429z m0-164.571429H292.571429v-36.571428h438.857142v36.571428z m0-164.571428H292.571429v-36.571429h438.857142v36.571429z" horiz-adv-x="1024" />
<glyph glyph-name="zhongzhishixun" unicode="&#59349;" d="M758.328889 384a108.544 108.544 0 1 1-109.226667-113.777778h1.137778a110.876444 110.876444 0 0 1 108.088889 113.777778z m-108.088889 512a499.939556 499.939556 0 0 1-487.537778-512H0l216.746667-227.555556 216.746666 227.555556H270.791111a380.074667 380.074667 0 1 0 758.897778 5.688889 406.243556 406.243556 0 0 0-205.368889-359.651556 364.544 364.544 0 0 0-394.24 29.866667l-76.8-81.92a468.707556 468.707556 0 0 1 576.284444-13.198222A525.198222 525.198222 0 0 1 1115.022222 538.112 490.439111 490.439111 0 0 1 650.24 896z" horiz-adv-x="1138" />
<glyph glyph-name="fuzhiniantie" unicode="&#59350;" d="M872.106667 896H397.084444a151.552 151.552 0 0 1-151.324444-151.722667v-475.136a151.552 151.552 0 0 1 151.324444-151.665777h475.022223A152.007111 152.007111 0 0 1 1024 269.141333V744.277333A152.064 152.064 0 0 1 872.106667 896z m62.008889-626.858667a61.781333 61.781333 0 0 0-62.008889-62.065777H397.084444a62.179556 62.179556 0 0 0-62.008888 62.065777V744.277333a62.179556 62.179556 0 0 0 62.008888 62.122667h475.022223a61.838222 61.838222 0 0 0 62.008889-62.122667v-475.136z m-245.191112-245.475555a62.122667 62.122667 0 0 0-62.008888-62.065778H151.893333a62.577778 62.577778 0 0 0-62.577777 62.065778V498.801778a62.577778 62.577778 0 0 0 62.577777 62.122666h35.271111V650.524444h-35.271111A152.064 152.064 0 0 1 0 498.801778v-475.136A152.007111 152.007111 0 0 1 151.893333-128h475.022223a151.552 151.552 0 0 1 151.324444 151.665778v35.669333h-89.315556v-35.669333z" horiz-adv-x="1024" />
<glyph glyph-name="gongxiangzhuomian" unicode="&#59351;" d="M942.084119 257.42158A92.842512 92.842512 0 0 1 1024.003982 353.449864V796.386015A98.531391 98.531391 0 0 1 928.999696 895.998293H282.742995A94.435398 94.435398 0 0 1 187.738709 801.107785l81.919864 0.625777h672.994434v-450.04725z m-163.839727 490.950293H95.009975A98.58828 98.58828 0 0 1 0.005689 648.759594v-480.312088a92.44429 92.44429 0 0 1 95.004286-92.501179h299.235057v-141.08421H209.925339a33.393722 33.393722 0 0 1-23.893293-33.223055 29.183951 29.183951 0 0 1 23.893293-29.639062h452.265913a29.695951 29.695951 0 0 1 24.462181 29.639062 33.791944 33.791944 0 0 1-24.462181 33.223055H469.907128v141.08421h308.337264a92.44429 92.44429 0 0 1 95.004286 92.501179V648.759594A98.190059 98.190059 0 0 1 778.244392 748.087429z m13.65331-578.103926H81.356664v483.55475h710.541038v-483.55475zM473.889344 477.979434l-12.515535-27.875509s-10.808871-27.249732 24.462181-21.333297l98.986502 23.722627a17.91997 17.91997 0 0 1 12.515535 26.055067l-54.044355 97.279838a17.066638 17.066638 0 0 1-27.875509-2.958217l-11.946647-27.875509s-182.044141 74.694987-225.848512-120.376688c0 0 48.924363 112.070924 196.26634 53.361688zM412.449446 350.491647l11.946647 27.875509s9.671095 27.249732-24.462182 20.76441l-98.986501-26.111957a17.46486 17.46486 0 0 1-11.946647-26.055067l56.319906-95.459397a16.725305 16.725305 0 0 1 27.306621 3.527106l11.377759 27.875509s183.750805-69.973217 222.435185 126.293122c0.568888 0-44.942147-113.265589-193.990788-58.709235z" horiz-adv-x="1024" />
<glyph glyph-name="tuichuquanping" unicode="&#59348;" d="M604.728889-9.614222l-3.413333 304.014222 304.355555-3.185778-115.484444-115.2L1024-57.628444 953.457778-128l-233.244445 233.585778z m-185.457778 0l2.844445 304.014222-303.786667-3.185778 115.484444-115.2L0-57.628444 70.542222-128l233.244445 233.585778z m185.457778 787.228444l-3.413333-304.014222 304.355555 3.185778-115.484444 115.2L1024 825.628444 953.457778 896l-233.244445-233.585778z m-185.457778 0l2.844445-304.014222-303.786667 3.185778 115.484444 115.2L0 825.628444 70.542222 896l233.244445-233.585778z" horiz-adv-x="1024" />
<glyph glyph-name="quanping" unicode="&#59346;" d="M731.022222 896l116.053334-116.224-225.848889-226.417778 56.888889-56.888889 225.848888 226.417778L1024 602.510222V896h-292.977778z m-43.804444-620.088889l-56.888889-56.888889L853.333333-5.233778 731.591111-128H1024v294.172444l-113.777778-114.232888-223.004444 224.199111zM336.782222 491.633778l56.888889 56.888889L170.666667 772.778667 292.408889 895.601778H0v-294.172445L113.777778 715.662222z m9.102222-220.16l-225.848888-226.474667L0 165.432889V-128h292.977778l-116.053334 116.224 225.848889 226.417778z" horiz-adv-x="1024" />
<glyph glyph-name="fuzhibanbenkudizhi1" unicode="&#59347;" d="M796.444444-128H227.555556a170.666667 170.666667 0 0 0-170.666667 170.666667V668.444444a170.666667 170.666667 0 0 0 170.666667 170.666667v-113.777778a56.888889 56.888889 0 0 1-56.888889-56.888889v-625.777777a56.888889 56.888889 0 0 1 56.888889-56.888889h568.888888a56.888889 56.888889 0 0 1 56.888889 56.888889V668.444444a56.888889 56.888889 0 0 1-56.888889 56.888889V839.111111a170.666667 170.666667 0 0 0 170.666667-170.666667v-625.777777a170.666667 170.666667 0 0 0-170.666667-170.666667zM284.444444 896h455.111112v-341.333333H284.444444V896z m113.777778-227.555556h227.555556V782.222222H398.222222v-113.777778z" horiz-adv-x="1024" />
<glyph glyph-name="shiyanhuanjingdaojishi" unicode="&#59345;" d="M512 896a512 512 0 1 1 512-512 513.536 513.536 0 0 1-512 512z m0-953.628444A441.628444 441.628444 0 1 0 953.457778 384 442.197333 442.197333 0 0 0 512-57.628444z m153.6 230.4a38.912 38.912 0 0 1 51.2 0 39.822222 39.822222 0 0 1 0 51.2L556.942222 396.8c0 6.371556-6.826667 6.371556-6.826666 12.8v307.2A40.903111 40.903111 0 0 1 512 755.2a41.472 41.472 0 0 1-38.684444-38.4v-326.428444a59.221333 59.221333 0 0 1 19.342222-44.771556l172.942222-172.828444z" horiz-adv-x="1024" />
<glyph glyph-name="vncshixunjiemian-gongjulan" unicode="&#59344;" d="M1069.401234 738.420432h-164.474038V817.201576A80.253091 80.253091 0 0 1 823.010166 895.982721H328.948076a80.253091 80.253091 0 0 1-81.917031-78.781145v-78.781144H82.557007A80.82907 80.82907 0 0 1 0 659.639288v-708.838305A80.82907 80.82907 0 0 1 82.557007-127.980161h986.844227A80.82907 80.82907 0 0 1 1151.958242-49.199017V659.703286a80.82907 80.82907 0 0 1-82.557008 78.717146zM328.948076 817.201576h494.06209v-78.781144H328.948076V817.201576z m740.453158-866.400593H82.557007V265.861563h369.906591v-39.358574a80.82907 80.82907 0 0 1 82.557008-78.781144h81.91703a80.82907 80.82907 0 0 1 82.557007 78.781144v39.358574h369.906591v-315.06058z m-534.380628 275.702006V384.00128h81.91703v-157.562288H535.020606z m164.474037 118.139718V384.00128a80.82907 80.82907 0 0 1-82.557007 78.781144H535.020606A80.82907 80.82907 0 0 1 452.463598 384.00128v-39.358573H82.557007V659.703286h986.844227v-315.060579h-369.906591z" horiz-adv-x="1152" />
<glyph glyph-name="vncshixunjiemian-zhankai" unicode="&#59343;" d="M359.799168 896h204.8a51.2 51.2 0 0 0 51.2-51.2v-921.6a51.2 51.2 0 0 0-51.2-51.2H359.799168V896zM410.999168 473.6m12.8 0l0 0q12.8 0 12.8-12.8l0-153.6q0-12.8-12.8-12.8l0 0q-12.8 0-12.8 12.8l0 153.6q0 12.8 12.8 12.8ZM551.799168 396.8l-89.6-102.4V473.6l89.6-76.8" horiz-adv-x="1024" />
<glyph glyph-name="vncshixunjiemian-shouqi" unicode="&#59341;" d="M375.43616 896h204.8v-1024H375.43616a51.2 51.2 0 0 0-51.2 51.2V844.8a51.2 51.2 0 0 0 51.2 51.2zM503.43616 473.6m12.8 0l0 0q12.8 0 12.8-12.8l0-153.6q0-12.8-12.8-12.8l0 0q-12.8 0-12.8 12.8l0 153.6q0 12.8 12.8 12.8ZM388.23616 396.8l89.6-102.4V473.6l-89.6-76.8" horiz-adv-x="1024" />
<glyph glyph-name="chexiaofenzu" unicode="&#59338;" d="M1228.790784-127.995733H51.199616a50.602287 50.602287 0 0 0-51.199616 49.919625V846.076961A50.602287 50.602287 0 0 0 51.199616 895.996587h406.695616a13.3119 13.3119 0 0 0 8.53327-3.413308l187.731925-175.188019H1228.790784a50.602287 50.602287 0 0 0 51.199616-49.919626v-745.551742a50.602287 50.602287 0 0 0-51.199616-49.919625zM426.663467 384.000427v-85.332694h426.663466V384.000427z" horiz-adv-x="1280" />
<glyph glyph-name="chexiaogongxiang" unicode="&#59339;" d="M1190.570667-128h-1100.8c-59.733333 0-89.429333 24.064-89.429334 71.594667V824.405333C0.341333 871.936 30.464 896 89.770667 896h1100.8c59.733333 0 89.429333-24.064 89.429333-71.594667v-880.810666c0-47.445333-30.122667-71.594667-89.429333-71.594667zM267.434667 625.92l-9.642667-218.965333-9.130667-204.8a13.482667 13.482667 0 0 1 3.584-9.728 13.312 13.312 0 0 1 9.642667-4.096h375.466667a13.312 13.312 0 0 1 12.032 7.68 13.397333 13.397333 0 0 1-1.962667 14.250666L550.912 322.389333a10.069333 10.069333 0 0 1 1.194667 1.450667 372.650667 372.650667 0 0 0 294.997333 187.733333 276.48 276.48 0 0 0 89.941333-15.36 15.701333 15.701333 0 0 1 5.12-0.853333 14.592 14.592 0 0 1 13.482667 8.533333 11.434667 11.434667 0 0 1-2.986667 12.970667 398.421333 398.421333 0 0 1-270.165333 123.904A409.6 409.6 0 0 1 392.789333 496.64a12.117333 12.117333 0 0 1-1.962666-2.56L267.349333 626.261333z" horiz-adv-x="1280" />
<glyph glyph-name="xuanzhong1" unicode="&#59340;" d="M943.108257-127.946108h-862.270406A80.837851 80.837851 0 0 0 0-47.108257v862.270406A80.837851 80.837851 0 0 0 80.837851 896h862.270406A80.837851 80.837851 0 0 0 1023.946108 815.162149v-862.270406a80.837851 80.837851 0 0 0-80.837851-80.837851zM258.142203 434.63144l-69.574443-53.460765L459.913478 114.567444A1603.176254 1603.176254 0 0 0 835.324457 615.762118l-16.490922 37.72433v-0.377243a1722.277354 1722.277354 0 0 1-403.54255-337.201621l-157.148782 118.562181z" horiz-adv-x="1024" />
<glyph glyph-name="jingshi1" unicode="&#59337;" d="M512 896A512 512 0 1 0 0 384 512.605091 512.605091 0 0 0 512 896z m-28.392727-256a13.451636 13.451636 0 0 1-13.591273-13.963636l15.592727-328.517819a7.493818 7.493818 0 0 1 7.447273-6.981818h52.177455a7.540364 7.540364 0 0 1 7.447272 6.981818l15.546182 328.517819a13.312 13.312 0 0 1-13.591273 13.963636H483.607273z m35.514182-512a49.943273 49.943273 0 1 1-49.757091 49.943273 49.850182 49.850182 0 0 1 49.757091-49.943273z" horiz-adv-x="1024" />
<glyph glyph-name="shanchu21" unicode="&#59336;" d="M519.469714 896a192.512 192.512 0 0 1-191.780571-186.916571H85.549714a49.225143 49.225143 0 0 1 0-98.450286h53.979429v-550.729143c0-103.387429 69.485714-187.904 155.721143-187.904h438.637714c85.942857 0 155.721143 84.114286 155.721143 187.904V610.304h48.932571a49.225143 49.225143 0 0 1 0 98.450286h-227.620571A191.963429 191.963429 0 0 1 519.469714 896z m-100.132571-186.916571a100.205714 100.205714 0 0 0 200.082286 0z m-124.342857-745.033143c-30.500571 0-64.073143 39.387429-64.073143 95.853714V610.304h566.857143v-550.912c0-56.283429-33.609143-95.853714-64.073143-95.853714H295.067429z m0 0M355.300571 78.518857a48.018286 48.018286 0 0 1 42.24 52.224v297.728a43.190857 43.190857 0 1 1-84.48 0v-297.910857a47.762286 47.762286 0 0 1 42.24-52.041143z m152.905143 0a48.018286 48.018286 0 0 1 42.24 52.224v297.728a43.190857 43.190857 0 1 1-84.48 0v-297.910857a48.128 48.128 0 0 1 42.24-52.041143z m160.914286 0a48.018286 48.018286 0 0 1 42.24 52.224v297.728a43.190857 43.190857 0 1 1-84.48 0v-297.910857a47.542857 47.542857 0 0 1 42.203429-52.041143z m0 0" horiz-adv-x="1024" />
<glyph glyph-name="shoucang3" unicode="&#59335;" d="M797.52334 896A304.639238 304.639238 0 0 1 554.66528 769.706982 303.743241 303.743241 0 0 1 311.80722 896C139.775651 896 0 743.979047 0 557.39818a447.657548 447.657548 0 0 1 90.453107-252.543369c116.991708-182.82621 411.732304-409.598976 424.361606-419.028286a64.341172 64.341172 0 0 1 79.701134 0c12.799968 9.42931 306.7299 236.842075 424.361606 419.028286A447.657548 447.657548 0 0 1 1109.33056 557.39818C1109.33056 743.979047 969.554909 896 797.52334 896z" horiz-adv-x="1109" />
<glyph glyph-name="sousuo2" unicode="&#59334;" d="M475.189041-54.326884a475.163442 475.163442 0 1 0 475.163441 475.163442 475.163442 475.163442 0 0 0-475.163441-475.163442z m0 814.551273a339.387831 339.387831 0 1 1 339.38783-339.387831 339.387831 339.387831 0 0 1-339.38783 339.387831zM958.288086-127.79521a65.481526 65.481526 0 0 0-46.436079 19.250237L772.543773 30.763262a65.686316 65.686316 0 1 0 92.872156 92.872156l139.308235-139.308234a65.686316 65.686316 0 0 0-46.436078-112.122394z" horiz-adv-x="1024" />
<glyph glyph-name="guangbiao" unicode="&#59332;" d="M0 541.675558m59.054074 0l1653.514063 0q59.054074 0 59.054074-59.054074l0 0q0-59.054074-59.054074-59.054074l-1653.514063 0q-59.054074 0-59.054074 59.054074l0 0q0 59.054074 59.054074 59.054074ZM874.827048 891.629999a29.527037 29.527037 0 0 0 21.909061 0l437.000145-174.859113a29.527037 29.527037 0 0 0-10.925003-56.987181h-874.000291a29.527037 29.527037 0 0 0-10.984058 56.928127zM896.795163 73.61297a29.527037 29.527037 0 0 0-21.909061 0l-437.000146 174.859112a29.527037 29.527037 0 0 0 10.925004 56.987181h874.000291a29.527037 29.527037 0 0 0 10.984057-56.928127z" horiz-adv-x="2194" />
<glyph glyph-name="QQ" unicode="&#59331;" d="M510.72 886.016c-276.992 0-501.76-224.768-501.76-501.76s224.768-501.76 501.76-501.76 501.76 224.768 501.76 501.76S787.712 886.016 510.72 886.016z m230.912-636.672c-10.496-5.376-26.88 6.912-42.496 29.952-6.144-25.088-21.248-47.616-42.752-65.792 22.784-8.448 37.376-22.016 37.376-37.632 0-25.344-40.192-46.08-89.6-46.08-44.544 0-81.664 16.896-88.32 38.656h-10.752c-6.912-22.016-43.776-38.656-88.32-38.656-49.408 0-89.6 20.48-89.6 46.08 0 15.616 14.848 29.184 37.376 37.632-21.504 18.176-36.864 40.96-42.752 65.792-15.36-23.04-32-35.584-42.496-29.952-15.36 7.936-12.288 50.688 6.912 95.488 14.848 35.072 35.328 61.184 50.688 66.816-0.256 2.304-0.256 4.608-0.256 6.656 0 13.568 3.84 26.112 10.24 36.352v2.304c0 6.144 1.536 12.032 4.096 17.152 3.84 91.392 63.488 164.096 159.744 164.096s155.904-72.704 159.744-164.096c2.56-5.12 4.096-11.008 4.096-17.152v-2.304c6.4-10.24 10.24-22.784 10.24-36.352 0-2.304 0-4.608-0.256-6.656 15.616-5.632 35.84-31.744 50.688-66.816 18.688-44.8 21.76-87.552 6.4-95.488z" horiz-adv-x="1024" />
<glyph glyph-name="yonghu" unicode="&#59330;" d="M637.953132 347.721749c71.730695 40.298821 120.348995 116.815519 120.348995 204.542536 0 129.46256-105.705484 234.781234-235.641835 234.781234-129.936351 0-235.628532-105.318674-235.628532-234.781234 0-84.393085 45.041846-158.307516 112.302739-199.683878-152.041812-47.787376-262.605953-189.523471-262.605953-356.600721 0-5.058203 0.560772-9.956769 0.762363-14.97404l52.356438 0c-0.230244 4.986571-0.76134 9.914814-0.76134 14.97404 0 177.279612 144.855132 321.502341 322.909387 321.502341 178.054255 0 322.910411-144.222729 322.910411-321.502341 0-5.058203-0.532119-9.987468-0.775666-14.97404l52.371788 0c0.200568 5.016247 0.760317 9.914814 0.760317 14.97404C887.263268 158.068318 783.009855 295.982364 637.953132 347.721749zM339.389222 552.264285c0 100.588953 82.208327 182.423773 183.27107 182.423773 101.06479 0 183.272094-81.83482 183.272094-182.423773 0-100.589976-82.207303-182.423773-183.272094-182.423773C421.597549 369.840512 339.389222 451.674309 339.389222 552.264285z" horiz-adv-x="1024" />
<glyph glyph-name="oschina" unicode="&#59329;" d="M996.072727 211.781818C923.927273 13.963636 735.418182-128 512-128 230.4-128 0 100.072727 0 384S230.4 896 512 896c221.090909 0 411.927273-141.963636 481.745455-339.781818l-321.163637-116.363637c-23.272727 65.163636-86.109091 114.036364-160.581818 114.036364-95.418182 0-169.890909-76.8-169.890909-169.890909s76.8-169.890909 169.890909-169.890909c74.472727 0 137.309091 46.545455 160.581818 114.036364l323.490909-116.363637z" horiz-adv-x="1024" />
<glyph glyph-name="you" unicode="&#59327;" d="M972.772848 435.172848a72.405869 72.405869 0 0 0 0-102.381899L563.172848-76.809051a72.405869 72.405869 0 1 0-102.381899 102.418102l358.409051 358.40905-358.409051 358.372848a72.405869 72.405869 0 0 0 102.381899 102.381899z" horiz-adv-x="1024" />
<glyph glyph-name="zuo" unicode="&#59328;" d="M460.807241-76.807241L51.228963 332.807241a72.408429 72.408429 0 0 0 0 102.385518L460.807241 844.807241a72.408429 72.408429 0 0 0 102.421722 0 72.408429 72.408429 0 0 0 0-102.421723l-358.421722-358.421722 358.421722-358.385519a72.408429 72.408429 0 0 0 0-102.385518 72.408429 72.408429 0 0 0-102.421722 0z" horiz-adv-x="1024" />
<glyph glyph-name="bianchengyuyan" unicode="&#59325;" d="M969.386667-114.346667H259.413333C157.013333-114.346667 68.266667-32.426667 68.266667 76.8V704.853333C68.266667 814.08 150.186667 896 259.413333 896h716.8C1078.613333 896 1160.533333 814.08 1160.533333 704.853333v-634.88c0-102.4-81.92-184.32-191.146666-184.32zM259.413333 793.6c-47.786667 0-81.92-40.96-81.92-81.92V76.8c0-47.786667 40.96-81.92 81.92-81.92h716.8c47.786667 0 81.92 40.96 81.92 81.92V704.853333c0 47.786667-40.96 81.92-81.92 81.92H259.413333zM54.613333 561.493333h1112.746667v-102.4H54.613333zM273.066667 670.72m-68.266667 0a68.266667 68.266667 0 1 1 136.533333 0 68.266667 68.266667 0 1 1-136.533333 0ZM498.346667 670.72m-68.266667 0a68.266667 68.266667 0 1 1 136.533333 0 68.266667 68.266667 0 1 1-136.533333 0ZM750.933333 670.72m-68.266666 0a68.266667 68.266667 0 1 1 136.533333 0 68.266667 68.266667 0 1 1-136.533333 0ZM384.477867 62.805333c-6.826667 0-13.653333 0-20.48 6.826667l-129.706667 102.4c-6.826667 6.826667-13.653333 13.653333-13.653333 27.306667 0 6.826667 6.826667 20.48 13.653333 27.306666l129.706667 122.88c13.653333 13.653333 34.133333 13.653333 47.786666 0 13.653333-13.653333 13.653333-34.133333 0-47.786666l-102.4-95.573334 102.4-81.92c6.826667-13.653333 13.653333-34.133333 0-47.786666-6.826667-6.826667-13.653333-13.653333-27.306666-13.653334zM814.557867 62.805333c-13.653333 0-20.48 6.826667-27.306667 13.653334-13.653333 13.653333-6.826667 34.133333 6.826667 47.786666l102.4 81.92-102.4 88.746667c-13.653333 13.653333-13.653333 34.133333 0 47.786667 6.826667 20.48 27.306667 20.48 40.96 6.826666l129.706666-122.88c6.826667-6.826667 13.653333-13.653333 13.653334-27.306666 0-6.826667-6.826667-20.48-13.653334-27.306667l-129.706666-102.4c-6.826667-6.826667-13.653333-6.826667-20.48-6.826667zM471.586133 77.6192l226.986667 324.4032 55.978667-39.1168-226.986667-324.471467z" horiz-adv-x="1228" />
<glyph glyph-name="jiantou" unicode="&#59324;" d="M512 896c-281.6 0-512-230.4-512-512s230.4-512 512-512 512 230.4 512 512-230.4 512-512 512z m0-938.666667c-234.666667 0-426.666667 192-426.666667 426.666667s192 426.666667 426.666667 426.666667 426.666667-192 426.666667-426.666667-192-426.666667-426.666667-426.666667zM793.6 499.2c-17.066667 17.066667-42.666667 17.066667-59.733333 0l-221.866667-221.866667-221.866667 221.866667c-17.066667 17.066667-42.666667 17.066667-59.733333 0-17.066667-17.066667-17.066667-42.666667 0-59.733333l251.733333-251.733334c17.066667-17.066667 42.666667-17.066667 59.733334 0l251.733333 251.733334c17.066667 12.8 17.066667 42.666667 0 59.733333z" horiz-adv-x="1024" />
<glyph glyph-name="ziyongshijuan" unicode="&#59315;" d="M875.91961-115.537171H148.055415a28.572098 28.572098 0 0 0-28.572098 28.522147V854.940098A28.597073 28.597073 0 0 0 148.055415 883.512195h578.035512l178.40078-322.584975v-647.942244a28.572098 28.572098 0 0 0-28.572097-28.522147zM269.361951 248.407415v-35.665171h285.446244v35.665171z m0 99.902439v-35.665171h478.108098v35.665171z m0 107.045463v-35.715122h478.108098v35.715122z m0 99.902439v-35.715122h478.108098v35.715122zM726.065951 705.086439l178.400781-178.40078V705.086439zM726.065951 705.086439h178.400781L726.065951 883.48722z" horiz-adv-x="1024" />
<glyph glyph-name="yigongkaishijuan" unicode="&#59323;" d="M875.898246-115.487525H148.076779a28.596376 28.596376 0 0 0-28.571401 28.571401V854.966074A28.596376 28.596376 0 0 0 148.076779 883.537475h577.996439l178.396429-322.577108v-647.901466a28.596376 28.596376 0 0 0-28.571401-28.546426zM444.555011 287.68391c-60.939001 0-116.783103-34.965001-165.958879-103.945952l-1.54845-2.172825-1.423575-2.072925a35.214751 35.214751 0 0 1 0-39.960001c49.950001-71.753177 106.693203-108.116778 168.905929-108.116778 60.988951 0 116.858028 34.965001 166.008829 103.945952l1.473525 2.122875 1.44855 2.072926a35.289676 35.289676 0 0 1 0 39.960001c-49.875076 71.778152-106.818078 108.166728-168.880954 108.166727z m-175.224604 114.160728v-35.664301h478.146386v35.664301z m0 107.067828v-35.714251h478.146386V508.887491z m0 99.900002v-35.714251h478.146386V608.787493z m175.224604-518.980513a70.729202 70.729202 0 0 0-70.629302 70.654277 70.729202 70.729202 0 0 0 70.629302 70.654277 70.729202 70.729202 0 0 0 70.654277-70.654277 70.729202 70.729202 0 0 0-70.629302-70.654277z m0 113.161728a42.582376 42.582376 0 0 1-42.457501-42.457501 42.607351 42.607351 0 0 1 42.457501-42.457501 42.607351 42.607351 0 0 1 42.457501 42.457501 42.582376 42.582376 0 0 1-42.432526 42.457501zM726.073218 705.11607l178.396429-178.396429V705.11607zM726.073218 705.11607h178.396429L726.073218 883.5125z" horiz-adv-x="1024" />
<glyph glyph-name="shipin" unicode="&#59316;" d="M512.000213-127.998293a508.627426 508.627426 0 0 0-362.025309 149.972771A508.627426 508.627426 0 0 0 0.002133 383.999787a508.670092 508.670092 0 0 0 149.972771 362.067975A508.627426 508.627426 0 0 0 512.000213 895.997867a508.670092 508.670092 0 0 0 362.067976-149.972771A508.670092 508.670092 0 0 0 1023.998293 383.999787a508.627426 508.627426 0 0 0-149.972771-362.025309A508.712759 508.712759 0 0 0 512.000213-127.998293zM256.001173 492.628713v-324.64945a31.743881 31.743881 0 0 1 33.365209-31.402548h445.224997a31.743881 31.743881 0 0 1 33.365208 31.402548V492.628713zM652.202354 597.33232l75.690383-83.797019H767.999253V565.929771A31.701214 31.701214 0 0 1 734.634045 597.33232z m-111.274249 0l75.690383-83.797019h85.717012L626.645117 597.33232zM429.653855 597.33232l75.647717-83.797019h85.717012L515.328201 597.33232zM318.33694 597.33232l75.690382-83.797019h85.717012L404.053951 597.33232z m-28.970558 0A31.701214 31.701214 0 0 1 256.001173 565.929771v-52.39447h112.383579L292.737036 597.33232z m178.089998-371.795939c-15.402609 0-33.407875 6.869308-33.407874 26.197235v146.602117c0 19.327928 18.005266 26.197235 33.407874 26.197235a37.589192 37.589192 0 0 0 17.8346-4.266651l126.890191-69.11974a29.397223 29.397223 0 0 0 16.682604-26.197236 29.397223 29.397223 0 0 0-16.682604-26.197235l-126.890191-69.11974a34.133205 34.133205 0 0 0-17.8346-4.095985z" horiz-adv-x="1024" />
<glyph glyph-name="shixun2" unicode="&#59326;" d="M512-127.998676a508.600064 508.600064 0 0 0-361.930098 150.068578A508.68834 508.68834 0 0 0 0.001324 384a508.68834 508.68834 0 0 0 150.068578 361.930098A508.600064 508.600064 0 0 0 512 895.998676a508.68834 508.68834 0 0 0 361.930098-150.068578 508.68834 508.68834 0 0 0 150.068578-361.930098 508.644202 508.644202 0 0 0-150.068578-361.930098 508.68834 508.68834 0 0 0-361.930098-150.068578zM306.450187 648.826901A58.83571 58.83571 0 0 1 247.173099 589.152573V286.896803a58.83571 58.83571 0 0 1 59.277088-59.674329h137.047921l-40.739205-59.718466a20.568223 20.568223 0 0 1-7.415153-18.626159 27.321309 27.321309 0 0 1 29.616475-29.881302h174.123688a24.187524 24.187524 0 0 1 13.241345 4.413782c1.677237 0.971032 3.354474 1.942064 5.340676 2.957234a30.896472 30.896472 0 0 1 12.491002 19.906155 27.012344 27.012344 0 0 1-5.075849 21.142015l-40.739205 59.718466h133.296207A58.83571 58.83571 0 0 1 776.826901 286.896803V589.020159A78.477038 78.477038 0 0 1 706.471221 648.826901z m285.174435-290.956489a143.315491 143.315491 0 0 0-68.899132 26.482691l-12.579278 7.150326a73.842568 73.842568 0 0 0-14.830307 7.459291 73.842568 73.842568 0 0 1-14.830306 7.459291 61.792944 61.792944 0 0 1-34.559911 11.255143 92.689415 92.689415 0 0 1-69.163959-44.844022 22.598562 22.598562 0 0 0-20.347534-13.241345 28.821994 28.821994 0 0 0-20.347533 9.533769 24.893729 24.893729 0 0 0-13.594448 18.008229 22.068908 22.068908 0 0 0 6.135157 19.288226 162.515442 162.515442 0 0 0 118.730727 71.944642 115.552805 115.552805 0 0 0 62.763976-19.729605c3.398612-2.251029 6.444121-4.413782 9.136528-6.576534a71.547401 71.547401 0 0 1 20.479947-12.049624c28.424754-18.40547 41.357134-26.791655 52.700553-26.791655 9.224804 0 17.655127 5.517227 32.441296 15.580649a44.137817 44.137817 0 0 0 19.288226 4.899298 22.598562 22.598562 0 0 0 21.495117-12.358589c2.339304-9.489631 5.958605-32.441295-11.12273-41.04817a99.26595 99.26595 0 0 0-63.072941-22.377873z" horiz-adv-x="1024" />
<glyph glyph-name="fangda2" unicode="&#59322;" d="M860.115543 119.677826a480.813387 480.813387 0 1 1-84.350991-84.223573l145.256993-145.193283a59.631818 59.631818 0 1 1 84.287281 84.287281l-145.193283 145.129575zM94.840545 413.186143A387.734236 387.734236 0 1 0 482.511071 25.515617a388.116491 388.116491 0 0 0-387.670526 387.670526z m549.109657 45.552084H528.126864V574.497856a45.679502 45.679502 0 0 1-91.231585 0V458.738227H321.135649a45.615792 45.615792 0 0 1 0-91.167876H436.83157v-115.75963a45.679502 45.679502 0 0 1 91.231584 0V367.570351h115.75963a45.615792 45.615792 0 0 1 0 91.167876z" horiz-adv-x="1028" />
<glyph glyph-name="fangzuobi" unicode="&#59321;" d="M420.69248 563.665455a36.631273 36.631273 0 0 1-27.415273-9.309091 39.284364 39.284364 0 0 1-12.846545-26.717091 39.749818 39.749818 0 0 1 9.309091-28.299637 37.236364 37.236364 0 0 1 25.786182-13.265454 38.074182 38.074182 0 0 1 40.215272 36.072727 38.539636 38.539636 0 0 1-34.862545 41.611636m441.250909-348.76509a33.466182 33.466182 0 0 0-52.829091-11.450182c-13.963636 13.591273-72.843636 98.909091-72.843636 98.909091L651.325207 239.709091a31.045818 31.045818 0 0 0-43.008 6.004364L464.538298 431.336727a98.164364 98.164364 0 0 0-101.515636 6.050909 106.356364 106.356364 0 0 0-10.519273 165.841455 98.536727 98.536727 0 0 0 73.309091 25.134545 103.470545 103.470545 0 0 0 93.556364-111.429818 111.429818 111.429818 0 0 0-10.100364-38.725818l130.327273-167.563636 86.202182 64.046545a29.556364 29.556364 0 0 0 23.738181 5.399273 32.581818 32.581818 0 0 0 20.48-13.498182l50.315637-74.472727a786.944 786.944 0 0 1 81.733818 369.245091v24.855272a175.197091 175.197091 0 0 0-114.967273 130.653091H237.443025a176.872727 176.872727 0 0 0-115.29309-130.699636l-0.279273-24.808727c0-286.347636 142.382545-572.509091 390.144-705.815273a671.045818 671.045818 0 0 1 161.373091 121.856 36.119273 36.119273 0 0 0 51.618909-1.908364 44.497455 44.497455 0 0 0-4.468364-59.205818 738.304 738.304 0 0 0-191.488-139.636364 35.421091 35.421091 0 0 0-33.466182-0.558545C212.448116 18.245818 46.280844 339.456 46.280844 661.550545c0 7.214545 0 16.430545 1.070545 29.277091 0 10.379636 0.558545 19.595636 1.117091 28.485819a37.655273 37.655273 0 0 0 33.186909 37.236363A99.328 99.328 0 0 1 166.088844 855.505455V856.250182A39.284364 39.284364 0 0 0 203.883753 896h616.401454a39.144727 39.144727 0 0 0 37.981091-39.703273 99.421091 99.421091 0 0 1 84.573091-99.700363 37.469091 37.469091 0 0 0 32.861091-36.305455c0.605091-8.936727 1.117091-18.618182 1.117091-29.649454 0.512-12.846545 0.512-22.062545 0.512-29.277091a841.402182 841.402182 0 0 0-115.432727-446.324364" horiz-adv-x="1024" />
<glyph glyph-name="shizhong" unicode="&#59320;" d="M181.527 640l9.31 9.31C218.763 691.2 256 728.435 302.544 756.363c-13.963 18.618-41.89 32.581-69.818 32.581-46.545 0-83.782-37.236-83.782-79.127 0-32.582 9.31-55.854 32.582-69.818z m660.946 0l-9.31 9.31c-27.927 41.89-69.818 79.126-111.708 107.054 13.963 23.272 41.89 37.236 69.818 37.236 46.545 0 83.782-37.236 83.782-83.782 0-32.582-9.31-55.854-32.582-69.818zM521.309 765.673c-200.145 0-363.054-162.91-363.054-363.055s162.909-363.054 363.054-363.054 363.055 162.909 363.055 363.054-162.91 363.055-363.055 363.055zM679.564 332.79999999999995h-204.8V560.873h74.472v-153.6h130.328V332.79999999999995zM232.727-16.289999999999964c-13.963 0-23.272 4.654-32.582 13.963-18.618 18.618-18.618 46.545 0 65.163l97.746 93.091c18.618 18.618 46.545 18.618 65.164 0 18.618-18.618 18.618-46.545 0-65.163l-97.746-93.091c-9.309-9.31-23.273-13.964-32.582-13.964z m572.51-9.31c-13.964 0-23.273 4.655-32.582 13.964l-102.4 102.4c-18.619 18.618-18.619 46.545 0 65.163s46.545 18.618 65.163 0l102.4-102.4c18.618-18.618 18.618-46.545 0-65.163-9.309-9.31-18.618-13.964-32.582-13.964z" horiz-adv-x="1024" />
<glyph glyph-name="shangchuanshipin1" unicode="&#59319;" d="M547.584-62.272H0V896h958.272v-581.888H889.6V827.52H68.48V6.4h479.104z m0 0M844.928 16.192h179.2l-242.752 330.432-242.752-330.432h162.176v-144.256h144.256z m0 0l-222.464 396.8-292.16 229.312v-459.136z" horiz-adv-x="1024" />
<glyph glyph-name="duigou1" unicode="&#59314;" d="M1155.765578 895.525596a3193.803104 3193.803104 0 0 1-740.069493-640.444753l-288.200139 225.341673L0 378.900162l497.530693-506.425758A3054.209868 3054.209868 0 0 0 1186.008802 824.958073l-30.243224 71.160528m0-0.593005z" horiz-adv-x="1186" />
<glyph glyph-name="lianjie1" unicode="&#59317;" d="M95.99604 26.958728a63.101397 63.101397 0 0 1 63.99736-61.885447h703.970961a62.909405 62.909405 0 0 1 63.997361 61.885447V741.041272a63.101397 63.101397 0 0 1-63.997361 61.885447h-703.970961a62.909405 62.909405 0 0 1-63.99736-61.885447zM159.9934 895.978881h703.970961A157.689495 157.689495 0 0 0 1023.957762 741.041272v-714.082544A157.497503 157.497503 0 0 0 863.964361-127.978881h-703.970961A157.689495 157.689495 0 0 0 0 26.958728V741.041272A157.497503 157.497503 0 0 0 159.9934 895.978881zM389.743923 262.021032a24.446992 24.446992 0 0 1 34.494577 0L634.213839 471.612386a24.638984 24.638984 0 0 1-35.006556 34.686569L389.551931 296.707601a24.191002 24.191002 0 0 1 0-34.686569z m127.418744 61.117479a24.254999 24.254999 0 0 1-10.623562-32.894644 52.669827 52.669827 0 0 0 4.543813-30.014761 49.917941 49.917941 0 0 0-13.695435-26.622902l-1.279947-1.151953-105.019668-104.827676-1.151953-0.831965a48.509999 48.509999 0 0 0-67.38922 0.831965l-67.38922 67.261226-0.959961 0.831966a48.318007 48.318007 0 0 0-13.247453 33.406622 47.422044 47.422044 0 0 0 14.207414 34.17459l1.471939 1.471939 104.827676 104.827676a49.661951 49.661951 0 0 0 26.622902 13.56744 50.749907 50.749907 0 0 0 29.82277-4.671807 24.574986 24.574986 0 0 1 22.271081 43.838192 99.323903 99.323903 0 0 1-59.965527 9.343614 95.548059 95.548059 0 0 1-53.245803-27.39087l-105.147663-104.95567-1.151952-1.151953v-0.319987a97.339985 97.339985 0 0 1-1.279948-136.442371l1.279948-1.279948v-0.319986l67.069233-67.069234h0.319987a96.892003 96.892003 0 0 1 68.733165-28.670817 95.612056 95.612056 0 0 1 67.709207 27.262875l1.599934 1.47194 105.019668 105.147662 1.471939 0.831966a99.003916 99.003916 0 0 1 27.070883 53.693785 97.275987 97.275987 0 0 1-9.343614 59.64554 24.702981 24.702981 0 0 1-33.086636 11.13554zM831.965681 539.38559a98.043956 98.043956 0 0 1-26.942888 67.389221l-1.471939 1.471939-67.389221 67.38922A97.659972 97.659972 0 0 1 666.980487 703.986801a95.99604 95.99604 0 0 1-67.38922-27.070884l-1.599934-1.279947-105.019668-104.827676-1.151953-1.471939a95.484061 95.484061 0 0 1-27.262875-53.885777 98.235948 98.235948 0 0 1 9.21562-59.837532 24.638984 24.638984 0 0 1 43.710197 22.719063 50.365922 50.365922 0 0 0-4.543813 29.82277 49.533957 49.533957 0 0 0 13.695435 26.302915l1.47194 1.279947L632.933891 640.565417l0.959961 1.471939a50.045936 50.045936 0 0 0 33.21463 12.799472 48.318007 48.318007 0 0 0 34.494577-14.335409l67.069233-67.38922 1.151953-0.511979a50.045936 50.045936 0 0 0 12.799472-33.406622 46.910065 46.910065 0 0 0-14.207414-34.17459v-0.319987l-0.959961-0.95996-105.147662-104.827676a47.486041 47.486041 0 0 0-26.622902-13.887427 49.789946 49.789946 0 0 0-29.82277 4.863799 25.086965 25.086965 0 0 1-33.21463-10.943548 24.766978 24.766978 0 0 1 11.135541-33.086636 96.636014 96.636014 0 0 1 59.64554-9.023627 95.164074 95.164074 0 0 1 53.56579 27.262875l104.827676 104.827676 1.279947 1.471939a96.572016 96.572016 0 0 1 28.414828 68.86116z" horiz-adv-x="1024" />
<glyph glyph-name="zhangjie" unicode="&#59318;" d="M773.902013 896A123.083076 123.083076 0 0 0 895.918512 769.84518v-834.789101a63.994667 63.994667 0 0 0-61.008249-63.056079 82.211816 82.211816 0 0 0-28.712274 7.423381l-240.449296 126.154821a110.92409 110.92409 0 0 1-107.63903 0l-240.406633-126.154821a63.141405 63.141405 0 0 0-82.553121 25.981835 71.802016 71.802016 0 0 0-7.167402 29.864178V773.599533a121.547204 121.547204 0 0 0 118.432797 122.44313z m-71.759353-474.84043h-383.968003a40.828598 40.828598 0 0 1 0-81.614532h383.968003a40.529956 40.529956 0 0 1 39.463378 40.828598 43.132406 43.132406 0 0 1-39.463378 40.828597z m0 237.420215h-383.968003a40.529956 40.529956 0 0 1-39.463378-40.828598 39.847346 39.847346 0 0 1 39.463378-37.116907h383.968003a40.529956 40.529956 0 0 1 39.463378 40.828598 42.663111 42.663111 0 0 1-39.463378 37.116907z" horiz-adv-x="1024" />
<glyph glyph-name="mobanguanli2" unicode="&#59313;" d="M1133.714286-120.685714H36.571429V201.142857h73.142857v-248.685714h950.857143V201.142857h73.142857zM943.542857 91.428571h-731.428571V896h731.428571v-804.571429z m-658.285714 73.142858h585.142857V822.857143h-585.142857v-658.285714zM416.914286 618.057143h343.771428v-73.142857H416.914286zM416.914286 420.571429h343.771428v-73.142858H416.914286z" horiz-adv-x="1170" />
<glyph glyph-name="fenzuzuoye2" unicode="&#59312;" d="M585.142857-79.945143l-21.942857 7.314286c-29.257143 14.628571-58.514286 21.942857-80.457143 29.257143-65.828571 21.942857-131.657143 29.257143-204.8 36.571428-51.2 7.314286-117.028571 0-182.857143-14.628571-36.571429-7.314286-80.457143 14.628571-87.771428 58.514286v709.485714c0 36.571429 29.257143 73.142857 65.828571 73.142857 73.142857 7.314286 131.657143 7.314286 168.228572 7.314286h14.628571c51.2-7.314286 109.714286-14.628571 182.857143-36.571429 51.2-14.628571 73.142857-21.942857 87.771428-29.257143 29.257143-7.314286 51.2-7.314286 58.514286-7.314285 14.628571 0 102.4 29.257143 138.971429 36.571428 21.942857 7.314286 36.571429 14.628571 43.885714 14.628572 36.571429 7.314286 65.828571 14.628571 109.714286 21.942857 43.885714 7.314286 124.342857 7.314286 226.742857 0 36.571429 0 65.828571-36.571429 65.828571-73.142857v-702.171429c0-43.885714-29.257143-73.142857-73.142857-73.142857h-14.628571c-73.142857 14.628571-138.971429 21.942857-190.171429 21.942857-73.142857 0-146.285714-14.628571-219.428571-36.571429-21.942857-7.314286-43.885714-14.628571-58.514286-29.257142l-29.257143-14.628572z m-351.085714 153.6h43.885714c73.142857-7.314286 146.285714-21.942857 219.428572-43.885714 29.257143-7.314286 58.514286-14.628571 87.771428-29.257143 21.942857 7.314286 36.571429 21.942857 65.828572 29.257143 80.457143 29.257143 160.914286 43.885714 248.685714 43.885714 58.514286 0 131.657143-7.314286 204.8-21.942857l-7.314286 702.171429c-124.342857 14.628571-182.857143 7.314286-212.114286 0-36.571429-7.314286-73.142857-14.628571-102.4-21.942858-7.314286 0-21.942857-7.314286-43.885714-14.628571-87.771429-21.942857-131.657143-36.571429-153.6-36.571429-14.628571 0-29.257143 0-51.2 7.314286H512l7.314286 21.942857-7.314286-14.628571c-7.314286 0-73.142857 21.942857-95.085714 21.942857-65.828571 21.942857-117.028571 29.257143-168.228572 36.571429h-14.628571c-29.257143 0-87.771429 0-160.914286-7.314286v-694.857143c58.514286 14.628571 109.714286 21.942857 160.914286 21.942857zM548.571429 739.254857h73.142857v-775.314286h-73.142857zM160.914286 578.340571h226.742857v-73.142857H160.914286zM160.914286 344.283429h226.742857v-73.142858H160.914286zM782.628571 578.340571h226.742858v-73.142857h-226.742858zM782.628571 344.283429h226.742858v-73.142858h-226.742858z" horiz-adv-x="1170" />
<glyph glyph-name="biyezuoye1" unicode="&#59311;" d="M593.92 343.04L6.826667 581.973333 546.133333 841.386667c27.306667 13.653333 61.44 13.653333 88.746667 0l539.306667-238.933334-580.266667-259.413333zM177.493333 588.8L593.92 418.133333l416.426667 184.32L607.573333 786.773333c-6.826667 6.826667-20.48 6.826667-27.306666 0L177.493333 588.8zM54.613333 602.453333h68.266667v-361.813333h-68.266667zM109.226667 254.293333m-68.266667 0a68.266667 68.266667 0 1 1 136.533333 0 68.266667 68.266667 0 1 1-136.533333 0ZM279.893333 124.586667c191.146667-286.72 416.426667-286.72 682.666667-13.653334 163.84 170.666667-129.706667-116.053333-334.506667-116.053333-95.573333 0-211.626667 40.96-348.16 129.706667zM1037.653333 1.706667c-20.48 0-40.96 13.653333-40.96 34.133333-6.826667 47.786667-20.48 81.92-40.96 102.4-20.48 13.653333-40.96 20.48-75.093333 13.653333-20.48 0-40.96 13.653333-47.786667 34.133334 0 20.48 13.653333 40.96 34.133334 47.786666 54.613333 6.826667 102.4 0 136.533333-27.306666 40.96-34.133333 61.44-81.92 68.266667-157.013334 13.653333-20.48-6.826667-40.96-34.133334-47.786666 6.826667 0 0 0 0 0z" horiz-adv-x="1174" />
<glyph glyph-name="tongji3" unicode="&#59310;" d="M463.811765-73.788235C228.894118-73.788235 30.117647 118.964706 30.117647 353.882353c0 234.917647 192.752941 427.670588 433.694118 427.670588v-60.235294C259.011765 721.317647 90.352941 558.682353 90.352941 353.882353s168.658824-367.435294 373.458824-367.435294c198.776471 0 379.482353 156.611765 391.529411 337.317647H445.741176v60.235294h475.858824V353.882353c-6.023529-228.894118-210.823529-427.670588-457.788235-427.670588zM433.694118 775.529412h60.235294v-457.788236h-60.235294zM433.332706 381.711059l433.694118 4.698353 0.602352-60.235294-433.694117-4.698353zM969.788235 504.470588h-60.235294c0 162.635294-132.517647 301.176471-301.17647 301.176471v60.235294c198.776471 0 361.411765-162.635294 361.411764-361.411765zM969.788235 468.329412H578.258824V859.858824h60.235294v-331.294118h331.294117z" horiz-adv-x="1024" />
<glyph glyph-name="qiandao1" unicode="&#59309;" d="M984.615385-128h-866.461539C55.138462-128 0-72.861538 0-9.846154v708.923077C0 762.092308 55.138462 817.230769 118.153846 817.230769h866.461539c63.015385 0 118.153846-55.138462 118.153846-118.153846v-708.923077c0-63.015385-55.138462-118.153846-118.153846-118.153846zM118.153846 738.461538c-23.630769 0-39.384615-15.753846-39.384615-39.384615v-708.923077c0-23.630769 15.753846-39.384615 39.384615-39.384615h866.461539c23.630769 0 39.384615 15.753846 39.384615 39.384615v708.923077c0 23.630769-15.753846 39.384615-39.384615 39.384615h-866.461539zM315.076923 896h78.769231v-236.307692H315.076923zM504.123077 92.553846L299.323077 352.492308l63.015385 47.261538 141.784615-189.046154 299.323077 322.953846 55.138461-55.138461zM669.538462 896h78.76923v-236.307692h-78.76923z" horiz-adv-x="1102" />
<glyph glyph-name="fenban2" unicode="&#59308;" d="M354.986667 356.693333c-129.706667 0-232.106667 109.226667-232.106667 238.933334S225.28 834.56 354.986667 834.56c109.226667 0 204.8-81.92 232.106666-197.973333l-61.44-13.653334C512 711.68 443.733333 766.293333 354.986667 766.293333c-95.573333 0-170.666667-81.92-170.666667-177.493333s81.92-177.493333 170.666667-177.493333v-54.613334zM559.786667 206.506667c-136.533333 0-238.933333 109.226667-238.933334 238.933333S430.08 691.2 559.786667 691.2s238.933333-109.226667 238.933333-238.933333-102.4-245.76-238.933333-245.76z m0 416.426666C464.213333 622.933333 389.12 547.84 389.12 452.266667S464.213333 281.6 559.786667 281.6s170.666667 75.093333 170.666666 170.666667S655.36 622.933333 559.786667 622.933333zM116.053333 110.933333H61.44C54.613333 281.6 191.146667 418.133333 354.986667 418.133333v-61.44c-129.706667 0-238.933333-109.226667-238.933334-245.76zM921.6-114.346667h-68.266667c0 157.013333-129.706667 286.72-286.72 286.72s-286.72-129.706667-286.72-286.72h-68.266666c0 197.973333 157.013333 354.986667 354.986666 354.986667 191.146667 0 354.986667-157.013333 354.986667-354.986667z" horiz-adv-x="1024" />
<glyph glyph-name="taolun2" unicode="&#59307;" d="M118.153846-128c-23.630769 0-31.507692 0-39.384615 7.876923-31.507692 15.753846-23.630769 55.138462-7.876923 126.030769 15.753846 78.769231 15.753846 94.523077 7.876923 118.153846-55.138462 78.769231-78.769231 173.292308-78.769231 267.815385C0 667.569231 244.184615 896 551.384615 896s551.384615-228.430769 551.384616-504.123077-244.184615-504.123077-551.384616-504.123077c-55.138462 0-110.276923 7.876923-157.538461 23.630769-23.630769 7.876923-47.261538 0-141.784616-15.753846h-7.876923c-63.015385-23.630769-102.4-23.630769-126.030769-23.630769zM551.384615 817.230769C291.446154 817.230769 78.769231 628.184615 78.769231 391.876923c0-78.769231 23.630769-157.538462 70.892307-220.553846 31.507692-55.138462 23.630769-102.4 7.876924-181.169231 0-15.753846-7.876923-31.507692-7.876924-39.384615 15.753846 0 39.384615 7.876923 78.769231 15.753846H236.307692c102.4 15.753846 133.907692 23.630769 181.169231 15.753846 47.261538-15.753846 94.523077-15.753846 141.784615-15.753846 259.938462 0 472.615385 189.046154 472.615385 425.353846C1024 628.184615 811.323077 817.230769 551.384615 817.230769zM315.076923 226.461538c-63.015385 0-118.153846 55.138462-118.153846 118.153847S252.061538 462.769231 315.076923 462.769231s118.153846-55.138462 118.153846-118.153846S378.092308 226.461538 315.076923 226.461538z m0 157.538462c-23.630769 0-39.384615-15.753846-39.384615-39.384615s15.753846-39.384615 39.384615-39.384616 39.384615 15.753846 39.384615 39.384616-15.753846 39.384615-39.384615 39.384615zM551.384615 226.461538c-63.015385 0-118.153846 55.138462-118.153846 118.153847S488.369231 462.769231 551.384615 462.769231s118.153846-55.138462 118.153847-118.153846S614.4 226.461538 551.384615 226.461538z m0 157.538462c-23.630769 0-39.384615-15.753846-39.384615-39.384615s15.753846-39.384615 39.384615-39.384616 39.384615 15.753846 39.384616 39.384616-15.753846 39.384615-39.384616 39.384615zM787.692308 226.461538c-63.015385 0-118.153846 55.138462-118.153846 118.153847s55.138462 118.153846 118.153846 118.153846 118.153846-55.138462 118.153846-118.153846-55.138462-118.153846-118.153846-118.153847z m0 157.538462c-23.630769 0-39.384615-15.753846-39.384616-39.384615s15.753846-39.384615 39.384616-39.384616 39.384615 15.753846 39.384615 39.384616-15.753846 39.384615-39.384615 39.384615z" horiz-adv-x="1102" />
<glyph glyph-name="shipinzhibo1" unicode="&#59306;" d="M884.363636-128h-744.727272C65.163636-128 0-62.836364 0 11.636364v744.727272C0 830.836364 65.163636 896 139.636364 896h744.727272c74.472727 0 139.636364-65.163636 139.636364-139.636364v-744.727272c0-74.472727-65.163636-139.636364-139.636364-139.636364z m-744.727272 930.909091c-27.927273 0-46.545455-18.618182-46.545455-46.545455v-744.727272c0-27.927273 18.618182-46.545455 46.545455-46.545455h744.727272c27.927273 0 46.545455 18.618182 46.545455 46.545455v744.727272c0 27.927273-18.618182 46.545455-46.545455 46.545455h-744.727272zM1340.509091 11.636364l-372.363636 186.181818V495.709091l372.363636 167.563636v-651.636363z m-279.272727 242.036363l186.181818-93.090909V523.636364l-186.181818-83.781819v-186.181818zM186.181818 709.818182h186.181818v-93.090909H186.181818z" horiz-adv-x="1396" />
<glyph glyph-name="kaoshishijuan1" unicode="&#59305;" d="M443.733333-93.866667H136.533333c-54.613333 0-102.4 47.786667-102.4 102.4V759.466667C34.133333 814.08 81.92 861.866667 136.533333 861.866667h614.4c54.613333 0 102.4-47.786667 102.4-102.4v-327.68h-68.266666V759.466667c0 20.48-13.653333 34.133333-34.133334 34.133333H136.533333c-20.48 0-34.133333-13.653333-34.133333-34.133333v-750.933334c0-20.48 13.653333-34.133333 34.133333-34.133333h307.2v-68.266667zM750.933333 76.8c-75.093333 0-136.533333 61.44-136.533333 136.533333s61.44 136.533333 136.533333 136.533334 136.533333-61.44 136.533334-136.533334-61.44-136.533333-136.533334-136.533333z m0 204.8c-40.96 0-68.266667-27.306667-68.266666-68.266667s27.306667-68.266667 68.266666-68.266666 68.266667 27.306667 68.266667 68.266666-27.306667 68.266667-68.266667 68.266667zM989.866667-93.866667h-68.266667c0 95.573333-75.093333 170.666667-170.666667 170.666667s-170.666667-75.093333-170.666666-170.666667h-68.266667c0 129.706667 109.226667 238.933333 238.933333 238.933334s238.933333-109.226667 238.933334-238.933334zM580.266667 554.666667h-341.333334c-20.48 0-34.133333 13.653333-34.133333 34.133333s13.653333 34.133333 34.133333 34.133333h341.333334c20.48 0 34.133333-13.653333 34.133333-34.133333s-13.653333-34.133333-34.133333-34.133333zM512 349.866667h-273.066667c-20.48 0-34.133333 13.653333-34.133333 34.133333s13.653333 34.133333 34.133333 34.133333h273.066667c20.48 0 34.133333-13.653333 34.133333-34.133333s-13.653333-34.133333-34.133333-34.133333zM204.8 213.333333h204.8v-68.266666H204.8z" horiz-adv-x="1024" />
<glyph glyph-name="kaoshiwenjuan1" unicode="&#59303;" d="M471.811482-80.71359H161.957516c-53.887646 0-101.039337 47.151691-101.039337 101.039337V761.280884C60.918179 815.16853 108.06987 862.320221 161.957516 862.320221h606.236021c53.887646 0 101.039337-47.151691 101.039337-101.039337v-282.910143h-67.359558V761.280884c0 20.207867-13.471912 33.679779-33.679779 33.679779H161.957516c-20.207867 0-33.679779-13.471912-33.679779-33.679779v-740.955137c0-20.207867 13.471912-33.679779 33.679779-33.679779h309.853966v-67.359558zM700.83398-47.033811c-114.511249 0-202.078674 87.567425-202.078674 202.078674s87.567425 202.078674 202.078674 202.078673 202.078674-87.567425 202.078673-202.078673-87.567425-202.078674-202.078673-202.078674z m0 336.797789c-74.095514 0-134.719116-60.623602-134.719116-134.719115s60.623602-134.719116 134.719116-134.719116 134.719116 60.623602 134.719115 134.719116-60.623602 134.719116-134.719115 134.719115zM821.946465-13.69083l47.623207 47.623207 114.30917-114.30917-47.623207-47.623207zM599.794643 559.20221h-336.79779c-20.207867 0-33.679779 13.471912-33.679779 33.679779s13.471912 33.679779 33.679779 33.679779h336.79779c20.207867 0 33.679779-13.471912 33.679779-33.679779s-13.471912-33.679779-33.679779-33.679779zM397.715969 357.123536h-134.719116c-20.207867 0-33.679779 13.471912-33.679779 33.679779s13.471912 33.679779 33.679779 33.679779h134.719116c20.207867 0 33.679779-13.471912 33.679779-33.679779s-13.471912-33.679779-33.679779-33.679779z" horiz-adv-x="1024" />
<glyph glyph-name="xuexiziyuan1" unicode="&#59304;" d="M1024-64.984615H78.769231c-47.261538 0-78.769231 31.507692-78.769231 78.76923v787.692308c0 47.261538 31.507692 78.769231 78.769231 78.769231h315.076923l157.538461-165.415385h472.615385c47.261538 0 78.769231-31.507692 78.769231-78.769231v-622.276923c0-39.384615-31.507692-78.769231-78.769231-78.76923zM78.769231 801.476923v-787.692308h945.230769V636.061538H519.876923l-157.538461 165.415385H78.769231zM0 462.769231h1024v-78.769231H0zM118.153846 226.461538h315.076923v-78.76923h-315.076923zM984.615385 817.230769h-315.076923C645.907692 817.230769 630.153846 832.984615 630.153846 856.615385s15.753846 39.384615 39.384616 39.384615h315.076923c23.630769 0 39.384615-15.753846 39.384615-39.384615s-15.753846-39.384615-39.384615-39.384616z" horiz-adv-x="1102" />
<glyph glyph-name="putongzuoye1" unicode="&#59266;" d="M832-96H128c-51.2 0-96 44.8-96 96V768C32 819.2 76.8 864 128 864h544v-64H128c-19.2 0-32-12.8-32-32v-768c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32V294.4c0 19.2 12.8 32 32 32s32-12.8 32-32V0c0-51.2-44.8-96-96-96zM480 576h-256c-19.2 0-32 12.8-32 32s12.8 32 32 32h256c19.2 0 32-12.8 32-32s-12.8-32-32-32zM416 384h-192c-19.2 0-32 12.8-32 32s12.8 32 32 32h192c19.2 0 32-12.8 32-32s-12.8-32-32-32zM512 230.4V409.6l320 384c19.2 25.6 51.2 44.8 89.6 44.8 32 0 70.4-6.4 96-32 51.2-44.8 64-128 12.8-179.2l-320-384-198.4-12.8zM576 384v-89.6l102.4 6.4 300.8 358.4c25.6 25.6 19.2 70.4-6.4 89.6-12.8 19.2-25.6 25.6-44.8 25.6-19.2 0-32-6.4-44.8-25.6L576 384zM729.6 96H192c-19.2 0-32 12.8-32 32s12.8 32 32 32h537.6c19.2 0 32-12.8 32-32s-12.8-32-32-32z" horiz-adv-x="1088" />
<glyph glyph-name="shixunzuoye1" unicode="&#59302;" d="M914.285714 91.428571h-804.571428C51.2 91.428571 0 142.628571 0 201.142857v585.142857C0 844.8 51.2 896 109.714286 896h804.571428c58.514286 0 109.714286-51.2 109.714286-109.714286v-585.142857c0-58.514286-51.2-109.714286-109.714286-109.714286zM109.714286 822.857143c-21.942857 0-36.571429-14.628571-36.571429-36.571429v-585.142857c0-21.942857 14.628571-36.571429 36.571429-36.571428h804.571428c21.942857 0 36.571429 14.628571 36.571429 36.571428v585.142857c0 21.942857-14.628571 36.571429-36.571429 36.571429h-804.571428zM0 310.857143h950.857143v-73.142857H0zM256-54.857143H804.571429v-73.142857H256zM248.685714 362.057143l-146.285714 182.857143 146.285714 226.742857 58.514286-43.885714-117.028571-175.542858 117.028571-146.285714zM760.685714 362.057143l-58.514285 43.885714 117.028571 146.285714-117.028571 175.542858 58.514285 43.885714 146.285715-226.742857zM351.085714 413.257143l263.314286 351.085714 58.514286-43.885714-263.314286-351.085714zM365.714286 164.571429h73.142857v-219.428572H365.714286zM585.142857 164.571429h73.142857v-219.428572H585.142857z" horiz-adv-x="1024" />
<glyph glyph-name="Lastupdated" unicode="&#59301;" d="M512-107.52c-281.6 0-512 225.28-512 501.76S230.4 896 512 896s512-225.28 512-501.76-230.4-501.76-512-501.76z m0 931.84c-240.64 0-440.32-194.56-440.32-430.08s199.68-430.08 440.32-430.08 440.32 194.56 440.32 430.08-199.68 430.08-440.32 430.08zM547.84 102.4H476.16v215.04H261.12V389.12h215.04V609.28h71.68v-220.16h215.04v-71.68h-215.04z" horiz-adv-x="1024" />
<glyph glyph-name="CONTACTS" unicode="&#59300;" d="M599.771429-69.485714l-14.628572 68.266666c107.27619 19.504762 199.92381 87.771429 258.438095 190.171429l58.514286-34.133333c-68.266667-121.904762-180.419048-199.92381-302.323809-224.304762zM146.285714 452.266667l-68.266666 9.752381C107.27619 700.952381 297.447619 881.371429 521.752381 881.371429s414.47619-180.419048 443.733333-419.352381l-68.266666-4.876191c-24.380952 204.8-185.295238 355.961905-375.466667 355.961905-190.171429 0-351.085714-156.038095-375.466667-360.838095zM112.152381 159.695238c-48.761905 0-87.771429 39.009524-87.771429 87.771429v126.780952c0 48.761905 39.009524 87.771429 87.771429 87.771429s87.771429-39.009524 87.771429-87.771429v-131.657143c-4.87619-43.885714-43.885714-82.895238-87.771429-82.895238z m0 234.057143c-9.752381 0-19.504762-9.752381-19.504762-19.504762v-131.657143c0-9.752381 9.752381-19.504762 19.504762-19.504762s19.504762 9.752381 19.504762 19.504762v131.657143c-4.87619 9.752381-14.628571 19.504762-19.504762 19.504762zM536.380952-103.619048h-97.523809c-34.133333 0-63.390476 29.257143-63.390476 63.390477 0 34.133333 29.257143 63.390476 63.390476 63.390476h97.523809c34.133333 0 63.390476-29.257143 63.390477-63.390476 0-39.009524-29.257143-63.390476-63.390477-63.390477zM911.847619 159.695238c-48.761905 0-87.771429 39.009524-87.771429 87.771429v126.780952c0 48.761905 39.009524 87.771429 87.771429 87.771429s87.771429-39.009524 87.771429-87.771429v-131.657143c0-43.885714-39.009524-82.895238-87.771429-82.895238z m0 234.057143c-9.752381 0-19.504762-9.752381-19.504762-19.504762v-131.657143c0-9.752381 9.752381-19.504762 19.504762-19.504762s19.504762 9.752381 19.504762 19.504762v131.657143c0 9.752381-9.752381 19.504762-19.504762 19.504762z" horiz-adv-x="1024" />
<glyph glyph-name="SPONSORS" unicode="&#59299;" d="M489.73913 392.904348c-138.017391 0-253.773913 111.304348-253.773913 253.773913S347.269565 896 489.73913 896s253.773913-111.304348 253.773913-253.773913-115.756522-249.321739-253.773913-249.321739z m0 440.765217c-102.4 0-191.443478-84.591304-191.443478-191.443478S382.886957 455.234783 489.73913 455.234783c102.4 0 191.443478 84.591304 191.443479 191.443478s-89.043478 186.991304-191.443479 186.991304zM120.208696-105.73913L115.756522-83.478261c-8.904348 35.617391-13.356522 66.782609-13.356522 102.4 0 222.608696 182.53913 405.147826 405.147826 405.147826s405.147826-182.53913 405.147826-405.147826c0-31.165217-4.452174-66.782609-13.356522-97.947826l-4.452173-22.26087-774.678261-4.452173zM507.547826 361.73913c-186.991304 0-342.817391-155.826087-342.817391-342.817391 0-22.26087 0-44.521739 4.452174-62.330435L845.913043-38.956522c4.452174 17.808696 4.452174 40.069565 4.452174 57.878261 0 186.991304-155.826087 342.817391-342.817391 342.817391zM512-38.956522l-106.852174 289.391305 106.852174 120.208695 97.947826-120.208695L512-38.956522z m-31.165217 276.034783l31.165217-89.043478 31.165217 89.043478-31.165217 35.617391-31.165217-35.617391z" horiz-adv-x="1024" />
<glyph glyph-name="FINALREPORTS" unicode="&#59298;" d="M633.904762-98.742857H219.428571c-73.142857 0-131.657143 58.514286-131.657142 131.657143V749.714286C87.771429 822.857143 146.285714 881.371429 219.428571 881.371429h580.266667c73.142857 0 131.657143-58.514286 131.657143-131.657143v-516.876191l-297.447619-331.580952zM219.428571 813.104762c-34.133333 0-63.390476-29.257143-63.390476-63.390476v-716.8c0-34.133333 29.257143-63.390476 63.390476-63.390476h385.219048l263.314286 287.695238V749.714286c0 34.133333-29.257143 63.390476-63.390476 63.390476H219.428571zM653.409524-64.609524h-68.266667v341.333334h312.076191v-68.266667h-243.809524zM238.933333 652.190476h570.514286v-68.266666H238.933333zM238.933333 447.390476h570.514286v-68.266666H238.933333z" horiz-adv-x="1024" />
<glyph glyph-name="STEERINGCOMMITTEE" unicode="&#59297;" d="M409.6 389.389474C269.473684 389.389474 156.294737 502.568421 156.294737 642.694737S269.473684 896 409.6 896s253.305263-113.178947 253.305263-253.305263-113.178947-253.305263-253.305263-253.305263z m0 431.157894c-97.010526 0-177.852632-80.842105-177.852632-177.852631S312.589474 464.842105 409.6 464.842105s177.852632 80.842105 177.852632 177.852632-80.842105 177.852632-177.852632 177.852631zM689.852632 340.884211V416.336842c97.010526 0 177.852632 80.842105 177.852631 177.852632 0 75.452632-48.505263 140.126316-118.568421 167.073684l26.947369 70.063158c102.4-37.726316 167.073684-129.347368 167.073684-237.136842 0-140.126316-113.178947-253.305263-253.305263-253.305263zM1050.947368-30.989474l-75.452631 16.168421c5.389474 21.557895 5.389474 43.115789 5.389474 70.063158 0 156.294737-123.957895 280.252632-280.252632 280.252632V416.336842c194.021053 0 355.705263-161.684211 355.705263-355.705263 5.389474-32.336842 0-64.673684-5.389474-91.621053zM37.726316-122.610526l-5.389474 26.947368c-10.778947 32.336842-16.168421 70.063158-16.168421 107.789474 0 226.357895 183.242105 414.989474 409.6 414.989473 226.357895 0 409.6-188.631579 409.6-414.989473 0-32.336842-5.389474-64.673684-10.778947-97.010527l-5.389474-26.947368-781.473684-10.778947z m388.042105 474.273684c-183.242105 0-334.147368-150.905263-334.147368-339.536842 0-21.557895 0-37.726316 5.389473-59.284211l662.905263 5.389474c0 16.168421 5.389474 32.336842 5.389474 53.894737 0 188.631579-150.905263 339.536842-339.536842 339.536842z" horiz-adv-x="1077" />
<glyph glyph-name="ORGANIZINGICSE-MOU" unicode="&#59296;" d="M614.4 537.6H450.56C373.76 537.6 312.32 604.16 312.32 675.84V757.76C312.32 834.56 373.76 896 450.56 896H614.4c76.8 0 138.24-61.44 138.24-138.24v-81.92C752.64 604.16 691.2 537.6 614.4 537.6zM450.56 824.32c-35.84 0-66.56-30.72-66.56-66.56v-81.92c0-35.84 30.72-66.56 66.56-66.56H614.4c35.84 0 66.56 30.72 66.56 66.56V757.76c0 35.84-30.72 66.56-66.56 66.56H450.56zM302.08-92.16H138.24c-76.8 0-138.24 61.44-138.24 138.24V128c0 76.8 61.44 138.24 138.24 138.24h163.84c76.8 0 138.24-61.44 138.24-138.24v-81.92c0-76.8-61.44-138.24-138.24-138.24z m-163.84 286.72c-35.84 0-66.56-30.72-66.56-66.56v-81.92c0-35.84 30.72-66.56 66.56-66.56h163.84c35.84 0 66.56 30.72 66.56 66.56V128c0 35.84-30.72 66.56-66.56 66.56H138.24zM936.96-92.16h-163.84c-76.8 0-138.24 61.44-138.24 138.24V128c0 76.8 61.44 138.24 138.24 138.24h163.84c76.8 0 138.24-61.44 138.24-138.24v-81.92c0-76.8-61.44-138.24-138.24-138.24z m-163.84 286.72c-35.84 0-66.56-30.72-66.56-66.56v-81.92c0-35.84 30.72-66.56 66.56-66.56h163.84c35.84 0 66.56 30.72 66.56 66.56V128c0 35.84-30.72 66.56-66.56 66.56h-163.84zM890.88 266.24H819.2v107.52H256v-107.52H184.32V445.44h317.44V537.6h71.68v-92.16h317.44z" horiz-adv-x="1075" />
<glyph glyph-name="INFLUENTIALPAPERS" unicode="&#59295;" d="M791.272727-90.763636H232.727273C162.909091-90.763636 107.054545-34.909091 107.054545 34.909091V756.363636C107.054545 826.181818 162.909091 882.036364 232.727273 882.036364h428.218182l251.345454-209.454546v-637.672727c4.654545-69.818182-51.2-125.672727-121.018182-125.672727zM232.727273 816.872727c-32.581818 0-60.509091-27.927273-60.509091-60.509091v-721.454545c0-32.581818 27.927273-60.509091 60.509091-60.509091h558.545454c32.581818 0 60.509091 27.927273 60.509091 60.509091V644.654545l-209.454545 172.218182H232.727273zM307.2 672.581818H512v-65.163636H307.2zM377.018182 640h65.163636v-125.672727H377.018182zM512 528.290909h228.072727v-65.163636H512zM307.2 337.454545h432.872727v-65.163636H307.2zM307.2 146.618182h316.509091v-65.163637H307.2zM884.363636 626.036364h-265.309091V849.454545h65.163637v-158.254545H884.363636z" horiz-adv-x="1024" />
<glyph glyph-name="BIBLIOGRAPHIES" unicode="&#59294;" d="M156.038095 696.07619H87.771429V881.371429h629.028571c73.142857 0 131.657143-58.514286 131.657143-131.657143v-48.761905h-68.266667V749.714286c0 34.133333-29.257143 63.390476-63.390476 63.390476H156.038095v-117.028572zM804.571429-128H87.771429V735.085714H804.571429c73.142857 0 131.657143-58.514286 131.657142-131.657143v-599.771428c0-73.142857-63.390476-131.657143-131.657142-131.657143zM156.038095-59.733333H804.571429c34.133333 0 63.390476 29.257143 63.390476 63.390476V603.428571c0 34.133333-29.257143 63.390476-63.390476 63.390477H156.038095v-726.552381zM302.32381 486.4h380.342857v-68.266667H302.32381zM302.32381 325.485714H512v-68.266666H302.32381z" horiz-adv-x="1024" />
<glyph glyph-name="PROCEEDINGS" unicode="&#59293;" d="M481.28 138.24L204.8 445.44l384 358.4 276.48-312.32-384-353.28zM302.08 440.32l184.32-199.68 276.48 256-179.2 204.8-281.6-261.12zM906.24-71.68c-30.72 0-61.44 15.36-87.04 40.96L532.48 281.6l174.08 163.84 291.84-327.68c20.48-20.48 30.72-51.2 25.6-81.92 0-30.72-15.36-56.32-35.84-76.8-25.6-20.48-51.2-30.72-81.92-30.72z m-271.36 348.16l240.64-266.24c15.36-20.48 46.08-20.48 66.56-5.12 10.24 10.24 15.36 15.36 15.36 30.72 0 10.24-5.12 20.48-10.24 30.72l-240.64 276.48-71.68-66.56zM849.92 450.56c-30.72 0-61.44 10.24-87.04 35.84l-194.56 204.8c-46.08 51.2-46.08 128 5.12 174.08 20.48 20.48 51.2 30.72 87.04 30.72 30.72 0 61.44-15.36 87.04-40.96l194.56-204.8c46.08-51.2 40.96-122.88-5.12-163.84-30.72-25.6-61.44-35.84-87.04-35.84z m-194.56 373.76c-10.24 0-25.6-5.12-35.84-15.36-20.48-20.48-20.48-51.2 0-71.68l194.56-204.8c20.48-20.48 46.08-20.48 66.56 0 20.48 15.36 20.48 46.08 5.12 66.56l-194.56 209.92c-10.24 10.24-20.48 15.36-35.84 15.36zM399.36 51.2c-35.84 0-71.68 15.36-97.28 40.96L35.84 368.64 215.04 537.6l358.4-384-76.8-66.56c-30.72-20.48-66.56-35.84-97.28-35.84z m-266.24 317.44l215.04-225.28c25.6-25.6 66.56-25.6 92.16-5.12l20.48 20.48L204.8 435.2l-71.68-66.56zM0-35.84h624.64v-71.68H0z" horiz-adv-x="1025" />
<glyph glyph-name="HISTORY" unicode="&#59292;" d="M422.956522-61.217391H178.086957c-66.782609 0-120.208696 53.426087-120.208696 120.208695V762.434783C57.878261 829.217391 111.304348 882.643478 178.086957 882.643478h574.330434c66.782609 0 120.208696-53.426087 120.208696-120.208695v-396.243479h-62.330435V762.434783c0 31.165217-26.713043 57.878261-57.878261 57.87826H178.086957c-31.165217 0-57.878261-26.713043-57.878261-57.87826v-703.443479c0-31.165217 26.713043-57.878261 57.878261-57.878261h244.869565v-62.330434zM756.869565-119.095652c-115.756522 0-213.704348 93.495652-213.704348 209.252174s93.495652 209.252174 213.704348 209.252174 213.704348-93.495652 213.704348-209.252174-97.947826-209.252174-213.704348-209.252174z m0 356.173913c-84.591304 0-151.373913-66.782609-151.373913-146.921739 0-80.13913 66.782609-146.921739 151.373913-146.921739s151.373913 66.782609 151.373913 146.921739c-4.452174 80.13913-71.234783 146.921739-151.373913 146.921739zM828.104348 1.113043h-120.208696v169.182609h62.330435v-106.852174h57.878261zM218.156522 668.93913h503.095652v-62.330434H218.156522zM218.156522 450.782609h414.052174v-62.330435H218.156522zM218.156522 245.982609h249.321739V183.652174H218.156522z" horiz-adv-x="1024" />
<glyph glyph-name="CONDUCTSAFETY" unicode="&#59291;" d="M499.2-110.933333l-17.066667 8.533333c-166.4 98.133333-273.066667 192-324.266666 294.4C110.933333 290.133333 81.066667 448 76.8 678.4v25.6l25.6 4.266667c98.133333 21.333333 170.666667 46.933333 217.6 68.266666C366.933333 797.866667 422.4 832 482.133333 878.933333l17.066667 12.8 17.066667-12.8c72.533333-46.933333 132.266667-81.066667 179.2-102.4 46.933333-17.066667 119.466667-42.666667 217.6-68.266666l21.333333-4.266667V682.666667c21.333333-204.8 8.533333-354.133333-46.933333-452.266667-55.466667-98.133333-174.933333-204.8-371.2-332.8l-17.066667-8.533333z m-362.666667 768c8.533333-204.8 34.133333-354.133333 76.8-439.466667s140.8-170.666667 285.866667-260.266667c179.2 115.2 290.133333 217.6 337.066667 302.933334 46.933333 85.333333 59.733333 217.6 42.666666 396.8-93.866667 25.6-162.133333 46.933333-204.8 64-42.666667 17.066667-102.4 51.2-170.666666 93.866666-55.466667-42.666667-110.933333-72.533333-157.866667-93.866666-46.933333-21.333333-115.2-42.666667-209.066667-64zM536.405333 205.226667h-59.733333v153.6h-149.333333v59.733333h149.333333v153.6h59.733333v-153.6h153.6v-59.733333h-153.6z" horiz-adv-x="1024" />
<glyph glyph-name="EDISTATEMENT" unicode="&#59290;" d="M819.2-128H200.347826C133.565217-128 80.13913-74.573913 80.13913-7.791304V762.434783C80.13913 829.217391 133.565217 882.643478 200.347826 882.643478h618.852174c66.782609 0 120.208696-53.426087 120.208696-120.208695v-770.226087c0-66.782609-53.426087-120.208696-120.208696-120.208696zM200.347826 820.313043C169.182609 820.313043 142.469565 793.6 142.469565 762.434783v-770.226087c0-31.165217 26.713043-57.878261 57.878261-57.878261h618.852174c31.165217 0 57.878261 26.713043 57.878261 57.878261V762.434783c0 31.165217-26.713043 57.878261-57.878261 57.87826H200.347826zM267.130435 308.313043h507.547826v-62.330434H267.130435zM267.130435 107.965217h262.678261v-62.330434H267.130435zM498.643478 744.626087h62.330435v-218.156522H498.643478zM538.713043 441.878261m-44.521739 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0Z" horiz-adv-x="1024" />
<glyph glyph-name="MAILINGLIST" unicode="&#59289;" d="M1070.08 66.56h-215.04v71.68h215.04c35.84 0 66.56 30.72 66.56 66.56V742.4c0 35.84-30.72 66.56-66.56 66.56H153.6c-35.84 0-66.56-30.72-66.56-66.56v-537.6c0-35.84 30.72-66.56 66.56-66.56h230.4v-71.68H153.6C76.8 66.56 15.36 128 15.36 204.8V742.4C15.36 819.2 76.8 880.64 153.6 880.64h916.48c76.8 0 138.24-61.44 138.24-138.24v-537.6c0-76.8-61.44-138.24-138.24-138.24zM614.4 394.24L138.24 727.04l40.96 56.32L614.4 481.28l424.96 302.08 46.08-56.32zM134.6048 223.8464L388.7104 483.84l51.2512-50.0736-254.1056-259.9424zM795.648 428.4928l51.2 50.1248 254.2592-259.84-51.2-50.176zM460.8 286.72h307.2v-71.68H460.8zM460.8 189.44h307.2v-71.68H460.8zM460.8 87.04h307.2v-71.68H460.8zM460.8-15.36h307.2v-71.68H460.8z" horiz-adv-x="1228" />
<glyph glyph-name="HOME" unicode="&#59288;" d="M828.952381-113.371429h-151.161905c-43.885714 0-82.895238 39.009524-82.895238 82.895239v263.314285H477.866667V-30.47619c0-43.885714-39.009524-82.895238-82.895238-82.895239h-146.285715c-43.885714 0-82.895238 39.009524-82.895238 82.895239v360.838095H87.771429c-24.380952 0-48.761905 9.752381-63.390477 29.257143-14.628571 19.504762-19.504762 39.009524-19.504762 58.514285 0 24.380952 14.628571 43.885714 29.257143 53.638096L487.619048 842.361905c29.257143 24.380952 73.142857 24.380952 107.27619 0l443.733333-370.590476c19.504762-14.628571 29.257143-39.009524 29.257143-63.390477 0-43.885714-39.009524-82.895238-82.895238-82.895238h-78.019047v-360.838095c4.87619-39.009524-34.133333-78.019048-78.019048-78.019048z m-419.352381 414.476191h253.561905V-30.47619c0-9.752381 4.87619-14.628571 14.628571-14.628572H828.952381c9.752381 0 14.628571 4.87619 14.628571 14.628572v429.104761h146.285715c9.752381 0 14.628571 4.87619 14.628571 14.628572 0 4.87619 0 9.752381-4.87619 9.752381l-443.733334 370.590476c-4.87619 4.87619-14.628571 4.87619-19.504762 0L82.895238 423.009524c-4.87619-4.87619-4.87619-9.752381-4.87619-9.752381s0-4.87619 4.87619-9.752381 4.87619-4.87619 9.752381-4.876191h146.285714V-30.47619c0-9.752381 4.87619-14.628571 14.628572-14.628572h146.285714c9.752381 0 14.628571 4.87619 14.628571 14.628572v331.580952z" horiz-adv-x="1072" />
<glyph glyph-name="zhunbeizhong" unicode="&#59287;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM320 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM512 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM704 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z" horiz-adv-x="1024" />
@ -74,9 +311,6 @@ Created by iconfont
<glyph glyph-name="fenzuzuoye1" unicode="&#59267;" d="M21.333333 896h1024v-1024H21.333333zM949.333333 736H718.933333c-51.2 0-96-12.8-140.8-38.4l-44.8-32-51.2 25.6C443.733333 723.2 392.533333 736 347.733333 736H117.333333C98.133333 736 85.333333 723.2 85.333333 704v-569.6c0-19.2 12.8-32 32-32h230.4c51.2 0 96-12.8 140.8-38.4l44.8-25.6h12.8l38.4 25.6c38.4 25.6 89.6 38.4 140.8 38.4h230.4c19.2 0 32 12.8 32 32V704c-6.4 19.2-19.2 32-38.4 32zM347.733333 172.8h-192V665.6H341.333333c38.4 0 70.4-12.8 102.4-32l51.2-32 6.4-6.4v-460.8c-44.8 25.6-102.4 38.4-153.6 38.4z m563.2 0H725.333333c-57.6 0-108.8-12.8-153.6-38.4V595.2l6.4 6.4 51.2 32c32 19.2 64 32 102.4 32H917.333333v-492.8zM418.133333 537.6H232.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 0-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v38.4c0 6.4 0 12.8-6.4 12.8z m224-12.8v-44.8c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8c0 6.4-6.4 6.4-6.4 6.4H648.533333c-6.4 6.4-6.4 0-6.4-6.4z m-224-128H232.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 0-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8s0 6.4-6.4 6.4z m416 0H648.533333c-6.4 0-6.4-6.4-6.4-6.4v-44.8c0-6.4 6.4-6.4 6.4-6.4h185.6c6.4 0 6.4 6.4 6.4 6.4v44.8s0 6.4-6.4 6.4z" horiz-adv-x="1365" />
<glyph glyph-name="putongzuoye1" unicode="&#59266;" d="M4.266667 896h1024v-1024H4.266667zM650.666667 832v-70.4h-512v-755.2h652.8v320h70.4v-358.4c0-19.2-12.8-32-32-32H100.266667c-19.2 0-32 12.8-32 32v832c0 19.2 12.8 32 32 32h550.4zM420.266667 454.4H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 32 38.4 32h160c19.2 0 32-12.8 32-32s-12.8-38.4-32-38.4zM516.266667 601.6H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 32 38.4 32h256c19.2 0 38.4-19.2 38.4-38.4s-19.2-32-38.4-32zM714.666667 89.6H260.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h454.4c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM522.666667 185.6c-25.6 0-51.2 19.2-64 44.8-6.4 12.8-6.4 19.2-6.4 32l12.8 134.4c0 12.8 6.4 25.6 12.8 32l236.8 345.6c19.2 32 51.2 51.2 89.6 57.6 38.4 6.4 70.4 0 102.4-19.2l12.8-6.4c57.6-44.8 70.4-128 32-185.6L708.266667 268.8c-6.4-12.8-19.2-19.2-32-25.6l-134.4-51.2c-6.4 0-12.8-6.4-19.2-6.4z m300.8 576h-12.8c-19.2 0-32-12.8-38.4-25.6L535.466667 390.4l-6.4-128L644.266667 307.2l243.2 345.6c19.2 25.6 12.8 64-12.8 89.6l-6.4 6.4 19.2 25.6-25.6-25.6c-12.8 6.4-25.6 12.8-38.4 12.8z" horiz-adv-x="1092" />
<glyph glyph-name="shixunzuoye" unicode="&#59265;" d="M4.266667 896h1024v-1024H4.266667zM964.266667 128H68.266667V832h896v-704zM138.666667 204.8h755.2V761.6H138.666667v-556.8zM708.266667-64H324.266667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h384c19.2 0 38.4-19.2 38.4-38.4s-19.2-38.4-38.4-38.4zM708.266667 403.2c-12.8 0-19.2 6.4-25.6 12.8-12.8 12.8-12.8 38.4 6.4 51.2L772.266667 544 682.666667 620.8c-12.8 12.8-12.8 38.4 0 51.2 12.8 12.8 38.4 12.8 51.2 0l89.6-83.2c12.8-12.8 19.2-32 19.2-44.8 0-19.2-6.4-38.4-19.2-51.2l-6.4-6.4-83.2-76.8c-12.8 0-19.2-6.4-25.6-6.4zM330.666667 403.2c-6.4 0-19.2 0-25.6 6.4L215.466667 492.8c-25.6 25.6-25.6 70.4 0 96l89.6 83.2c12.8 12.8 38.4 12.8 51.2 0 12.8-12.8 12.8-38.4 0-51.2L266.666667 537.6l83.2-70.4c12.8-12.8 19.2-38.4 6.4-51.2-6.4-6.4-19.2-12.8-25.6-12.8zM465.066667 384H452.266667c-19.2 12.8-25.6 32-19.2 51.2l102.4 243.2c6.4 19.2 25.6 32 44.8 19.2 19.2-6.4 25.6-25.6 19.2-44.8L503.466667 409.6c-6.4-12.8-19.2-25.6-38.4-25.6zM925.866667 256H119.466667c-19.2 0-38.4 19.2-38.4 38.4s19.2 38.4 38.4 38.4h800c19.2 0 38.4-19.2 38.4-38.4s-12.8-38.4-32-38.4zM401.066667 160h70.4V-64H401.066667zM586.666667 160h70.4V-64H586.666667z" horiz-adv-x="1092" />

Before

Width:  |  Height:  |  Size: 506 KiB

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,40 +1,111 @@
.maxW50{max-width: 50%;}
.minW50{min-width: 50%;}
.width70{width: 70%;}
.width30{width: 30%;}
.custom-commit-tabs .ant-tabs-bar{border-bottom: none;}
.maxW200px{max-width: 200px;}
.pr_tags_open{
background: #28BD6C !important;
color: #fff !important;
border: none !important;
.CodeMirror-merge {
position: relative;
white-space: pre;
}
.pr_tags_closed{
background: #FA6400 !important;
color: #fff !important;
border: none !important;
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
min-height:50px;
}
.pr_tags_merged{
background: #4C9ED3 !important;
color: #fff !important;
border: none !important;
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 48%; }
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 4%; }
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
.CodeMirror-merge-pane {
display: inline-block;
white-space: normal;
vertical-align: top;
}
.ant-btn-success{
border: 1px solid #28BD6C !important;
color: #28BD6C !important;
.CodeMirror-merge-pane-rightmost {
position: absolute;
right: 0px;
z-index: 1;
}
.ant-btn-success:hover{
background: #28BD6C !important;
color:#fff !important;
.CodeMirror-merge-gap {
z-index: 2;
display: inline-block;
height: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
position: relative;
background: #515151;
}
.display-flex{display: flex !important;}
.merge-flex1{flex:1}
.ant-tag.pr-branch-tag{
border-radius: 12px;
height: 24px;
background: rgba(241,248,255,1);
border: none;
font-size: 13px;
padding: 0 10px;
}
.CodeMirror-merge-scrolllock-wrap {
position: absolute;
bottom: 0; left: 50%;
}
.CodeMirror-merge-scrolllock {
position: relative;
left: -50%;
cursor: pointer;
color: #d8d8d8;
line-height: 1;
}
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute;
left: 0; top: 0;
right: 0; bottom: 0;
line-height: 1;
}
.CodeMirror-merge-copy {
position: absolute;
cursor: pointer;
color: #ce374b;
z-index: 3;
}
.CodeMirror-merge-copy-reverse {
position: absolute;
cursor: pointer;
color: #44c;
}
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-chunk { background: #9a6868; }
.CodeMirror-merge-r-chunk-start { /*border-top: 1px solid #ee8; */}
.CodeMirror-merge-r-chunk-end {/* border-bottom: 1px solid #ee8; */}
.CodeMirror-merge-r-connect { fill:#9a6868;}
.CodeMirror-merge-l-chunk { background: #eef; }
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
.CodeMirror-merge-collapsed-widget:before {
content: "(...)";
}
.CodeMirror-merge-collapsed-widget {
cursor: pointer;
color: #88b;
background: #eef;
border: 1px solid #ddf;
font-size: 90%;
padding: 0 3px;
border-radius: 4px;
}
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }

View File

@ -1,53 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=”Keywords” Content=”EduCoder,信息技术实践教学,精品课程网,慕课MOOC″>
<meta name=”Keywords” Content=”实践课程,项目实战,java实训,python实战,人工智能技术,后端开发学习,移动开发入门″>
<meta name=”Keywords” Content=”翻转课堂,高效课堂创建,教学模式″>
<meta name=”Keywords” Content=”实训项目,python教程,C语言入门,java书,php后端开发,app前端开发,数据库技术″>
<meta name=”Keywords” Content=”在线竞赛,计算机应用大赛,编程大赛,大学生计算机设计大赛,全国高校绿色计算机大赛″>
<meta name=”Description”
Content=”EduCoder是信息技术类实践教学平台。EduCoder涵盖了计算机、大数据、云计算、人工智能、软件工程、物联网等专业课程。超10000个实训案例及22000个技能评测点建立学、练、评、测一体化实验环境。”>
<meta name=”Description”
Content=”EduCoder实践课程旨在于通过企业级实战实训案例帮助众多程序员提升各项业务能力。解决学生、学员、企业员工等程序设计能力、算法设计能力、问题求解能力、应用开发能力、系统运维能力等。”>
<meta name=”Description”
Content=”EduCoder翻转课堂教学模式颠覆了传统教学模式让教师与学生的关系由“权威”变成了“伙伴”。将学习的主动权转交给学生使学生可个性化化学学生的学习主体得到了彰显。”>
<meta name=”Description” Content=”EduCoder实训项目为单个知识点关卡实践训练帮助学生巩固单一弱点强化学习。 >
<meta name=”Description” Content=”EduCoder实践教学平台各类大赛为进一步提高各类学生综合运用高级语言程序设计能力培养创新意识和实践探索精神发掘优秀软件人才。 >
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>
<meta name=”Keywords” Content=”TrustieOpenSourceProject″>
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<script type="text/javascript">
window.__isR = true;
if (
(navigator.userAgent.indexOf('MSIE 9') != -1
|| navigator.userAgent.indexOf('MSIE 10') != -1)
&&
location.pathname.indexOf("/compatibility") == -1) {
location.href = '/compatibility.html'
}
</script>
<link rel=" stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
<link rel=" stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/merge.css">
<%= htmlWebpackPlugin.tags.headTags %>
</head>
<body>
<!--用于markdown转html -->
<div id="md_div" style="display: none;"></div>
<div id="root" class="page -layout-v -fit widthunit"></div>
<div id="picture_display" style="display: none;"></div>
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
<script src="%PUBLIC_URL%js/js_min_all.js"></script>
<script src="%PUBLIC_URL%js/codemirror/codemirror.js"></script>
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
<%= htmlWebpackPlugin.tags.bodyTags %>
</body>
</html>

View File

@ -9,13 +9,7 @@ import {
} from 'react-router-dom';
import axios from 'axios';
import LoginDialog from './modules/login/LoginDialog';
import Notcompletedysl from './modules/user/Notcompletedysl';
import Trialapplicationysl from './modules/login/Trialapplicationysl';
import Trialapplicationreview from './modules/user/Trialapplicationreview';
import AccountProfile from "./modules/user/AccountProfile";
import Accountnewprofile from './modules/user/Accountnewprofile';
import Certifiedprofessional from './modules/modals/Certifiedprofessional';
import 'babel-polyfill';
import Loading from './Loading'
import Loadable from 'react-loadable';
@ -76,6 +70,10 @@ const OrganizeIndex = Loadable({
loader: () => import('./forge/Team/Index'),
loading: Loading,
})
const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'),
loading: Loading,
})
class App extends Component {
constructor(props) {
@ -213,18 +211,12 @@ class App extends Component {
<Provider store={store}>
<ConfigProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<Accountnewprofile {...this.props}{...this.state} />
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
<Notcompletedysl {...this.props} {...this.state}></Notcompletedysl>
<Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl>
<Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview>
<AccountProfile {...this.props} {...this.state} />
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy} />
<Router>
<Switch>
{/*项目*/}
<Route
path={"/projects/:projectId/ops/:opsId/detail"}
path={"/projects/:owner/:projectId/devops/:opsId/detail"}
render={
(props) => {
return (<OpsDetail {...this.props} {...props} {...this.state} />)
@ -240,7 +232,15 @@ class App extends Component {
}
}>
</Route>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
{/*403*/}
<Route path="/403" component={Shixunauthority} />

View File

@ -1,12 +1,9 @@
import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage , isDev, queryString } from 'educoder';
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css';
const $ = window.$;
let timestamp;
let checkSubmitFlg = false;
let message501 = false;
broadcastChannelOnmessage('refreshPage', () => {
@ -30,20 +27,17 @@ if (isDev) {
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
}
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'p86402359'
}
function clearAllCookie() {
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
setpostcookie()
}
clearAllCookie();
// clearAllCookie();
function setpostcookie() {
const str = window.location.pathname;
let newdomain = ".educoder.net"
if (str.indexOf("/wxcode") !== -1) {
console.log("123")
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
const _params = window.location.search;
@ -53,7 +47,6 @@ function setpostcookie() {
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
let autologin_trusties = _search.split('&')[1].split('=');
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
}
}
}
@ -63,9 +56,9 @@ window._debugType = debugType;
export function initAxiosInterceptors(props) {
initOnlineOfflineListener()
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
var
proxy = "http://localhost:3000"
proxy = "http://39.105.176.215:49999"
var
proxy = "http://localhost:3000";
proxy = "http://osredmforge.educoder.net";
const requestMap = {};
window.setfalseInRequestMap = function (keyName) {
@ -77,7 +70,7 @@ export function initAxiosInterceptors(props) {
setpostcookie()
clearAllCookie()
if (config.url.indexOf(proxy) !== -1 || config.url.indexOf(':') !== -1) {
if (config.url.indexOf(proxy) !== -1) {
return config
}
requestProxy(config)
@ -109,12 +102,10 @@ export function initAxiosInterceptors(props) {
});
axios.interceptors.response.use(function (response) {
// console.log(".............")
if (response === undefined) {
return
}
const config = response.config
const config = response.config;
if (response.data.status === -1) {
if (window.location.pathname.startsWith('/tasks/')) {
props.showSnackbar(response.data.message || '服务器异常,请联系管理员。')
@ -127,12 +118,10 @@ export function initAxiosInterceptors(props) {
},
});
}
throw new axios.Cancel('Operation canceled by the user.');
}
if (response.data.status === 403 || response.data.status === "403") {
locationurl('/403');
}
@ -159,8 +148,6 @@ export function initAxiosInterceptors(props) {
message501 = false
}, 2000);
}
requestMap[response.config.url] = false;
setpostcookie();
return response;

View File

@ -1,7 +1,4 @@
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Spin } from 'antd';
class Loading extends Component {
@ -12,7 +9,6 @@ class Loading extends Component {
}
render() {
// Loading
return (
<div className="App" style={{ minHeight: '800px', width: "100%" }}>
<style>

View File

@ -68,7 +68,7 @@ export function appendFileSizeToUploadFile(item) {
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
}
export function appendFileSizeToUploadFileAll(fileList) {
return fileList.map(item => {
return fileList && fileList.map(item => {
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
}

View File

@ -6,18 +6,33 @@ const { Search } = Input;
const $ = window.$;
const isDev = window.location.port == 3007;
const isdev2= window.location.hostname ==='www.educoder.net'
export const TEST_HOST = "https://testforgeplus.trustie.net/"
export const TEST_HOST = "http://39.105.176.215:49999"
export function getImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net/'
const local = 'http://39.105.176.215:49999';
if (isDev) {
return `${local}/${path}`
}
return `/${path}`;
}
export function getImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'http://39.105.176.215:49999';
if(path.indexOf("http://")===-1){
if (isDev) {
return `${local}/images/${path}`
}
return `/${path}`;
}else{
return path;
}
}
export function getcdnImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
@ -78,7 +93,7 @@ export function setImagesUrl(path){
}
export function getUrl(path, goTest) {
const local = 'https://testforgeplus.trustie.net'
const local = 'http://39.105.176.215:49999'
if (isDev) {
return `${local}${path?path:''}`
}
@ -147,7 +162,7 @@ export function getmyUrl(geturl) {
}
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`;
return `${getUrl()}/api/attachments.json`;
}
export function getUploadLogoActionUrl() {

View File

@ -38,13 +38,11 @@ export const formatDelta = (deltas) => {
alt="${alt}"
/>
`;
// text = "<img src="+url+" width='60px' height='30px' onclick='' alt="+alt+"/>";
}
}
formatted.push(text);
});
console.log(formatted);
return formatted.join('');
}

View File

@ -4,7 +4,7 @@
export {
getUploadLogoActionUrl as getUploadLogoActionUrl,
getImageUrl as getImageUrl, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl
} from './UrlTool';
@ -76,10 +76,4 @@ export { default as AliyunUploader } from './components/media/AliyunUploader'
export { default as ImageLayer2 } from './hooks/ImageLayer2'
// 外部
export { default as CBreadcrumb } from '../modules/courses/common/CBreadcrumb'
export { CNotificationHOC as CNotificationHOC } from '../modules/courses/common/CNotificationHOC'
export { default as ModalWrapper } from '../modules/courses/common/ModalWrapper'
export { default as NoneData } from '../modules/courses/coursesPublic/NoneData'
export { default as WordNumberTextarea } from '../modules/modals/WordNumberTextarea'

View File

@ -48,15 +48,15 @@ function buildToc(coll, k, level, ctx) {
});
ctx.push("</ul>")
}
ctx.push("</li>")
ctx.push("</li>");
k = buildToc(coll, k, level, ctx)
return k
}
export function getTocContent() {
buildToc(toc, 0, 0, ctx)
ctx.push("</ul>")
return ctx.join("")
buildToc(toc, 0, 0, ctx);
ctx.push("</ul>");
return ctx.join("");
}
const tokenizer = {
@ -157,7 +157,6 @@ renderer.heading = function (text, level, raw) {
})
return '<h' + level + ' id="' + anchor + '">' + text + '</h' + level + '>'
}
marked.setOptions({
silent: true,
smartypants: true,

View File

@ -1,37 +1,58 @@
import React, { useEffect, useRef, useMemo } from "react";
import "katex/dist/katex.min.css";
import { renderToString } from 'katex';
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from "../common/marked";
import React, { useEffect, useRef, useMemo } from 'react'
import 'katex/dist/katex.min.css'
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from '../common/marked';
import 'code-prettify'
import dompurify from 'dompurify';
import { renderToString } from 'katex'
const preRegex = /<pre[^>]*>/g
function _unescape(str) {
let div = document.createElement('div')
div.innerHTML = str
return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue;
return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue
}
export default ({ value = '', className, style = {} }) => {
let str = String(value)
export default ({
value = '',
className,
style = {},
url
}) => {
let str = String(value);
const html = useMemo(() => {
let rs = marked(str)
const math_expressions = getMathExpressions()
let rs = marked(str);
const math_expressions = getMathExpressions();
if (str.match(/\[TOC\]/)) {
rs = rs.replace("<p>[TOC]</p>", getTocContent())
cleanToc()
}
rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
const { type, expression } = math_expressions[capture]
return renderToString(_unescape(expression), { displayMode: type === 'block', throwOnError: false, output: 'html' })
return renderToString(_unescape(expression) || '', { displayMode: type === 'block', throwOnError: false, output: 'html' })
})
rs = rs.replace(/▁/g, "▁▁▁")
resetMathExpressions()
return rs
}, [str])
return dompurify.sanitize(rs)
}, [str]);
const el = useRef()
// #id
useEffect(()=>{
if(url && url.hash && html){
let u = url.hash;
if(u){
let id = decodeURIComponent(u.split("#")[1]);
let ele = document.getElementById(id);
if(ele){
window.scrollTo(0, ele.offsetTop + 220);
}
}
}
},[url])
const el = useRef();
function onAncherHandler(e) {
let target = e.target
if (target.tagName.toUpperCase() === 'A') {
@ -40,7 +61,7 @@ export default ({ value = '', className, style = {} }) => {
e.preventDefault()
let viewEl = document.getElementById(ancher.replace('#', ''))
if (viewEl) {
viewEl.parentNode.scrollTop = viewEl.offsetTop
viewEl.scrollIntoView(true)
}
}
}
@ -61,6 +82,12 @@ export default ({ value = '', className, style = {} }) => {
}
}
}, [html, el.current, onAncherHandler])
return (<div ref={el} style={style} className={`${className ? className : ''} markdown-body`} dangerouslySetInnerHTML={{ __html: html }}></div>)
return (
<div
ref={el}
style={style}
className={`${className ? className : ''} markdown-body`}
dangerouslySetInnerHTML={{ __html: html }}
></div>
)
}

135
src/forge/About/Index.jsx Normal file
View File

@ -0,0 +1,135 @@
import React , { useEffect , useState } from 'react';
import './index.scss';
import { Button } from 'antd';
import Upload from "../Upload/Index";
import UploadImg from "../Images/upload.png";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import { AlignCenterBetween } from '../Component/layout';
import axios from 'axios';
import RenderHtml from '../../components/render-html';
import Attachments from "../Upload/attachment";
function Index(props){
const [ attachments , setAttachments ] = useState(undefined);
const [ content , setContent ] = useState(undefined);
const [ edit , setEdit ] = useState(false);
const [ fileList , setFileList ] = useState(undefined);
const [ editOpration , setEditOpration ] = useState(false);
const { owner , projectsId } = props.match.params;
const { isManager , isDeveloper , current_user } = props;
useEffect(()=>{
if(owner && projectsId){
Init();
}
},[owner,projectsId])
useEffect(()=>{
if( (current_user && current_user.login) && (isManager === true || isDeveloper === true)){
setEditOpration(true);
}
},[isManager , isDeveloper])
function Init(){
const url = `/${owner}/${projectsId}/about.json`;
axios.get(url).then(result=>{
if(result){
setContent(result.data.content);
setAttachments(result.data.attachments);
}
}).catch(error=>{})
}
function editContent(){
setEdit(true);
}
function onContentChange(value){
setContent(value);
};
function UploadFunc(fileList){
setFileList(fileList);
};
function sureSubmit(){
const url = `/${owner}/${projectsId}/about.json`;
axios.post(url,{
content,attachment_ids:fileList
}).then(result=>{
if(result){
props.showNotification("项目主页编辑成功!");
Init();
setEdit(false);
}
}).catch(error=>{})
}
return(
<div className="aboutPanels">
<div className="aboutContent">
<AlignCenterBetween style={{padding:"14px 0px"}}>
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目简介</span>
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
</AlignCenterBetween>
{
edit ?
<div>
<MDEditor
placeholder={"请输入描述信息"}
height={500}
mdID={"order-new-description"}
initValue={content}
onChange={onContentChange}
className="mt20"
></MDEditor>
<div className="pb20">
<Upload
className="commentStyle mt20"
isComplete={true}
load={UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
size={100}
showNotification={props.showNotification}
/>
{attachments && attachments.length > 0 &&
<Attachments
attachments={attachments}
showNotification={props.showNotification}
canDelete={true}
></Attachments>
}
</div>
<div className="pb30">
<Button type="primary" onClick={sureSubmit}>确定</Button>
<Button className="ml30" onClick={()=>setEdit(false)}>取消</Button>
</div>
</div>
:
<div style={{padding:"20px 0px"}}>
{content ?
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
:
<div>暂无简介~</div>
}
{attachments && attachments.length > 0 &&
<Attachments
attachments={attachments}
showNotification={props.showNotification}
></Attachments>
}
</div>
}
</div>
</div>
)
}
export default Index;

View File

@ -0,0 +1,13 @@
.aboutPanels{
max-width: 1200px;
margin:0px auto;
.aboutContent{
border-radius: 2px;
border: 1px solid #EEEEEE;
padding:0px 30px;
width:100%;
background-color: #fff;
margin-top:20px;
margin-bottom: 30px;
}
}

View File

@ -177,7 +177,7 @@ class Activity extends Component{
}
</div>
:
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
}
</Spin>
{

View File

@ -32,7 +32,7 @@ class ActivityItem extends Component {
</p >
}
<p className="itemLine mt10">
<Link to={`/users/${item && item.login}`} className="show-user-link">
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>

View File

@ -101,6 +101,7 @@
height: 22px;
line-height: 22px;
border-radius: 50%;
width: 22px;
}
.change{
color: black;

View File

@ -4,7 +4,7 @@ import './branch.css';
import { getBranch , getTag } from '../GetData/getData';
export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
const [ showValue , setShowValue ] = useState(branch);
const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
@ -17,10 +17,11 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
useEffect(()=>{
setShowValue(branch);
},[branch])
useEffect(()=>{
document.body.addEventListener('click', e => {
let name = e.target.className;
let turn = name == "ant-input OptionsInput" || name == "navli active"|| name == "navli" || name == "padding10 bor-bottom-greyE";
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
if(turn){
return;
}else{
@ -30,8 +31,12 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
})
useEffect(()=>{
getBranchs(projectsId,owner);
},[projectsId])
if(branchList){
setData(branchList);
setDatas(branchList);
setIsSpin(false);
}
},[branchList])
async function getBranchs(id,owner){
@ -63,7 +68,7 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
}
}
function chooseitem(value){
setShowValue(value);
// setShowValue(value);
changeBranch(value);
}
@ -77,8 +82,8 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
onChange={changeInputValue} style={{width:"220px"}}
/>
<ul className="navUl">
<li className={nav==0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
<li className={nav==1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li>
<li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
</ul>
</div>
<Spin spinning={isSpin}>

View File

@ -51,7 +51,7 @@
display: flex;
align-items: center;
cursor: pointer;
width: 240px;
min-width: 240px;
}
.branch-tagBox-list .ant-popover-arrow{
display: none;

View File

@ -8,6 +8,10 @@ li.ant-menu-item{
margin:0px!important;
border-bottom: 1px solid #eee;
}
.flags{
border: 1px solid red;
border-radius: 5px;
}
// Cards
.cards{
display: flex;
@ -72,6 +76,7 @@ li.ant-menu-item{
border-radius:11px;
color: #fff;
margin-left: 5px;
font-size: 12px;
&.running{
background:#5091FF;
color: #F1F8FF;
@ -88,6 +93,10 @@ li.ant-menu-item{
background:#F73030;
color:#FCEEEE ;
}
&.killed{
background:#eee;
color:#999 ;
}
}
.handleBox{
position: fixed;
@ -95,6 +104,7 @@ li.ant-menu-item{
right:240px;
z-index: 10000;
}
@media screen and (max-width: 1800px){
.handleBox{
right:190px;

View File

@ -1,12 +1,10 @@
import React from 'react';
import styled from 'styled-components';
export default ({title , value , className})=>{
const Keys = styled.span`
display:flex;
align-item:center;
align-items:center;
& span{
display:block;
height:20px;

View File

@ -0,0 +1,24 @@
import React from 'react';
import { Modal , Button } from 'antd';
import './Component.scss';
function Modals({visible,title,content,onOk,onCancel}){
return(
<Modal
className="modalsStyle"
visible={visible}
title={title}
onCancel={onCancel}
closable={true}
footer={
<div>
<Button onClick={onCancel}>取消</Button>
<Button type={"primary"} style={{marginLeft:"20px"}} onClick={onOk}>确定</Button>
</div>
}
>
<div style={{fontSize:"16px"}}>{content}</div>
</Modal>
)
}
export default Modals;

View File

@ -0,0 +1,61 @@
import React , { useState , useEffect } from 'react';
import { Select } from 'antd';
import { getUrl } from 'educoder';
import axios from 'axios';
const Option = Select.Option;
export default (({ language , select_language })=>{
const [ six , setSix ] = useState(undefined);
const [ languages , setLanguage ] = useState(undefined);
useEffect(()=>{
const url = '/ci/languages.json';
axios.get(url).then(result=>{
if(result){
setLanguage(result.data);
}
}).catch(error=>{
console.log(error);
})
},[])
function changelanguage(value){
let array = value ? languages.filter(item=>item.name === value) :undefined;
select_language(value,array && array[0]);
}
useEffect(()=>{
const url = '/ci/languages/common.json';
axios.get(url).then(result=>{
if(result){
setSix(result.data);
}
}).catch(error=>{
console.log(error);
})
},[])
return(
<React.Fragment>
{
six &&
<ul className="language">
{
six.map((item,key)=>{
return(
key < 6 ? <li className={language ===item.name ? "active":""} onClick={()=>changelanguage(item.name)}><img alt="" src={item.cover_url && getUrl(item.cover_url)} /></li> : ""
)
})
}
</ul>
}
<Select showSearch={true} placeholder={"请选择文本语言"} style={{ width: 200 }} value={language} onChange={changelanguage}>
<Option value={undefined}>请选择文本语言</Option>
{languages && languages.map((item, key) => {
return <Option value={item.name}>{item.name}</Option>;
})}
</Select>
</React.Fragment>
)
})

View File

@ -3,42 +3,54 @@ import './Component.scss';
export const Tags = (status)=>{
switch(status){
case 1:
case "running":
return(
<span className="statusColor running">运行中</span>
);
case 2:
case "failure":case"error":
return (
<span className="statusColor failed">未通过</span>
);
case 3:
case "success":
return (
<span className="statusColor pass">已通过</span>
);
default:
case "pending":
return (
<span className="statusColor Preparing">准备中</span>
);
case 'killed':
return (
<span className="statusColor killed">已撤销</span>
);
}
}
export const TagsLine = (status)=>{
switch(status){
case 1:
case "running":
return(
<span className="statuslineColor running">运行中</span>
);
case 2:
case "failure":case "error":
return (
<span className="statuslineColor failed">未通过</span>
);
case 3:
case "success":
return (
<span className="statuslineColor pass">已通过</span>
);
default:
case "pending":
return (
<span className="statuslineColor Preparing">准备中</span>
);
case 'killed':
return (
<span className="statuslineColor killed">已撤销</span>
);
case 'skipped':
return (
<span className="statuslineColor skipped">已跳过</span>
);
}
}
}

View File

@ -0,0 +1,46 @@
import React ,{ useState } from 'react';
import { Modal , Input , Spin } from 'antd';
import { AlignCenter } from "./layout";
import axios from 'axios';
import './Component.scss';
function PasswordAuthority({ authorityValBox , successFunc , cancelFunc }){
const [ authorityVal , setAuthorityVal ] = useState(undefined);
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
const [ isSpin , setIsSpin ] = useState(false);
// -
function cancelAuthority(){
setAuthorityVal(undefined);
cancelFunc();
}
//
function okAuthority(){
if(!authorityVal){
setAuthorityValFlag(true);
return;
}
setIsSpin(true);
const url = `/users/ci/oauth_grant.json`;
axios.get(url,{
params:{password:authorityVal}
}).then(result=>{
setIsSpin(false);
if(result){
successFunc(result.data.step);
}
}).catch(error=>{setIsSpin(false);});
}
return(
<Modal visible={authorityValBox} centered={true} title="授权" onCancel={cancelAuthority} onOk={okAuthority}>
<Spin spinning={isSpin}>
<p style={{textAlign:"center"}}>请输入您的登录密码确认授权DevOps应用</p>
<AlignCenter style={{justifyContent:"center",marginTop:"20px"}}>
<span>密码</span>
<Input.Password value={authorityVal} className={authorityValFlag===true && "flags"} onChange={(e)=>setAuthorityVal(e.target.value)} style={{width:"220px"}}></Input.Password>
</AlignCenter>
</Spin>
</Modal>
)
}
export default PasswordAuthority;

View File

@ -1,27 +1,66 @@
import React , { forwardRef , useCallback } from 'react';
import activate from '../Images/activate.png';
import { Blueback } from '../Component/layout';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { Form , Input } from 'antd';
import axios from 'axios';
import React, { forwardRef, useCallback, useState , useEffect } from "react";
import activate from "../Images/activate.png";
import { Blueback , AlignCenter } from "../Component/layout";
import PasswordAuthority from "../Component/PasswordAuthority";
import styled from "styled-components";
import { Form, Input , Spin , Modal } from "antd";
import axios from "axios";
const P = styled.p`{
width:200px;
line-height:30px;
font-size:16px;
color:#333;
text-align:center;
margin-top:30px;
margin-bottom:30px!important;
}`;
function About( props , ref){
const { form: { getFieldDecorator , validateFields } } = props;
const P = styled.p`
{
width: 230px;
line-height: 30px;
font-size: 16px;
color: #333;
text-align: center;
margin-top: 30px;
margin-bottom: 30px !important;
}
`;
function About(props, ref) {
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
const [isSpining, setIsSpining] = useState(true);
const [ authorityValBox , setAuthorityValBox ] = useState(false);
const [ authorityVal , setAuthorityVal ] = useState(undefined);
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
//0: devops
//1:
const [step, setStep] = useState(undefined);
// step1true
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const AuthorLogin = props.author && props.author.login;
const CurrentLogin = props.current_user && props.current_user.login;
useEffect(()=>{
if(CurrentLogin === AuthorLogin){
auth('get');
}else{
setIsSpining(false);
}
},[AuthorLogin,CurrentLogin])
function auth(type){
const url = `/${owner}/${projectsId}/ci_authorize.json`;
axios({
method:`${type}`,
url
}).then(result=>{
if(result && result.data ){
setIsSpining(false);
setStep(result.data.step);
setFieldsValue({...result.data.cloud_account});
}
}).catch(error=>{
console.log(error);
})
}
const helper = useCallback(
(label, name, rules, widget, isRequired) => (
<React.Fragment>
<span className={isRequired?"required":""}>{label}</span>
<span className={isRequired ? "required" : ""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
@ -29,52 +68,122 @@ function About( props , ref){
),
[]
);
function startActive(){
let projectsId = props.match.params.projectsId;
validateFields((error,values)=>{
if(!error){
const url = `/dev_ops/cloud_accounts.json`;
axios.post(url,{
...values,
project_id:projectsId
}).then(result=>{
if(result && result.data.redirect_url){
window.location.href = result.data.redirect_url;
}
}).catch(error=>{
console.log(error);
})
//
function goStep() {
validateFields((error, values) => {
if (!error) {
if(step > 0){
setAuthorityValBox(true);
}else{
setIsSpining(true);
const url = `/${owner}/${projectsId}/cloud_accounts.json`;
axios.post(url, {...values,ip_num:values.ip}).then((result) => {
setIsSpining(false);
if (result && result.data.redirect_url) {
props.showNotification("服务器信息配置完成!");
setStep(1);
setAuthorityValBox(true);
}
})
.catch((error) => {
console.log(error);
setIsSpining(false);
});
}
}
});
}
//
function startActive(){
setIsSpining(true);
const url = `/${owner}/${projectsId}/activate.json`;
axios.post(url).then(result=>{
setIsSpining(false);
if(result && result.data.status === 0){
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
// open_devops
let { changeOpenDevops } = props;
changeOpenDevops && changeOpenDevops(true);
}
}).catch(error=>{
console.log(error);
setIsSpining(false);
})
}
return(
<div className="activatePanel">
<img src={activate} alt="" width="250px"/>
<P>定义DevOps工作流帮助您检测bug发布代码</P>
<Link to={""} style={{color:"#5091FF",marginBottom:"20px"}}>了解什么是DevOps</Link>
<Form>
{helper(
"服务器IP地址",
"ip_num",
[{ required: true, message: "请输入服务器IP地址" }],
<Input placeholder="请输入服务器IP地址" style={{width:"368px"}} size="large" />,true
)}
{helper(
"服务器用户名:",
"account",
[{ required: true, message: "请输入服务器用户名" }],
<Input placeholder="请输入服务器用户名" size="large" />,true
)}
{helper(
"服务器密码:",
"secret",
[{ required: true, message: "请输入服务器密码" }],
<Input.Password placeholder="请输入服务器密码" size="large" />,true
)}
</Form>
<Blueback onClick={startActive}>开始激活</Blueback>
</div>
)
// -
function cancelAuthority(){
setAuthorityValBox(false);
}
//
function okAuthority(step){
setAuthorityValBox(false);
setStep(step);
}
return (
<Spin spinning={isSpining}>
<PasswordAuthority authorityValBox={authorityValBox} successFunc={okAuthority} cancelFunc={cancelAuthority}></PasswordAuthority>
<div className="activatePanel">
<img src={activate} alt="" width="250px" />
<P>定义DevOps工作流帮助您检测bug发布代码</P>
{
CurrentLogin !== AuthorLogin && (step === undefined || (step && step < 1)) &&
<div className="noOperation">DevOps开启功能暂未对项目创建者以外的角色开放可以联系项目创建者进行开启开启后便可查看构建信息</div>
}
<a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}>
了解什么是DevOps
</a>
<a href={"https://forum.trustie.net/forums/3110/detail"} target="_blank" style={{ color: "#5091FF"}}>
如何使用DevOps
</a>
{
AuthorLogin === CurrentLogin ?
<React.Fragment>
{ step <=1 ?
<React.Fragment>
<Input.Password style={{display:'none'}} size="large" />
<Form style={{marginTop:"20px"}}>
<p className="mb20" style={{width:"370px"}}>请仔细核对您的服务器信息一旦确认提交将无法修改</p>
{helper(
"服务器IP地址",
"ip",
[{ required: true, message: "请输入服务器IP地址" }],
<Input
placeholder="请输入服务器IP地址"
style={{ width: "368px" }}
size="large"
disabled={step > 0}
/>,
true
)}
{helper(
"服务器用户名:",
"account",
[{ required: true, message: "请输入服务器用户名" }],
<Input placeholder="请输入服务器用户名" size="large" disabled={step > 0}/>,
true
)}
{helper(
"服务器密码:",
"secret",
[{ required: true, message: "请输入服务器密码" }],
<Input.Password placeholder="请输入服务器密码" size="large" disabled={step > 0}/>,
true
)}
</Form>
<Blueback onClick={goStep}>下一步</Blueback>
</React.Fragment>
:""}
{step > 1 &&
<div style={{textAlign:'center',marginTop:"20px"}}>
<Blueback onClick={startActive} className="mt20">开始激活</Blueback>
</div>
}
</React.Fragment>
:""
}
</div>
</Spin>
);
}
export default Form.create()(forwardRef(About));
export default Form.create()(forwardRef(About));

View File

@ -1,53 +1,45 @@
import React , { useState , useEffect } from 'react';
import { Spin } from 'antd';
import { Blueback } from '../Component/layout';
import Editor from "react-monaco-editor";
import Modals from './DisposeModal';
import FileLanguage from '../Component/FileLanguage';
import FileLanguage from '../Component/OpsFileLanguage';
import axios from 'axios';
function Dispose(props){
const [ info , setInfo ] = useState(undefined);
const [ spining , setSpining ] = useState(true);
const [ info , setInfo ] = useState('.trustie-pipeline.yml');
const [ visible , setVisible ] = useState(false);
const [ ymlValue , setYmlValue ] = useState("");
const [ six , setSix ] = useState(undefined);
const [ sha , setSha ] = useState(undefined);
const [ fileLanguage , setFileLanguage ] = useState(undefined);
const [ first , setFirst ] = useState(false);
let projectsId = props.match.params.projectsId;
let owner = props.match.params.owner;
useEffect(()=>{
if(projectsId){
const url = '/dev_ops/builds/get_trustie_pipeline.json';
const url = `/${owner}/${projectsId}/get_trustie_pipeline.json`;
axios.get(url,{
params:{
project_id:projectsId
}
}).then(result=>{
if(result && result.data.content){
setInfo(result.data);
setInfo(result.data.name);
setYmlValue(result.data.content);
setFirst(true);
setSha(result.data.sha);
}else{
setFirst(false);
}
setSpining(false);
}).catch(error=>{
console.log(error);
})
}
},[])
useEffect(()=>{
const url = '/dev_ops/languages/common.json';
axios.get(url).then(result=>{
if(result){
setSix(result.data);
}
}).catch(error=>{
console.log(error);
})
},[])
},[projectsId])
//
function changeEditor(value){
@ -57,25 +49,25 @@ function Dispose(props){
//
function select_language(value,array){
setFileLanguage(value);
// console.log(array);
setYmlValue( array && array.content);
}
//
function submit(){
let url = '';
const { defaultBranch } = props;
let params = {
branch: "master",
branch: defaultBranch,
content:ymlValue,
filepath:info && info.name,
filepath:info,
message:''
}
if(first){
// true
url = `/${owner}/${projectsId}/update_file.json`;
url = `/${owner}/${projectsId}/update_trustie_pipeline.json`;
axios.put(url,{
...params,
sha:info && info.sha
sha
}).then(result=>{
if(result){
setVisible(true);
@ -95,37 +87,24 @@ function Dispose(props){
}
}
function suresubmit(){
props.history.push(`/projects/${owner}/${projectsId}/ops/list`);
setVisible(false);
props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
}
return(
<React.Fragment>
<Spin spinning={spining}>
<Modals visible={visible} closeFunc={(flag)=>setVisible(flag)} sureFunc={suresubmit}></Modals>
<p>编程语言</p>
{
six &&
<ul className="language">
{
six && six.map((item,key)=>{
return(
key < 6 ? <li><img alt="" src={item.cover_url} /></li> : ""
)
})
}
</ul>
}
<div className="mt20 mb20">
<FileLanguage language={fileLanguage} select_language={select_language}/>
</div>
<p>配置脚本</p>
<div className="editorBody">
<p className="editorHead">
<span>{info && info.name}</span>
<a><i className="iconfont icon-bianji6 font-14"></i></a>
</p>
<p className="editorHead">{info}</p>
<Editor
height="300px"
language={"java"}
language={"yml"}
theme={"vs-grey"}
defaultValue="请输入内容"
value={ymlValue}
@ -134,7 +113,7 @@ function Dispose(props){
></Editor>
</div>
<Blueback onClick={submit}>确定提交</Blueback>
</React.Fragment>
</Spin>
)
}
export default Dispose;

View File

@ -8,7 +8,7 @@ const Div = styled.div`{
text-align:center;
color:#333;
}`
export default (({visible , closeFunc , suresubmit})=>{
export default (({visible , closeFunc , sureFunc})=>{
return(
<Modal
title="提示"
@ -17,7 +17,7 @@ export default (({visible , closeFunc , suresubmit})=>{
footer={
<div>
<Button onClick={()=>closeFunc(false)}>取消</Button>
<Button type={"primary"} onClick={suresubmit} style={{marginLeft:"20px"}}>确定</Button>
<Button type={"primary"} onClick={()=>sureFunc()} style={{marginLeft:"20px"}}>确定</Button>
</div>
}
onCancel={()=>closeFunc(false)}

View File

@ -1,4 +1,4 @@
import React from 'react';
import React , { useEffect } from 'react';
import { WhiteBack } from '../Component/layout';
import './ops.scss';
@ -15,20 +15,33 @@ const Infos = Loadable({
loading: Loading,
})
export default ((props)=>{
const { projectsId , owner } = props.match.params;
const open_devops = props.projectDetail && props.projectDetail.open_devops;
//
useEffect(()=>{
if(open_devops !== undefined){
if(open_devops){
props.history.replace(`/projects/${owner}/${projectsId}/devops/list`);
}else{
props.history.replace(`/projects/${owner}/${projectsId}/devops`);
}
}
},[open_devops])
return(
<WhiteBack className="opsPanel">
<Switch {...props}>
<Route path="/projects/:projectsId/ops/dispose"
<Route path="/projects/:owner/:projectsId/devops/dispose"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops/list"
<Route path="/projects/:owner/:projectsId/devops/list"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops"
<Route path="/projects/:owner/:projectsId/devops"
render={
() => (<About {...props} />)
}

View File

@ -1,4 +1,4 @@
import React , { useEffect , useState } from 'react';
import React , { useEffect , useState , useRef } from 'react';
import { Banner } from '../Component/layout';
import { Link } from 'react-router-dom';
@ -11,27 +11,46 @@ const Div = styled.div`{
padding:24px 30px;
}`;
export default ((props)=>{
const [ menu , setMenu ] = useState(undefined);
const [ menu , setMenu ] = useState(false);
const [ permission , setPermission ] = useState("");
const childRef = useRef();
const path = props.location.pathname;
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const projectDetail = props.projectDetail;
useEffect(()=>{
// console.log(props.match.params.projectsId)
if(path === `/projects/${props.match.params.projectsId}/ops/list`){
if(path === `/projects/${owner}/${projectsId}/devops/list`){
setMenu(true);
}else{
setMenu(false);
}
},[path])
useEffect(()=>{
if(projectDetail){
setPermission(props.projectDetail.permission);
}
},[projectDetail])
const updateChildState = () => {
// changeVal
if (childRef.current) {
childRef.current.changeVal();
}
}
return(
<div className="disposePanel">
<Banner>
<Link to={`/projects/${props.match.params.projectsId}/ops/dispose`}>工作流配置</Link>
{ menu ? <Link to={`/projects/${props.match.params.projectsId}/ops/list`} style={{ marginLeft:"66px",color:"#5091FF" }}>构建列表</Link>:""}
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`} className={menu===false && "color-blue"} style={{ marginRight:"66px"}}>工作流配置</Link>}
<Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/list`}className={menu===true && "color-blue"}>构建列表</Link>
{ menu===true && <a onClick={updateChildState} style={{float:"right",fontSize:"14px",color:"#FF6E21",marginTop:"5px"}}>刷新</a>}
</Banner>
<Div>
{ menu && menu === true && <Structure {...props}/> }
{ menu && menu === false && <Dispost {...props}/> }
{ menu === true && <Structure {...props} wrappedComponentRef={(form) => childRef.current = form} ref={childRef}/> }
{ menu === false && permission !=="Reporter" && <Dispost {...props}/> }
</Div>
</div>
)

View File

@ -1,42 +1,127 @@
import React from 'react';
import { FlexAJ , Blueline , AlignCenter } from '../Component/layout';
import styled from 'styled-components';
import { Menu } from 'antd';
import { TagsLine } from '../Component/OpsStatus';
import React, { useEffect, useState } from "react";
import { FlexAJ, Blueline, AlignCenter } from "../Component/layout";
import styled from "styled-components";
import { Menu, Popconfirm } from "antd";
import { TagsLine } from "../Component/OpsStatus";
import { Time } from "../Utils/Time";
import { truncateCommitId } from "../common/util";
import { getUrl } from 'educoder';
const SubMenu = Menu.SubMenu;
const Img = styled.img`{
width:25px;
height:25px;
border-radius:50%;
margin-right:10px;
}`
export default (()=>{
return(
const Img = styled.img`
{
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 10px;
}
`;
export default ({ data, repeatSet , chooseSteps }) => {
const [tamp, setTamp] = useState(undefined);
const [sha, setSha] = useState(undefined);
useEffect(() => {
if (data && data.started) {
let t = parseInt(data.started) * 1000;
let time = Time(t);
setTamp(time);
}
if (data && data.after) {
setSha(truncateCommitId(data.after));
}
}, [data]);
function renderStatusBtn() {
let status = data && data.status;
let number = data && data.number;
if (status === "failure" || status === "error" || status === "success") {
return "";
}else if(status === "killed"){
return(
<Popconfirm
title="确认重新构建?"
onConfirm={(e) => repeatSet(e,'repeat',number)}
onCancel={(e)=>{e.stopPropagation()}}
cancelText="取消"
okText="确定"
>
<Blueline onClick={(e)=>{e.stopPropagation()}}>重新构建</Blueline>
</Popconfirm>
);
} else {
return (
<Popconfirm
title="确认撤销构建?"
onConfirm={(e) => repeatSet(e,'cancel',number)}
onCancel={(e)=>{e.stopPropagation()}}
cancelText="取消"
okText="确定"
>
<Blueline onClick={(e)=>{e.stopPropagation()}}>撤销构建</Blueline>
</Popconfirm>
);
}
}
function clickSub(e,stageN,stepN){
chooseSteps(stageN,stepN);
}
return (
<div>
<FlexAJ className="leftheader">
<AlignCenter>
<Img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2091711702,2468700162&fm=111&gp=0.jpg"/>
<span className="nest">开始时间<span>2020.07.10 15:30</span></span>
<span className="nest">运行时间<span>20s</span></span>
<Img src={getUrl(`/images/${data && data.author && data.author.image_url}`)} />
{data && data.started &&
<span className="nest">
开始时间<span> {data.started}</span>
</span>
}
{
data && data.duration_time &&
<span className="nest">
运行时间<span>{data.duration_time}</span>
</span>
}
</AlignCenter>
<Blueline>重新创建</Blueline>
{renderStatusBtn()}
</FlexAJ>
<div className="leftMainContent">
<AlignCenter className="contentBranch">
<i className="iconfont icon-fenzhi1"></i>
<span>分支</span>
<span className="branchname">master</span>
<span className="branchsha">8b3476f5</span>
<span className="branchname">{data && data.branch_target}</span>
<span className="branchsha">{data && truncateCommitId(data.build_after_sha)}</span>
</AlignCenter>
</div>
<Menu mode='inline' className="leftMenu">
<SubMenu title={<div><i className="iconfont icon-gongzuoliu font-14 mr4"></i><span>CI</span></div>}>
<Menu.Item>
<FlexAJ><span>Build setup 01 {TagsLine(1)}</span><span>20s</span></FlexAJ>
</Menu.Item>
</SubMenu>
<Menu mode="inline" className="leftMenu" defaultOpenKeys={[`0`]} defaultSelectedKeys={[`0`]}>
{data && data.stages ? data.stages.map((item, key) => {
return item.steps && item.steps.length > 0 ?
<SubMenu
title={
<div>
<i className="iconfont icon-gongzuoliu font-14 mr4"></i>
<span>{item.name}</span>
</div>
}
key={`${key}`}
>
{item.steps.map((i, k) => {
return (
<Menu.Item key={`${k}`} onClick={(e)=>clickSub(e,item.number,i.id)}>
<FlexAJ>
<span>
{i.name} {i.status ? TagsLine(i.status) : ""}
</span>
<span>{i.duration_time}</span>
</FlexAJ>
</Menu.Item>
);
})}
</SubMenu>
: "";
})
: ""}
</Menu>
</div>
)
})
);
};

View File

@ -1,21 +1,107 @@
import React from 'react';
import { FlexAJ , AlignCenter } from '../Component/layout';
import React, { useState, useEffect } from "react";
import { Spin } from "antd";
import { FlexAJ, AlignCenter } from "../Component/layout";
import axios from "axios";
export default (()=>{
return(
<div className="rightMainContent">
<div>
<FlexAJ className="items">
<span>Build setup 01</span>
<AlignCenter>20<i className="iconfont icon-triangle"></i></AlignCenter>
</FlexAJ>
export default ({
data,
stepN,
stageN,
projectId,
owner,
opsId,
rightSpin,
}) => {
const [coders, setCoders] = useState(undefined);
const [empty, setEmpty] = useState(false);
const [spining, setSpining] = useState(true);
const [stage, setStage] = useState(undefined);
const [step, setStep] = useState(undefined);
useEffect(() => {
setSpining(rightSpin);
}, [rightSpin]);
useEffect(() => {
if (data) {
let stages = data.stages;
if (stages && stages.length > 0) {
let pre = stageN
? stages.filter((item) => item.number === stageN)[0]
: stages[0];
setStage(pre);
let p = pre && pre.steps;
let sub = stepN
? p && p.length > 0 && p.filter((item) => item.id === stepN)[0]
: p[0];
setStep(sub);
if (sub && sub.status !== "skipped") {
getStep(pre.number, sub.number);
}
// skippedout
if(sub.status === "skipped"){
setCoders(undefined);
setEmpty(true);
setSpining(false);
}
} else {
setSpining(false);
}
}
}, [data, stageN, stepN]);
function getStep(stageN, stepN) {
if (stageN && stepN) {
const url = `/${owner}/${projectId}/builds/${opsId}/logs/${stageN}/${stepN}.json`;
axios.get(url).then((result) => {
if (result) {
setCoders(result.data);
setSpining(false);
}
})
.catch((error) => {
console.log(error);
});
}
}
return (
<Spin spinning={spining}>
<div className="rightMainContent">
{data && data.status !== "error" ? (
<div>
<FlexAJ className="items">
<span>{step && step.name}</span>
<AlignCenter>
{step && step.duration_time}
<i className="iconfont icon-sanjiaoxing-down"></i>
</AlignCenter>
</FlexAJ>
<div>
{coders && coders.length > 0 ? (
coders.map((item, key) => {
return (
<div className="opsDetailOut">
<span>{key + 1}</span>
<p>{item.out}</p>
</div>
);
})
) : empty ? (
<div className="opsDetailOut">
<span>1</span>
<p>
{stage && stage.name} {step && step.name}: Skipped
</p>
</div>
) : (
""
)}
</div>
</div>
) : (
<div style={{ color: "red" }}>error:{data && data.error}</div>
)}
</div>
<div>
<FlexAJ className="items"></FlexAJ>
</div>
<div>
<FlexAJ className="items"></FlexAJ>
</div>
</div>
)
})
</Spin>
);
};

View File

@ -1,240 +1,320 @@
import React , { useState , useEffect } from 'react';
import { FlexAJ , AlignCenter , Blueback } from '../Component/layout';
import { Table , Pagination } from 'antd';
import { truncateCommitId } from '../common/util';
import styled from 'styled-components';
import axios from 'axios';
import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "react";
import { FlexAJ, AlignCenter } from "../Component/layout";
import { Table, Pagination, Popconfirm } from "antd";
import { truncateCommitId } from "../common/util";
import {getUrl} from 'educoder';
import axios from "axios";
const STATUS = [
{name:"所有",value:"1"},
{name:"准备中",value:"2"},
{name:"运行中",value:"3"},
{name:"已完成",value:"4"}
]
const LIMIT = 15;
const datasource = [
{
status:2,
author:"caishi",
message:{
branch:"master",
sha:"8b3476f5",
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
},
begin:"2020-07-08",
run:"20s"
},
{
status:1,
author:"caishi",
message:{
branch:"master",
sha:"8b3476f5",
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
},
begin:"2020-07-08",
run:""
}
{ name: "所有"},
{ name: "运行中", value: "running" },
{ name: "已撤销", value: "killed" },
{ name: "构建失败", value: "failure" },
{ name: "已完成", value: "success" },
];
const LIMIT = 15;
function Structure(props,ref){
const [status, setStatus] = useState(undefined);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [data, setData] = useState(undefined);
const [tableLoading, setTableLoading] = useState(true);
const Img = styled.img`{
border-radius:50%;
margin-rigth:10px;
width:25px;
height:25px;
}`
export default ((props)=>{
const [ status ,setStatus ] = useState("1");
const [ page ,setPage ] = useState(1);
const [ total ,setTotal ] = useState(10);
const [ data , setData ] = useState(undefined);
let projectsId = props.match.params.projectsId;
let owner = props.match.params.owner;
const permission = props.projectDetail && props.projectDetail.permission;
let projectsId = props.match.params.projectsId;
useEffect(()=>{
if(projectsId){
const url ='/dev_ops/builds.json';
axios.get(url,{
params:{
project_id:projectsId
}
}).then(result=>{
if(result){
let list = result.data && result.data.map((item,key)=>{
return {
status:item.status,
author:item.sender,
message:{
branch:item.source,
image:item.author_avatar,
message:item.message,
sha:truncateCommitId(item.after)
},
started:item.started,
timestamp:item.timestamp
}
})
setData(list);
}
}).catch(error=>{
console.log(error);
})
useImperativeHandle(ref, () => ({
changeVal: () => {
setTableLoading(true);
Init();
}
},[])
}))
function ChangeStatus(value){
setStatus(value)
useEffect(() => {
if (projectsId) {
Init();
}
}, [page]);
let current_user = props.current_user;
function Init(status) {
const url = `/${owner}/${projectsId}/builds.json`;
axios.get(url,{
params:{
search:status,
page,limit:LIMIT
}
}).then((result) => {
if (result && result.data) {
let list = result.data.builds && result.data.builds.map((item, key) => {
return {
...item,
author:item.author && item.author.name,
message: {
branch: item.branch_target,
message: item.message,
sha: truncateCommitId(item.build_after_sha),
},
started: item.started || "--"
};
});
setTotal(result.data.total_count);
setData(list);
setTableLoading(false);
}
})
.catch((error) => {
console.log(error);
});
}
function ChangeStatus(value) {
setStatus(value);
Init(value);
}
//
function ChangePage(page){
setPage(page)
function ChangePage(page) {
setPage(page);
}
function renderStatus() {
return(
return (
<ul className="listNav">
{
STATUS.map((item,key)=>{
return <li onClick={()=>ChangeStatus(item.value)} className={ status === item.value ? "active":""}>{item.name}</li>
})
}
{STATUS.map((item, key) => {
return (
<li
onClick={() => ChangeStatus(item.value)}
className={status === item.value ? "active" : ""}
>
{item.name}
</li>
);
})}
</ul>
)
);
}
function renderStatusBtn(status){
if(status === "failure" || status ==="success"){
function renderStatusBtn(status, number) {
if (status === "error" || status === "success") {
return "";
}else if(status === "killed" || status === "failure"){
return(
<a className="color-blue">重新构建</a>
)
}else{
return(
<a className="color-red">撤销构建</a>
)
<Popconfirm
title="确认重新构建?"
onConfirm={(e) => repeatSet(e,number)}
onCancel={(e)=>{e.stopPropagation()}}
cancelText="取消"
okText="确定"
>
<a className="color-blue" onClick={(e)=>{e.stopPropagation()}}>重新构建</a>
</Popconfirm>
);
} else {
return (
<Popconfirm
title="确认撤销构建?"
onConfirm={(e) => cancelSet(e,number)}
onCancel={(e)=>{e.stopPropagation()}}
cancelText="取消"
okText="确定"
>
<a className="color-red" onClick={(e)=>{e.stopPropagation()}}>撤销构建</a>
</Popconfirm>
);
}
}
function renderTableStatus (status){
switch (status){
//
function repeatSet(e,number) {
e.stopPropagation();
setTableLoading(true);
const url = `/${owner}/${projectsId}/builds/${number}/restart.json`;
axios.post(url).then((result) => {
if (result) {
props.showNotification("工作流正在重新构建!");
Init();
}
})
.catch((error) => {
console.log(error);
});
}
//
function cancelSet(e,number) {
e.stopPropagation();
setTableLoading(true);
const url = `/${owner}/${projectsId}/builds/${number}/stop.json`;
axios.delete(url).then((result) => {
if (result) {
props.showNotification("撤销构建成功!");
Init(projectsId);
}
})
.catch((error) => {
console.log(error);
});
}
function renderTableStatus(status) {
switch (status) {
case "running":
return(
<span className="statusTag running"><i className="iconfont icon-yunhangzhong"></i>运行中</span>
);
case "failure":
return (
<span className="statusTag failed"><i className="iconfont icon-weitongguo"></i>未通过</span>
<span className="statusTag running">
<i className="iconfont icon-yunhangzhong"></i>运行中
</span>
);
case "failure": case 'error':
return (
<span className="statusTag failed">
<i className="iconfont icon-weitongguo"></i>未通过
</span>
);
case "success":
return (
<span className="statusTag pass"><i className="iconfont icon-yitongguo"></i>已通过</span>
<span className="statusTag pass">
<i className="iconfont icon-yitongguo"></i>已通过
</span>
);
default:
case 'killed':
return (
<span className="statusTag Preparing"><i className="iconfont icon-zhunbeizhong"></i>准备中</span>
<span className="statusTag killed">
<i className="iconfont icon-weitongguo"></i>已撤销
</span>
);
case 'pending':
return (
<span className="statusTag Preparing">
<i className="iconfont icon-zhunbeizhong"></i>准备中
</span>
);
}
}
function clickRows(event,e){
props.history.push(`/projects/${owner}/${projectsId}/devops/${e.number}/detail`);
}
const column = [
{
title:'序号',
dataIndex:"No",
key:"No",
width:"8%",
render:(item,value,key)=>{
return(
<span>#{key+1}</span>
)
}
title: "序号",
dataIndex: "number",
key: "number",
width: "8%",
render: ( value, item, key) => {
return <span>#{value}</span>;
},
},
{
title:'状态',
dataIndex:"status",
key:"status",
width:"12%",
render:(value,item,key)=>{
return(renderTableStatus(value))
}
title: "状态",
dataIndex: "status",
key: "status",
width: "12%",
render: (value, item, key) => {
return renderTableStatus(value);
},
},
{
title:'构建人',
dataIndex:"author",
key:"author",
width:"12%",
align:"center"
title: "构建人",
dataIndex: "author",
key: "author",
width: "12%",
align: "center",
},
{
title:'提交信息',
dataIndex:"message",
key:"message",
width:"30%",
render:(value,item,key)=>{
title: "提交信息",
dataIndex: "message",
key: "message",
width: "30%",
render: (value, item, key) => {
let meg = item.message;
return (
return (
<React.Fragment>
<div>
{ meg.branch && <span className="mr10 color-grey-8"><i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支{meg.branch}</span>}
{ meg.sha && <span className="color-orange">{meg.sha}</span>}
{meg.branch && (
<span className="mr10 color-grey-8">
<i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支
{meg.branch}
</span>
)}
{meg.sha && <span className="color-orange">{meg.sha}</span>}
</div>
<AlignCenter>
<Img src={meg.image} />
<div className="task-hide ml5" style={{maxWidth:"300px"}}>{meg.message}</div>
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} src={`${current_user && getUrl(`/images/${current_user.image_url}`)}`} />
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
{meg.message}
</div>
</AlignCenter>
</React.Fragment>
)
}
);
},
},
{
title:'开始时间',
dataIndex:"started",
key:"started",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || "--"}</span>
)
}
title: "开始时间",
dataIndex: "started",
key: "started",
width: "15%",
render: (value, item, key) => {
return <span>{value || "--"}</span>;
},
},
{
title:'运行时间',
dataIndex:"timestamp",
key:"timestamp",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || value === 0 ? `${value}s` : "--"}</span>
)
}
title: "运行时间",
dataIndex: "duration_time",
key: "duration_time",
width: "15%",
render: (value, item, key) => {
return <span>{value || "--"}</span>;
},
},
{
title:'操作',
dataIndex:"operation",
key:"operation",
render:(value,item,key)=>{
return(renderStatusBtn(item.status));
}
}
]
return(
title: "操作",
dataIndex: "operation",
key: "operation",
render: (value, item, key) => {
if(permission === "Admin" || permission === "Owner"){
return renderStatusBtn(item.status, item.number);
}else{
return "--";
}
},
},
];
return (
<div className="listPart">
<FlexAJ>
{renderStatus()}
<span>
<Blueback className="mr30">手动创建</Blueback>
<span className="mr30"><i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支</span>
<span><i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>标签</span>
</span>
{/* <Blueback>手动创建</Blueback> */}
{/* <span className="mr30">
<i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支
</span>
<span>
<i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>
标签
</span> */}
</FlexAJ>
<Table
onRow={(record,index)=>{
return{
onClick:(event)=>clickRows(event,record)
}
}}
columns={column}
className="normalTable"
dataSource={data}
pagination={false}
loading={tableLoading}
></Table>
{
total > LIMIT ?
<div style={{textAlign:'center',margin:"30px 50px"}}>
<Pagination showQuickJumper defaultCurrent={page} total={total} pageSize={LIMIT} onChange={ChangePage}></Pagination>
</div>:""
}
{total > LIMIT ?
<div style={{ textAlign: "center", margin: "30px 50px" }}>
<Pagination
showQuickJumper
defaultCurrent={page}
total={total}
pageSize={LIMIT}
onChange={ChangePage}
></Pagination>
</div>
:
"" }
</div>
)
})
);
};
export default forwardRef(Structure);

View File

@ -12,8 +12,14 @@
.disposePanel{
.language{
display: flex;
margin-bottom: 20px;
li{
margin-right: 20px;
cursor: pointer;
border:1px solid #fff;
&.active{
border:1px solid #5091FF;
}
}
}
.editorBody{
@ -36,6 +42,7 @@
top:7px;
}
.listPart{
min-height: 400px;
.listNav{
display: flex;
li{
@ -63,6 +70,7 @@
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:10px 5px;
color:#333;
cursor: pointer;
}
.ant-table-thead{
border:1px solid rgba(238,238,238,1)
@ -70,6 +78,9 @@
}
}
}
.ant-modal-close{
top:7px;
}
// 列表
.listPart{
.statusTag{
@ -103,8 +114,13 @@
border:1px solid #F73030;
color:#F73030 ;
}
&.killed{
background:#eee;
border:1px solid #999;
color:#999 ;
}
}
}
}
@ -205,6 +221,14 @@
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1);
}
&.killed{
border:1px solid #999;
color:#999;
}
&.skipped{
border:1px solid #d4d9de;
color:#798390;
}
}
}
&.rightSection{
@ -212,6 +236,8 @@
background-color: #081930;
.rightMainContent{
padding:24px 30px;
height:100vh;
overflow-y: auto;
& > div{
margin-bottom: 12px;
.items{
@ -264,4 +290,27 @@
cursor: col-resize;
}
}
}
.opsDetailOut{
display: flex;
color: #fff;
line-height: 22px;
align-items: flex-start;
margin-top: 5px;
&>span{
margin-right: 10px;
min-width: 20px;
text-align: left;
padding-left: 3px;
}
&>p{
margin-bottom: 0px;
}
}
.noOperation{
margin-bottom:20px;
width:380px;
text-align:center;
line-height:22px;
color:#666;
}

View File

@ -1,33 +1,114 @@
import React from 'react';
import './ops.scss';
import { FlexAJ, AlignCenter } from '../Component/layout';
import { Tags } from '../Component/OpsStatus';
import SplitPane from 'react-split-pane';
import LeftPanel from './OpsDetailLeftpanel';
import RightPanel from './OpsDetailRightpanel';
import React, { useEffect, useState, useRef, useContext } from "react";
import "./ops.scss";
import { FlexAJ, AlignCenter } from "../Component/layout";
import { Tags } from "../Component/OpsStatus";
import SplitPane from "react-split-pane";
import LeftPanel from "./OpsDetailLeftpanel";
import RightPanel from "./OpsDetailRightpanel";
import axios from "axios";
import { Spin } from "antd";
import { Link } from "react-router-dom";
export default (props) => {
const [data, setData] = useState(undefined);
const [stageN, setStageN] = useState(undefined);
const [stepN, setStepN] = useState(undefined);
const [rightSpin, setRightSpin] = useState(false);
const [spinning, setSpinning] = useState(true);
export default (()=>{
return(
<div className="opsDetailPanel">
<FlexAJ className="opsInfos">
<AlignCenter>
<span>#1</span>
<span className="ml10">将分支221063-improve-buy-ci-minutes-link合并到221063-improve-buy-ci-minutes-link"</span>
{Tags(1)}
</AlignCenter>
<a style={{color:"#ddd"}}><i className="iconfont icon-yiguanbi font-15 mr5"></i>退出</a>
</FlexAJ>
<div className="opsSection">
<SplitPane className="outer-split-pane" split="vertical" minSize={468} maxSize={-350} defaultSize="40%">
<section className="leftSection">
<LeftPanel />
</section>
<section className="rightSection">
<RightPanel />
</section>
</SplitPane>
let projectId = props.match.params.projectId;
let owner = props.match.params.owner;
let opsId = props.match.params.opsId;
useEffect(() => {
if (opsId && projectId) {
Init();
}
}, [opsId]);
function Init() {
const url = `/${owner}/${projectId}/builds/${opsId}.json`;
axios.get(url).then((result) => {
if (result && result.data) {
setSpinning(false);
setData(result.data);
}
})
.catch((error) => {
console.log(error);
setSpinning(false);
});
}
//
function repeatSet(e,type,number) {
if(type==="repeat"){
//
const url = `/${owner}/${projectId}/builds/${number}/restart.json`;
axios.post(url).then((result) => {
if (result && result.data) {
props.showNotification("工作流正在重新构建!");
props.history.push(`/projects/${owner}/${projectId}/devops/${result.data.number}/detail`);
}
})
.catch((error) => {
console.log(error);
});
}else{
//
const url = `/${owner}/${projectId}/builds/${number}/stop.json`;
axios.delete(url).then((result) => {
if (result) {
props.showNotification("撤销构建成功!");
Init();
}
})
.catch((error) => {
console.log(error);
});
}
}
function chooseSteps(pre,sub){
if(pre && sub){
setStepN(sub);
setStageN(pre);
setRightSpin(true);
}
}
return (
<Spin spinning={spinning}>
<div className="opsDetailPanel">
<FlexAJ className="opsInfos">
<AlignCenter>
<span>#{data && data.number}</span>
<span className="ml10">{data && data.message}</span>
{Tags(`${data && data.status}`)}
</AlignCenter>
<Link
style={{ color: "#ddd" }}
to={`/projects/${owner}/${projectId}/devops/list`}
>
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
</Link>
</FlexAJ>
<div className="opsSection">
<SplitPane
className="outer-split-pane"
split="vertical"
minSize={468}
maxSize={-350}
defaultSize="40%"
>
<section className="leftSection">
<LeftPanel data={data} repeatSet={repeatSet} chooseSteps={chooseSteps} />
</section>
<section className="rightSection">
<RightPanel data={data} rightSpin={rightSpin} stepN={stepN} stageN={stageN} owner={owner} projectId={projectId} opsId={opsId} />
</section>
</SplitPane>
</div>
</div>
</div>
)
});
</Spin>
);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -50,7 +50,6 @@ class Index extends Component {
)}
></Route>
<Route
exact
path="/projects"
render={(props) => (
<ProjectIndex {...this.props} {...props} />

View File

@ -32,9 +32,9 @@ export default ((props)=>{
return(
<li key={key}>
<div>
<Link to={`/projects/${owner}/${projectsId}?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
<Link to={`/projects/${owner}/${projectsId}/branch/${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
<p className="f-wrap-alignCenter mt15">
<span className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</span>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
</p>

View File

@ -1,9 +1,10 @@
import React , { Component } from 'react';
import { Spin , Pagination } from 'antd';
import { getImageUrl } from 'educoder';
import { truncateCommitId } from '../common/util'
import { truncateCommitId } from '../common/util';
import SelectBranch from '../Branch/Select';
import Nodata from '../Nodata';
import { getBranch } from '../GetData/getData';
import axios from 'axios';
import {Link} from "react-router-dom";
@ -12,21 +13,44 @@ class CoderRootCommit extends Component{
constructor(props){
super(props)
this.state={
branch:"master",
commitDatas:undefined,
dataCount:undefined,
limit:20,
page:1,
isSpining:false
isSpining:false,
branchList:undefined
}
}
componentDidMount=()=>{
const { branch , page , limit } = this.state;
this.Init();
this.getBranchs();
}
// 获取分支列表
getBranchs=()=>{
const { projectsId , owner } = this.props.match.params;
axios.get(`/${owner}/${projectsId}/branches.json`).then(result=>{
this.setState({
branchList:result.data
})
}).catch((error)=>{})
}
componentDidUpdate=(prevProps)=>{
const { location } = this.props;
const prevlocation = prevProps && prevProps.location;
if (location !== prevlocation) {
this.Init();
}
}
Init =()=>{
const { branchName } = this.props.match.params;
const { page , limit } = this.state;
this.setState({
isSpining:true
})
this.getCommitList( branch , page , limit );
this.getCommitList( branchName , page , limit );
}
getCommitList=(branch , page , limit)=>{
@ -68,26 +92,20 @@ class CoderRootCommit extends Component{
// 切换分支 search:tag为根据标签搜索
changeBranch=(value)=>{
const { page , limit } = this.state;
const { getTopCount } = this.props;
this.setState({
isSpining:true,
branch:value,
})
this.getCommitList(value , page , limit);
getTopCount && getTopCount(value);
const { projectsId , owner } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}/commits/branch/${value}`);
}
ChangePage=(page)=>{
const { branch , limit } = this.state;
this.getCommitList(branch , page , limit);
const { branchName } = this.props.match.params;
const { limit } = this.state;
this.getCommitList(branchName , page , limit);
}
render(){
const { branch , commitDatas , dataCount , limit , page , isSpining } = this.state;
const { branchs , projectDetail, commit_class } = this.props;
const { projectsId , owner } = this.props.match.params;
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
const { projectDetail, commit_class , defaultBranch } = this.props;
const { projectsId , owner , branchName } = this.props.match.params;
let branch = branchName || defaultBranch;
return(
<React.Fragment>
<div className={commit_class}>
@ -98,6 +116,8 @@ class CoderRootCommit extends Component{
branch={branch}
changeBranch={this.changeBranch}
owner={owner}
history={this.props.history}
branchList={branchList}
></SelectBranch>
</div>
<Spin spinning={isSpining}>
@ -113,13 +133,13 @@ class CoderRootCommit extends Component{
return(
<div key={k}>
<p className="f-wrap-alignCenter">
<span className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</span>
<span className="flex1 ml20 font-16 color-grey-3">{item.message}</span>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</Link>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
</p>
<p className="f-wrap-alignCenter mt15">
<Link to={`/users/${item.login}`} className="show-user-link">
{item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
</Link>
</p>
</div>

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import { Menu, Spin, Button } from "antd";
import { Menu, Spin } from "antd";
import { getImageUrl } from "educoder";
import { Link } from "react-router-dom";
@ -10,16 +10,16 @@ import RootTable from './RootTable';
import CoderRootFileDetail from './CoderRootFileDetail';
import { truncateCommitId } from '../common/util';
import RenderHtml from '../../components/render-html';
import Nodata from '../Nodata';
import { getBranch } from '../GetData/getData';
import axios from "axios";
/**
* address:http和SSHhttp_url(对应git地址)
* branch:当前分支
* filePath:点击目录时当前目录的路径
* subfileType:保存当前点击目录的文件类型显示目录列表时才显示新建文件如果点击的是文件就不显示新建文件按钮
* readMeContent:根目录下面的readme文件内容
*/
function getPathUrl(array,index){
if(array && array.length>0 && index){
let str = "";
@ -29,13 +29,11 @@ function getPathUrl(array,index){
return str.substr(1);
}
}
class CoderRootDirectory extends Component {
constructor(props) {
super(props);
this.state = {
address: "http",
branch: "master",
filePath: undefined,
subFileType: undefined,
readMeContent: undefined,
@ -65,7 +63,17 @@ class CoderRootDirectory extends Component {
componentDidMount = () => {
this.Init();
this.getBranchs();
};
// 获取分支列表
getBranchs=()=>{
const { projectsId , owner } = this.props.match.params;
axios.get(`/${owner}/${projectsId}/branches.json`).then(result=>{
this.setState({
branchList:result.data
})
}).catch((error)=>{})
}
componentDidUpdate = (prevState) => {
const { location } = this.props;
@ -80,32 +88,27 @@ class CoderRootDirectory extends Component {
Init = () => {
let { search } = this.props.history.location;
let branchName = undefined;
if (search && search.indexOf("?branch=") > -1) {
branchName = search.split("?branch=")[1];
this.setState({
branch: branchName,
});
}
if (search && search.indexOf("?url=") > -1) {
let url = search.split("?url=")[1];
this.setState({
filePath: url,
});
this.getFileDetail(url);
const { branchName } = this.props.match.params;
const { defaultBranch } = this.props;
let branch = branchName || defaultBranch;
if (search && (search.indexOf("?url=") > -1 || search.indexOf("&url=") > -1)) {
let url = search.split("url=")[1];
if(url && decodeURI(url).indexOf("&")){
url=decodeURI(url).split("&")[0];
}
this.getFileDetail(decodeURI(url),branch);
} else {
const { branch } = this.state;
this.getProjectRoot(branchName || branch);
this.getProjectRoot(branch);
}
};
// 页面地址返回到主目录
returnMain = (branch) => {
const { projectsId , owner } = this.props.match.params;
const { projectsId , owner , branchName } = this.props.match.params;
this.setState({
readOnly:true
})
this.props.history.push(`/projects/${owner}/${projectsId}/coders`);
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}`);
this.getProjectRoot(branch);
};
@ -142,7 +145,7 @@ class CoderRootDirectory extends Component {
ChangeFile = (arr, readOnly) => {
const { projectsId , owner } = this.props.match.params;
//点击直接跳转页面 加载一次路由
this.props.history.push(`/projects/${owner}/${projectsId}/coders?url=${arr.path}`);
this.props.history.push(`/projects/${owner}/${projectsId}?url=${arr.path}`);
this.setState({
readOnly: readOnly,
chooseType:"file"
@ -162,19 +165,12 @@ class CoderRootDirectory extends Component {
index: k,
name: i,
path: str.substr(1),
type:
filePath && filePath.length > 0
? filePath[k]
? filePath[k].type
: type
: type,
type: filePath && filePath.length > 0 ? filePath[k] ? filePath[k].type : type : type,
});
});
const { projectsId , owner } = this.props.match.params;
//点击直接跳转页面 加载一次路由
this.props.history.push(
`/projects/${owner}/${projectsId}/coders?url=${str.substr(1)}`
);
this.props.history.push(`/projects/${owner}/${projectsId}?url=${str.substr(1)}`);
} else {
list.push({
index: 0,
@ -190,60 +186,74 @@ class CoderRootDirectory extends Component {
// 获取子目录
getFileDetail = (path, ref) => {
const { projectsId ,owner } = this.props.match.params;
const { branch } = this.state;
this.setState({
filePath: decodeURI(path),
});
const { projectsId , owner , branchName } = this.props.match.params;
const { chooseType } = this.state;
const url = `/${owner}/${projectsId}/sub_entries.json`;
axios.get(url,{
params:{
filepath:path,
ref:ref || branch
ref:ref || branchName,
type:chooseType
}
}).then((result)=>{
let entries = result.data && result.data.entries
if( entries && entries.length > 0){
let { chooseType } = this.state;
// 当前返回的子目录只有一条数据,且这条数据返回的是文件类型
if(entries.length === 1 && entries[0].type === "file" && chooseType ==="file"){
let entries = result.data && result.data.entries;
this.setState({
isSpin:false
})
if(result){
if(entries){
// 返回对象entries.type则是文件类型否则是文件夹
if(entries.type){
this.setState({
fileDetail:[entries],
rootList:undefined,
subFileType:false
})
}else{
this.setState({
fileDetail:undefined,
rootList:entries,
branchLastCommit:result.data.last_commit && result.data.last_commit.commit,
lastCommitAuthor:result.data.last_commit && (result.data.last_commit.author || (result.data.last_commit.commit && result.data.last_commit.commit.author))
})
this.renderData(entries);
}
}else{
this.setState({
fileDetail:entries,
fileDetail:undefined,
rootList:undefined,
isSpin:false,
subFileType:false
})
}else{
this.setState({
fileDetail:undefined,
rootList:entries,
isSpin:false,
branchLastCommit:result.data.last_commit && result.data.last_commit.commit,
lastCommitAuthor:result.data.last_commit && (result.data.last_commit.author || (result.data.last_commit.commit && result.data.last_commit.commit.author))
})
this.renderData(entries);
}
}
})
.catch((error) => {
this.setState({
isSpin:false
})
.catch((error) => {
console.log(error);
});
console.log(error);
});
};
renderData = (data) => {
const rootList = [];
const readMeContent = [];
const readMeFile = [];
data &&
data.map((item, key) => {
rootList.push({
key,
message: item.commit && item.commit.message,
...item,
});
if (item.is_readme_file) {
readMeContent.push({ ...item });
readMeFile.push({ ...item });
}
data && data.map((item, key) => {
rootList.push({
key,
message: item.commit && item.commit.message,
...item,
});
if (item.is_readme_file) {
readMeContent.push({ ...item });
readMeFile.push({ ...item });
}
});
this.setState({
rootList: rootList,
readMeContent,
@ -256,8 +266,8 @@ class CoderRootDirectory extends Component {
this.setState({
chooseType:type
})
const { projectsId, owner } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}/coders?url=${path}`);
const { projectsId, owner , branchName } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}?url=${path}`);
if(filename.substring(filename.length - 3) === ".md"){
this.setState({
md:true
@ -285,26 +295,23 @@ class CoderRootDirectory extends Component {
<span className="commonBox-title-read">
{readMeContent[0].name}
</span>
{permission ? (
{permission ?
<a
onClick={() => this.ChangeFile(readMeFile[0], false)}
className="ml20 pull-right"
>
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
</a>
) : (
:
""
)}
}
</div>
<div className="commonBox-info">
{readMeContent[0].content ? (
<RenderHtml
className="break_word_comments imageLayerParent"
value={readMeContent[0].content}
/>
) : (
{readMeContent[0].content ?
<RenderHtml className="break_word_comments imageLayerParent" value={readMeContent[0].content} url={this.props.history.location}/>
:
<span>暂无~</span>
)}
}
</div>
</div>
);
@ -313,24 +320,18 @@ class CoderRootDirectory extends Component {
// 选择分支
changeBranch = (value) => {
this.setState({
branch: value,
isSpin: true,
readOnly:true
});
const { getTopCount } = this.props;
getTopCount && getTopCount(value);
let { search } = this.props.history.location;
if (search && search.indexOf("?url=") > -1) {
let url = search.split("?url=")[1];
this.setState({
filePath: url,
});
this.getFileDetail(url, value);
} else {
this.getProjectRoot(value);
const { projectsId , owner } = this.props.match.params;
let url = `/projects/${owner}/${projectsId}${value && `/branch/${value}`}`;
if (search && (search.indexOf("?url=") > -1 || search.indexOf("&url=") > -1)) {
let u = search.split("url=")[1];
if(u && decodeURI(u).indexOf("&")){
u=decodeURI(u).split("&")[0];
}
url += `?url=${u}`;
}
this.props.history.push(url);
}
// 子目录路径返回链接
@ -340,7 +341,7 @@ class CoderRootDirectory extends Component {
readOnly:true
})
const { projectsId , owner } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}/coders?url=${url}`);
this.props.history.push(`/projects/${owner}/${projectsId}?url=${url}`);
}
onEdit=(readOnly)=>{
@ -368,6 +369,7 @@ class CoderRootDirectory extends Component {
title = (branchLastCommit,lastCommitAuthor) => {
if (branchLastCommit) {
const { projectsId , owner } = this.props.match.params;
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
@ -393,13 +395,13 @@ class CoderRootDirectory extends Component {
) : (
""
)}
<span className="color-blue flex-1 hide-1">
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</span>
</Link>
<span>{branchLastCommit.time_from_now}</span>
<span className="commitKey">
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</span>
</Link>
</div>
);
}else{
@ -407,33 +409,37 @@ class CoderRootDirectory extends Component {
}
}
render(){
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
const { isManager , isDeveloper , projectDetail } = this.props;
const { projectsId , owner } = this.props.match.params;
const { branchLastCommit , lastCommitAuthor , rootList ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url , branchList} = this.state;
const { isManager , isDeveloper , projectDetail , platform , defaultBranch } = this.props;
const { projectsId , owner , branchName } = this.props.match.params;
let branch = branchName || defaultBranch;
const columns = [
{
key:"name",
dataIndex: 'name',
width:"30%",
render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path,item.type,text)} className="ml12 task-hide" style={{ display: "block", maxWidth: "345px" }}>
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5":"iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5" : "iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
</a>
),
},
{
dataIndex: "commit",
key:"message",
dataIndex: "message",
width: "60%",
render: (text, item) =>
item.commit && item.commit.message ?
<span className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit.sha}`)}`} title={item.commit.message} className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
{item.commit.message}
</span>
</Link>
: ""
},
{
dataIndex: "commit",
key:"time_from_now",
dataIndex: "time_from_now",
width: "10%",
className: "edu-txt-right",
render: (text, item) =>
@ -452,13 +458,21 @@ class CoderRootDirectory extends Component {
<div className="main">
<div className="f-wrap-between mb20">
<div className="f-wrap-alignCenter">
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
owner={owner}
></SelectBranch>
{
platform ?
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
owner={owner}
history={this.props.history}
branchList={branchList}
></SelectBranch>
:
<span>分支<span className="color-grey-6">master</span></span>
}
{filePath && (
<span className="ml20 font-16">
@ -468,7 +482,8 @@ class CoderRootDirectory extends Component {
>
{projectDetail && projectDetail.identifier}
</a>
{ array && array.map((item, key) => {
{array &&
array.map((item, key) => {
return (
<React.Fragment>
{
@ -484,7 +499,7 @@ class CoderRootDirectory extends Component {
)}
</div>
<div className="f-wrap-alignCenter">
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && (
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && platform && (
<div>
<span>
<Link to={`/projects/${owner}/${projectsId}/${branch}/uploadfile${urlRoot}`} >
@ -525,10 +540,13 @@ class CoderRootDirectory extends Component {
{...this.state}
readOnly={this.state.readOnly}
onEdit={this.onEdit}
currentBranch={branch}
></CoderRootFileDetail>
)}
{/* readme.txt (isManager || isDeveloper)*/}
{this.renderReadMeContent(readMeContent, isManager || isDeveloper)}
{
!rootList && !fileDetail && <Nodata _html="暂未发现当前文件!"/>
}
{ rootList && this.renderReadMeContent(readMeContent, isManager || isDeveloper)}
</div>
</Spin>
);

View File

@ -1,12 +1,10 @@
import React, { Component } from "react";
import { Popconfirm, Select } from "antd";
import { Popconfirm , Select } from "antd";
import "./list.css";
import axios from "axios";
import Meditor from "../Newfile/m_editor";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
function bytesToSize(bytes) {
if (bytes === 0) return "0 B";
let k = 1024,
@ -21,7 +19,7 @@ class CoderRootFileDetail extends Component {
value: undefined,
language: undefined,
languages: undefined,
description:props.detail.content
description: props.detail.content
};
}
@ -95,8 +93,10 @@ class CoderRootFileDetail extends Component {
default_language = item;
}
}
this.state.languages = languages;
this.state.language = default_language;
this.setState({
languages,
language: default_language
})
};
select_language = (e) => {
@ -107,11 +107,13 @@ class CoderRootFileDetail extends Component {
EditFile = (flag) => {
const { onEdit } = this.props;
onEdit && onEdit(flag);
// this.setState({
// readOnly: false,
// });
};
DownLoadFile = (url) => {
let download_url = "/attachments/entries/get_file?download_url=" + url
window.open(download_url)
}
// 编辑文件
changeMmirror = (e, e1, value) => {
@ -122,17 +124,16 @@ class CoderRootFileDetail extends Component {
deleteFile = () => {
const { branch, detail } = this.props;
const { projectsId , owner } = this.props.match.params;
const { projectsId, owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/delete_file.json`;
axios
.delete(url, {
params: {
filepath: detail.path,
branch,
sha: detail.sha,
},
})
axios.delete(url, {
params: {
filepath: detail.path,
branch,
sha: detail.sha,
},
})
.then((result) => {
if (result) {
this.props.showNotification("删除成功!");
@ -163,12 +164,13 @@ class CoderRootFileDetail extends Component {
current_user,
isManager,
isDeveloper,
md
md,
currentBranch,
platform
} = this.props;
const { language, languages , description } = this.state;
const { language, languages, description } = this.state;
let flag = current_user && current_user.login && (isManager || isDeveloper);
const Option = Select.Option;
return (
<div className="mb20">
<div className="grid-item branchTitle">
@ -178,40 +180,52 @@ class CoderRootFileDetail extends Component {
</span>
</div>
<p className="text-right">
{flag && (
{flag && platform && (
<div>
{readOnly ? (
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
<span>
{
detail.direct_download ?
""
:
<span>
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
</a>
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
</span>
}
</span>
) : (
<React.Fragment>
<Select
showSearch={true}
placeholder={"请选择文本语言"}
style={{ width: 200 }}
value={language}
onChange={this.select_language}
>
<Option value={undefined}>请选择文本语言</Option>
{languages &&
languages.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
<button
type="button"
className="ant-btn ant-btn-sm ml20"
onClick={() => this.EditFile(true)}
>
<span> </span>
</button>
</React.Fragment>
)}
<React.Fragment>
<Select
showSearch={true}
placeholder={"请选择文本语言"}
style={{ width: 200 }}
value={language}
onChange={this.select_language}
>
<Option value={undefined}>请选择文本语言</Option>
{languages &&
languages.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
<button
type="button"
className="ant-btn ant-btn-sm ml20"
onClick={() => this.EditFile(true)}
>
<span> </span>
</button>
</React.Fragment>
)}
<Popconfirm
title="确认删除这个文件?"
@ -245,20 +259,21 @@ class CoderRootFileDetail extends Component {
</div>
) : (
md && readOnly ?
<div className="files-md">
<RenderHtml className="file-md imageLayerParent" value={description} />
</div>
:
<Meditor
{...this.props}
{...this.state}
language={language ? language : "javascript"}
filepath={`/${detail.path}`}
content={detail.content}
readOnly={readOnly}
editorType="update"
></Meditor>
)}
<div className="files-md">
<RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/>
</div>
:
<Meditor
{...this.props}
{...this.state}
language={language ? language : "javascript"}
filepath={`/${detail.path}`}
content={detail.content}
readOnly={readOnly}
editorType="update"
currentBranch={currentBranch}
></Meditor>
)}
</div>
</div>
);

View File

@ -55,12 +55,20 @@ class CoderRootIndex extends Component{
}
componentDidMount=()=>{
let { search } = this.props.history.location;
let branchName = undefined;
if (search && search.indexOf("?branch=") > -1) {
branchName = search.split("?branch=")[1];
this.Init();
}
componentDidUpdate=(prevProps)=>{
const { location } = this.props;
const prevlocation = prevProps && prevProps.location;
if (location !== prevlocation) {
this.Init();
}
this.getTopCount(branchName);
}
Init=()=>{
const { branchName } = this.props.match.params;
const { defaultBranch } = this.props;
this.getTopCount(branchName || defaultBranch);
}
getTopCount=(branch)=>{
@ -97,17 +105,23 @@ class CoderRootIndex extends Component{
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
{/* diff */}
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits/:sha"
render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits"
render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
{/* diff */}
<Route path="/projects/:owner/:projectsId/diff/:sha"
render={
() => (<Diff {...this.props} {...this.state}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
render={
@ -125,12 +139,18 @@ class CoderRootIndex extends Component{
() => (<CoderRootVersion {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/tag"
render={
() => (<CoderRootTag {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/branch"
<Route path="/projects/:owner/:projectsId/branch/:branchName"
render={
(props) => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/branchs"
render={
() => (<CoderRootBranch {...this.props} {...this.state} />)
}

View File

@ -3,13 +3,12 @@ import axios from 'axios';
import { Spin } from 'antd';
import { truncateCommitId } from '../common/util';
import Nodata from '../Nodata';
import { Link } from 'react-router-dom'
export default (( props, { projectDetail }) => {
const [isSpin, setSpin] = useState(true);
const [data, setData] = useState(undefined);
const repo_id = projectDetail && projectDetail.repo_id;
const { projectsId , owner } = props.match.params;
useEffect(() => {
@ -49,7 +48,7 @@ export default (( props, { projectDetail }) => {
<span className="font-16">{item.name}</span>
</span>
<span className="ul_tbody_third">
<span className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</span>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`} className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</Link>
</span>
<span className="ul_tbody_forth">
<a href={item.tarball_url} style={{ color: "#4CC1DA" }} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>

View File

@ -4,23 +4,13 @@ import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import '../css/index.scss'
import './list.css';
import SpecialModal from './SpecialModal';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
import axios from 'axios';
import img_1 from '../Images/1.png';
import img_2 from '../Images/2.png';
import img_3 from '../Images/3.png';
import img_6 from '../Images/6.png';
import img_7 from '../Images/7.png';
import img_parise from '../Images/parise.png';
import img_focus from '../Images/focus.png';
import img_parised from '../Images/parised.png';
import img_focused from '../Images/focused.png';
import img_fork from '../Images/fork.png';
import img_milepost from '../Images/milepost.png';
const Setting = Loadable({
loader: () => import('../Settings/Index'),
loading: Loading,
@ -114,6 +104,10 @@ const TrendsIndex = Loadable({
loading: Loading,
})
const DevAbout = Loadable({
loader: () => import('../About/Index'),
loading: Loading,
})
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
@ -124,7 +118,9 @@ const DevIndex = Loadable({
function checkPathname(pathname){
let name = "";
if(pathname){
if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){
if(pathname.indexOf("/about")>-1){
name="about"
}else if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){
name = "issues";
}else if(pathname.indexOf("/pulls")>-1){
name="pulls"
@ -134,6 +130,8 @@ function checkPathname(pathname){
name="activity"
}else if(pathname.indexOf("/setting")>-1){
name="setting"
}else if(pathname.indexOf("/devops")>-1){
name="devops"
}
}
return name;
@ -159,6 +157,14 @@ class Detail extends Component {
project: null,
firstSync:false,
secondSync:false,
open_devops:false,
// 默认分支
defaultBranch:undefined,
// 非本平台项目
platform:false,
visible:false,
user_apply_signatures:[]
}
}
@ -175,13 +181,35 @@ class Detail extends Component {
}
getProject = (num) => {
const {user} = this.props;
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/simple.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setState({
project: result.data
project: result.data,
open_devops:result.data.open_devops,
platform:result.data.platform && result.data.platform !== 'educoder'
})
let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0];
if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){
this.setState({
visible:true,
is_secret:result.data.is_secret,
user_apply_signatures:signa
})
}
// 工作流:两种状态进入的链接不同
const pathname = this.props.history.location.pathname;
if(pathname===`/projects/${owner}/${projectsId}/devops`){
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
}
}
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
// 是镜像项目,且未完成迁移
@ -207,6 +235,13 @@ class Detail extends Component {
}
})
}
// 工作流激活后修改状态
changeOpenDevops=(flag)=>{
this.setState({
open_devops:flag
})
}
canvasChannel = () => {
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
const actioncable = require("actioncable");
@ -234,11 +269,11 @@ class Detail extends Component {
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}.json`;
axios.get(url).then((result) => {
if (result) {
if (result && result.data) {
this.setState({
projectDetail: result.data,
project_id: result.data.project_id,
isManager: result.data.permission && result.data.permission === "Manager",
isManager: result.data.permission && (result.data.permission === "Manager" || result.data.permission === "Admin" || result.data.permission === "Owner"),
isReporter: result.data.permission && result.data.permission === "Reporter",
isDeveloper: result.data.permission && result.data.permission === "Developer",
http_url: result.data.clone_url,
@ -248,6 +283,7 @@ class Detail extends Component {
watchers_count: result.data.watchers_count,
praises_count: result.data.praises_count,
forked_count: result.data.forked_count,
defaultBranch:result.data.default_branch
})
}
}).catch((error) => { })
@ -255,8 +291,10 @@ class Detail extends Component {
// 关注和取消关注
focusFunc = (flag) => {
const { project_id } = this.state;
const { platform } = this.state;
if(!platform)return;
const { project_id } = this.state;
axios({
method: flag ? 'delete' : 'post',
url: `/watchers/${flag ? 'unfollow' : 'follow'}.json`,
@ -276,6 +314,8 @@ class Detail extends Component {
// 点赞和取消点赞
pariseFunc = (flag) => {
const { platform } = this.state;
if(!platform)return;
const { project_id } = this.state;
axios({
method: flag ? 'delete' : 'post',
@ -306,6 +346,8 @@ class Detail extends Component {
// fork项目
forkFunc = () => {
const { platform } = this.state;
if(!platform)return;
const { current_user } = this.props
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/forks.json`;
@ -321,6 +363,8 @@ class Detail extends Component {
// 同步镜像
synchronismMirror = () => {
const { platform } = this.state;
if(!platform)return;
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/sync_mirror.json`;
axios.post(url).then(result => {
@ -334,10 +378,24 @@ class Detail extends Component {
})
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
this.props.history.push('/projects');
}
render() {
const { projectDetail, watchers_count, praises_count, forked_count, firstSync , secondSync , isManager, watched, praised, project } = this.state;
const { projectDetail, watchers_count, praises_count,
forked_count, firstSync , secondSync ,
isManager, watched, praised,
project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
@ -346,8 +404,6 @@ class Detail extends Component {
const { projectsId , owner } = this.props.match.params;
const { state } = this.props.history.location;
const { current_user } = this.props;
const checkLogin = current_user && current_user.login;
const text = (
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
@ -359,16 +415,18 @@ class Detail extends Component {
</React.Fragment> : ""
);
const common = {
getDetail: this.getDetail
getDetail: this.getDetail,
changeOpenDevops:this.changeOpenDevops,
defaultBranch
}
return (
<div>
<SpecialModal {...this.props} visible={visible} hideModal={this.sureModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
<p className="font-22 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
<p className="color-white font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{project && project.author &&
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
{project.author.name}
@ -391,10 +449,11 @@ class Detail extends Component {
projectDetail.type === 2 ?
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-banbenku font-18 mt6" style={{ color: "#8D90E3" }}/>
</Tooltip>:
</Tooltip>
:
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-jingxiang font-18 color-green mt6" />
</Tooltip>
<i className="iconfont icon-jingxiang font-18 color-green mt6" />
</Tooltip>
:""
}
</span>
@ -407,29 +466,45 @@ class Detail extends Component {
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
}
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}>
<img src={watched ? img_focused : img_focus} alt="" width="14px" />
{watched ? '取消关注' : '关注'}
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.focusFunc(watched)}>
<i className={watched ? "iconfont icon-shixing color-orange font-16 mr3":"iconfont icon-kongxing color-grey-9 font-16 mr3"}></i>
<span>{watched ? '取消关注' : '关注'}</span>
</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }}>
{watchers_count}
</Link>
{
platform ?
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
{watchers_count}
</Link>
:
<span className="detail_tag_btn_count">{watchers_count}</span>
}
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.pariseFunc(praised)}>
<img src={praised ? img_parised : img_parise} width="13px" alt="" />
{praised ? '取消点赞' : '点赞'}
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3":"iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i>
<span>{praised ? '取消点赞' : '点赞'}</span>
</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
{praises_count}
</Link>
{
platform ?
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
{praises_count}
</Link>:
<span className="detail_tag_btn_count">{praises_count}</span>
}
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={this.forkFunc}>
<img src={img_fork} alt="" width="10px" />Fork</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={this.forkFunc}>
<i className="iconfont icon-fork color-grey-9 mr3"></i> (Fork)
</a>
{
platform ?
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
:
<span className="detail_tag_btn_count">{praises_count}</span>
}
</span>
</span>
}
@ -438,46 +513,66 @@ class Detail extends Component {
firstSync ? "" :
<div className="f-wrap-between pb20">
<ul className="headerMenu-wrapper">
<li className={pathname==="about" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
<i className={ pathname === "about" ? "iconfont icon-zhuye1 color-blue mr5 font-14":"iconfont icon-zhuye1 color-white font-14 mr5"}></i>
<span>主页</span>
</Link>
</li>
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
<img alt="" src={img_1} width="18" />代码库
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-blue mr5 font-14":"iconfont icon-daimaku color-white font-14 mr5"}></i>
<span>代码库</span>
</Link>
</li>
<li className={pathname==="issues" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<img alt="" src={img_2} width="12" />任务
{projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> : ""}
<i className={pathname==="issues" ? "iconfont icon-renwu color-blue mr5 font-14":"iconfont icon-renwu color-white font-14 mr5"}></i>
<span>易修 (Issue)</span>
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
</Link>
</li>
{
projectDetail && parseInt(projectDetail.type) !== 2 &&
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
<li className={pathname==="pulls" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
<img alt="" src={img_3} width="13" />合并请求
{projectDetail && projectDetail.pull_requests_count ? <span>{projectDetail.pull_requests_count}</span> : ""}
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-blue mr5 font-14":"iconfont icon-hebingqingqiu1 color-white font-14 mr5"}></i>
<span>合并请求</span>
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>
}
{/* <li className={url.indexOf("/ops") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/ops`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li> */}
{/* {
platform &&
<li className={pathname==="devops" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>(beta)
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li>
} */}
<li className={pathname==="milestones" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
<img alt="" src={img_milepost} width="16" />里程碑
{projectDetail && projectDetail.versions_count ? <span>{projectDetail.versions_count}</span> :""}
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-blue mr5 font-14":"iconfont icon-lichengbei color-white font-14 mr5"}></i>
<span>里程碑</span>
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
</Link>
</li>
<li className={pathname==="activity" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
<img alt="" src={img_6} width="16" />动态
</Link>
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-blue mr5 font-14":"iconfont icon-tongzhi color-white font-14 mr5"}></i>
<span>动态</span>
</Link>
</li>
{
isManager &&
<li className={url.indexOf("/setting") > 0 ? "active" : ""}><Link to={`/projects/${owner}/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
isManager && platform &&
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>
}
</ul>
</div>
@ -493,8 +588,14 @@ class Detail extends Component {
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 主页 */}
<Route path="/projects/:owner/:projectsId/about"
render={
() => (<DevAbout {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 工作流 */}
<Route path="/projects/:owner/:projectsId/ops"
<Route path="/projects/:owner/:projectsId/devops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
@ -623,6 +724,16 @@ class Detail extends Component {
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/branch/:branchName"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)

View File

@ -3,27 +3,53 @@ import { Link } from 'react-router-dom';
class DetailTop extends Component {
render() {
const { coderCount } = this.props;
const { coderCount , platform } = this.props;
const { projectsId, owner } = this.props.match.params;
const { pathname } = this.props.location;
return (
<p className="branch-wrapper">
<Link to={`/projects/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{(coderCount && coderCount.commits_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/branch`} className={pathname.indexOf("/branch") > 0 ? "active" : ""}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{(coderCount && coderCount.branches_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/tag`} className={pathname.indexOf("/tag") > 0 ? "active" : ""}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{(coderCount && coderCount.tags_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}>
<i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</Link>
{
platform ?
<React.Fragment>
<Link to={`/projects/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{(coderCount && coderCount.commits_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/branchs`} className={pathname.indexOf("/branchs") > 0 ? "active" : ""}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{(coderCount && coderCount.branches_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/tag`} className={pathname.indexOf("/tag") > 0 ? "active" : ""}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{(coderCount && coderCount.tags_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}>
<i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</Link>
</React.Fragment>
:
<React.Fragment>
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{(coderCount && coderCount.commits_count) || 0}</span>
</a>
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{(coderCount && coderCount.branches_count) || 0}</span>
</a>
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{(coderCount && coderCount.tags_count) || 0}</span>
</a>
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</a>
</React.Fragment>
}
<a href="javscript:void(0)" style={{cursor:"default"}}>
<i className="iconfont icon-cangku font-18 mr3"></i>
仓库 <span className="ml3">{(coderCount && coderCount.size) || 0}</span>

View File

@ -2,7 +2,8 @@ import React, { useEffect, useState } from "react";
import styled from "styled-components";
import { Button ,Spin } from "antd";
import { truncateCommitId } from '../common/util';
import Nodata from '../Nodata';
import { getImageUrl } from 'educoder';
import Files from '../Merge/Files';
import User from "../Component/User";
import Keys from "../Component/Keys";
@ -11,65 +12,34 @@ import axios from "axios";
const Infos = styled.div`
border: 1px solid #dddddd;
margin-bottom:15px;
& .commitinfos {
background-color: #f1f8ff;
border-bottom: 1px solid #ddd;
padding: 20px;
}
& > .f-wrap-between {
padding: 10px 24px;
padding: 10px 20px;
}
`;
const Operation = styled.p`
border-bottom: 1px solid #eee;
padding: 12px 0px;
margin-top: 10px;
display: flex;
justify-content: space-between;
align-items: center;
`;
const FileUl = styled.ul`
padding-top: 10px;
& li {
display: flex;
justify-content: space-between;
align-items: center;
height: 20px;
line-height: 20px;
margin-bottom: 10px;
}
`;
const DetailP = styled.p`
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 20px 12px 12px;
background-color: #fafafa;
border: 1px solid #dddddd;
`;
export default ({ projectDetail, match }) => {
export default ({ match , history }) => {
const [data, setData] = useState({undefined});
const [commit, setCommit] = useState(undefined);
const [files, setFiles] = useState(undefined);
const [parents, setParents] = useState(undefined);
const [committer, setCommitter] = useState(undefined);
const [fileflag , setFileflag] = useState(false);
const [isSpin, setIsSpin] = useState(true);
const repo_id = projectDetail && projectDetail.repo_id;
const { sha } = match.params;
const { sha , projectsId, owner } = match.params;
useEffect(() => {
if (repo_id && sha) {
const url = `/repositories/${repo_id}/commits/${sha}.json`;
if (projectsId && owner && sha) {
const url = `/${owner}/${projectsId}/commits/${sha}.json`;
axios
.get(url)
.then(result => {
if (result) {
setData(result.data);
setCommit(result.data.commit);
setFiles(result.data.files);
setParents(result.data.parents);
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
setIsSpin(false);
@ -79,78 +49,32 @@ export default ({ projectDetail, match }) => {
console.log(error);
});
}
}, [repo_id, sha]);
const renderFiles = () => {
return (
<FileUl>
{
files && files.length > 0 && files.map((item,key)=>{
return(
<li>
<span className="mr30 task-hide flex1">
<i className="iconfont icon-wenjia color-grey-3 font-16 mr8"></i>
{item.Name}
</span>
<span>
<label className="color-green mr20">+{item.Addition}</label>
<label className="color-red">-{item.Deletion}</label>
</span>
</li>
)
})
}
</FileUl>
);
};
function changeFlag(){
let flag = !fileflag;
setFileflag(flag);
}
const filesDetail = () => {
return (
<div>
<DetailP>
<span>
<i className="iconfont icon-youjiantou mr4 font-15 color-grey-9"></i>
<span className="font-16 color-grey-3">README.md</span>
</span>
<Button>查看文件</Button>
</DetailP>
</div>
);
};
}, [projectsId , owner, sha]);
return (
<div className="main">
<Spin spinning={isSpin}>
<Infos>
<div className="commitinfos">
<p className="f-wrap-between">
<span className="font-20 color-grey-3">
{ commit && commit.title }
</span>
<Button type="primary">浏览代码</Button>
</p>
{commit && commit.message ? (
<pre className="mt10">{commit.message}</pre>
) : (
""
)}
<div className="f-wrap-between">
{commit && commit.message &&
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
}
<Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/branch/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
</div>
</div>
<div className="f-wrap-between" style={{ alignItems: "center" }}>
<ul className="df">
<User
url={(committer && committer.image_url)|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
url={(committer && getImageUrl(`images/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
name={committer && committer.name}
/>
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
</ul>
<li className="df">
{
parents && parents.length > 0 && parents.map((item,key)=>{
return(
<Keys title="父节点" value={truncateCommitId(item.sha) } className="mr20"></Keys>
<Keys title="父节点" value={truncateCommitId(item.sha)} key={key} className="mr20"></Keys>
)
})
}
@ -158,35 +82,12 @@ export default ({ projectDetail, match }) => {
</li>
</div>
</Infos>
{
files && files.length > 0 ?
<React.Fragment>
<Operation>
<span className="files_info" onClick={changeFlag}>
<i className={fileflag ? "iconfont icon-sanjiaoxing-down mr8 color-grey-9 font-16":"iconfont icon-triangle mr8 color-grey-9 font-16"}></i>
<span className="color-grey-9">
共有<span>{files && files.length}个文件被更改</span>包括
{data && data.additions ? (
<span className="color-green">{data.additions}次插入</span>
) : (
""
)}
{data && data.additions && data.deletions ? "和" : ""}
{data && data.deletions ? (
<span className="color-red">{data.deletions}次删除</span>
) : (
""
)}
</span>
</span>
<Button>双栏查看</Button>
</Operation>
{fileflag && renderFiles()}
{filesDetail()}
</React.Fragment>
:
<Nodata _html="暂无文件修改信息!"/>
}
<Files
history={history}
data={data}
owner={owner}
projectsId={projectsId}
/>
</Spin>
</div>
);

View File

@ -1,14 +1,14 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Menu, Input, Spin, Pagination, Popover, Affix } from "antd";
import "../css/index.scss";
import "./list.css";
import ListItem from "./IndexItem";
import axios from "axios";
import img_new from "../Images/new.png";
import img_array from "../Images/array.png";
import banner_list from "../Images/banner_list.png";
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover } from 'antd';
import '../css/index.scss'
import './list.css';
import './Index.scss';
import ListItem from './IndexItem'
import axios from 'axios';
import img_new from '../Images/new.png';
import img_array from '../Images/array.png';
import banner from '../Images/banner_list.png';
const Search = Input.Search;
class Index extends Component {
@ -22,249 +22,151 @@ class Index extends Component {
sort: undefined,
total: 0,
isSpin: true,
project_type: undefined,
category_id: undefined,
language_id: undefined,
typeList: undefined,
categoryList: undefined,
languageSpin: false,
categorySPin: false,
menu_active_id: undefined,
};
recommendList:undefined,
languageList:undefined,
languageId:undefined
}
}
componentDidMount = () => {
const {
page,
limit,
search,
sort,
project_type,
category_id,
language_id,
} = this.state;
this.getListData(
page,
limit,
search,
sort,
project_type,
category_id,
language_id
);
const { page,search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort,category_id , languageId);
this.getType();
this.getCategory();
};
this.getRecommand();
this.getLanguage();
}
// 获取语言列表
getLanguage=()=>{
const url = '/project_languages.json';
axios.get(url).then(result=>{
if(result){
this.setState({
languageList:result.data.project_languages
})
}
}).catch(error=>{})
}
// 获取推荐列表
getRecommand=()=>{
const url = `/projects/recommend.json`;
axios.get(url).then(result=>{
if(result){
this.setState({
recommendList:result.data
})
}
}).catch(error=>{})
}
// 获取列表
getListData = (
page,
limit,
search,
sort,
project_type,
category_id,
language_id
) => {
getListData = (page,search, sort,category_id,language_id) => {
const { current_user } = this.props;
const url = `/projects.json`;
axios
.get(url, {
params: {
user_id: current_user && current_user.user_id,
page,
limit,
search,
sort_by: sort,
category_id,
language_id,
},
})
.then((result) => {
if (result) {
this.setState({
projectsList: result.data.projects,
total: result.data.total_count,
isSpin: false,
});
}
})
.catch((error) => {});
};
axios.get(url, {
params: {
user_id: current_user && current_user.user_id,
page,
limit:15,
search,
sort_by: sort,
category_id,
language_id
}
}).then((result) => {
if (result) {
this.setState({
projectsList: result.data.projects,
total: result.data.total_count,
isSpin: false
})
}
}).catch((error) => { })
}
// 获取类型
getType = () => {
this.setState({ languageSpin: true });
const url = `/projects/group_type_list.json`;
axios
.get(url)
.then((result) => {
if (result && result.data) {
this.setTypeList(result.data, undefined);
this.setState({ languageSpin: false });
}
})
.catch((error) => {
this.setState({ languageSpin: false });
});
};
axios.get(url).then((result) => {
if (result && result.data) {
this.setTypeList(result.data, undefined)
}
}).catch((error) => { })
}
setTypeList = (list, active_type) => {
this.setState({
typeList: list.map((item, key) => {
return (
<li
key={key}
className={
active_type && parseInt(active_type) === parseInt(item.id)
? "active"
: ""
}
onClick={() => this.changeType(`${item.id}`, list)}
>
<li key={key} className={active_type && parseInt(active_type) === item.id ? 'active' : ''} onClick={() => this.changeType(`${item.id}`, list)}>
<p>
<span className="font-16">{item.name}</span>
<span className="color-blue">{item.projects_count}</span>
</p>
</li>
);
}),
});
};
)
})
})
}
// 切换类型
changeType = (type, list) => {
const { page, limit, sort, category_id, language_id } = this.state;
let new_language_id = type;
if (parseInt(language_id) === parseInt(new_language_id)) {
new_language_id = undefined;
}
changeType = (id, list) => {
this.setState({
isSpin: true,
language_id: new_language_id,
search: undefined,
});
this.setTypeList(list, new_language_id);
// const { page, limit, sort, category_id, language_id } = this.state;
this.getListData(
page,
limit,
undefined,
sort,
undefined,
category_id,
new_language_id
);
};
languageId: id,
search: undefined
})
this.setTypeList(list, id)
const { page,sort, category_id} = this.state;
this.getListData(page,undefined, sort,category_id , id);
}
// 获取类型
getCategory = () => {
this.setState({ categorySpin: true });
const url = `/project_categories/group_list.json`;
axios
.get(url)
.then((result) => {
if (result && result.data) {
this.setCategoryList(result.data, undefined);
this.setState({ categorySpin: false });
}
})
.catch((error) => {
this.setState({ categorySpin: false });
});
};
children_category = (childrens, list, active_id) => {
return (
<div className="category-popver-content">
{childrens.map((item, key) => {
return (
<div
key={key}
onClick={() => this.changeCategory(item.id, list, item.parent_id)}
className={
active_id && parseInt(active_id) === item.id
? "active category-popver"
: "category-popver"
}
>
{item.name}
</div>
);
})}
</div>
);
};
axios.get(url).then((result) => {
if (result && result.data) {
this.setCategoryList(result.data, undefined);
}
}).catch((error) => { })
}
setCategoryList = (list, active_id, children_active_id = undefined) => {
setCategoryList = (list, active_id) => {
this.setState({
categoryList: list.map((item, key) => {
return (
<li
key={key}
className={
active_id && parseInt(active_id) === item.id ? "active" : ""
}
>
{item.children && item.children.length > 0 ? (
<Popover
content={this.children_category(
item.children,
list,
children_active_id
)}
placement="right"
trigger="click"
>
<p>
<span className="font-16">{item.name}</span>
<i className="iconfont icon-youjiantou color-grey-9 font-12 ml5"></i>
{/* <span className="color-blue">{item.projects_count}</span> */}
</p>
</Popover>
) : (
<p onClick={() => this.changeCategory(`${item.id}`, list)}>
<span className="font-16">{item.name}</span>
<span></span>
{/* <span className="color-blue">{item.projects_count}</span> */}
</p>
)}
<li key={key} className={active_id && parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
<p>
<span className="font-16">{item.name}</span>
<span className="color-blue">{item.projects_count}</span>
</p>
</li>
);
}),
});
};
)
})
})
}
changeCategory = (id, list, parent_id = undefined) => {
const { limit, sort, category_id, language_id } = this.state;
let new_category_id = id;
if (parseInt(category_id) === parseInt(new_category_id)) {
new_category_id = undefined;
}
changeCategory = (id, list) => {
this.setState({
category_id: new_category_id,
page: 1,
search: undefined,
menu_active_id: new_category_id,
category_id: id,
page: 1
});
let active_id = parent_id ? parent_id : new_category_id;
let children_active_id = parent_id ? id : undefined;
this.setCategoryList(list, active_id, children_active_id);
this.getListData(
1,
limit,
undefined,
sort,
undefined,
new_category_id,
language_id
);
};
this.setCategoryList(list, id)
const { sort,languageId } = this.state;
this.getListData(1,undefined, sort,id , languageId);
}
// 排序
ChangeSoryBy = (e) => {
@ -272,11 +174,11 @@ class Index extends Component {
sort_by: e.key,
page: 1,
search: undefined,
isSpin: true,
});
const { limit, project_type, category_id } = this.state;
this.getListData(1, limit, undefined, e.key, project_type, category_id);
};
isSpin: true
})
const {category_id , languageId } = this.state;
this.getListData(1,undefined, e.key,category_id , languageId);
}
// 搜索
searchFun = (value) => {
@ -285,161 +187,142 @@ class Index extends Component {
search: value,
isSpin: true,
project_type: undefined,
sort: "updated_on",
});
const { limit, sort, category_id } = this.state;
this.getListData(1, limit, value, sort, undefined, category_id);
};
sort: "updated_on"
})
const {sort, category_id , languageId } = this.state;
this.getListData(1,value, sort,category_id , languageId);
}
changeSearchValue = (e) => {
this.setState({
search: e.target.value,
});
};
search: e.target.value
})
}
// 翻页
ChangePage = (page) => {
this.setState({
page,
});
const { limit, search, sort, project_type, category_id } = this.state;
this.getListData(page, limit, search, sort, project_type, category_id);
};
page
})
const {search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort, category_id , languageId);
}
render() {
const { current_user } = this.props;
const menu = (
getoDetail=(login,identifier)=>{
this.props.history.push(`/projects/${login}/${identifier}`);
}
menu =()=> {
return(
<Menu onClick={this.ChangeSoryBy}>
<Menu.Item key="updated_on">更新时间排序</Menu.Item>
<Menu.Item key="created_on">创建时间排序</Menu.Item>
<Menu.Item key="forked_count">fork数据排序</Menu.Item>
<Menu.Item key="praises_count">点赞数量排序</Menu.Item>
</Menu>
);
const newItem = (
)
}
newItem = ()=>{
return(
<Menu>
<Menu.Item key="created_mirror">
<Link to={`/projects/mirror/new`}>新建镜像项目</Link>
</Menu.Item>
<Menu.Item key="created_deposit">
<Link to={`/projects/deposit/new`}>新建托管项目</Link>
</Menu.Item>
<Menu.Item key="created_mirror"><Link to={`/projects/mirror/new`}>新建镜像项目</Link></Menu.Item>
<Menu.Item key="created_deposit"><Link to={`/projects/deposit/new`}>新建托管项目</Link></Menu.Item>
</Menu>
);
)
}
const {
projectsList,
isSpin,
total,
search,
limit,
page,
typeList,
categoryList,
languageSpin,
categorySpin,
} = this.state;
pagination=(total,limit,page)=>{
return(
total && total > limit ?
<div className="edu-txt-center pt30 mb30 border-top-grey">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
)
}
render() {
const { current_user } = this.props;
const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state;
const pagination =
total && total > limit ? (
<div className="edu-txt-center pt30 mb30 border-top-grey">
<Pagination
simple
defaultCurrent={page}
total={total}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
);
return (
<div>
<div className="banner_list_img">
<img src={banner_list}></img>
</div>
<p className="t_project_banner"></p>
<p className="t_project_banner">
<img src={banner} width="100%" alt=""/>
</p>
{/* {
recommendList && recommendList.length>0 &&
<div className="recommandProjects">
{
recommendList.map((item,key)=>{
return(
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
<div className="mainInfo">
<img src={getUrl(`/images/${item.author && item.author.image_url}`)} alt=""/>
<p className="school">{item.name}</p>
<p className="name">{item.author && item.author.name}</p>
</div>
<div className="baseInfo">
<span className="look"><i className="iconfont icon-dianjiliang font-12"></i>{item.visits}</span>
<span className="type">{item.category && item.category.name}</span>
</div>
</div>
)
})
}
</div>
}
*/}
<div className="ProjectListIndex">
<div className="list-left">
<Affix offsetTop={5} style={{ position: "sticky", maxHeight: "100vh"}}>
<div className="mb20">
<Spin spinning={languageSpin}>
<ul className="list-l-Menu">
<li className="MenuTitle">
<i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
语言
</li>
<div className="list-affix">{typeList}</div>
</ul>
</Spin>
</div>
<div className="mb20">
<Spin spinning={categorySpin}>
<ul className="list-l-Menu">
<li className="MenuTitle">
<i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i>
项目类别
</li>
<div className="list-affix">{categoryList}</div>
</ul>
</Spin>
</div>
</Affix>
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
语言</li>
<div className="list-affix">{typeList}</div>
</ul>
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i></li>
<div className="list-affix">{categoryList}</div>
</ul>
</div>
<div
className="list-right boxShandow radius-2"
style={{ padding: 0 }}
>
<div className="list-right boxShandow radius-2" style={{padding:0}}>
<Spin spinning={isSpin}>
<div className="list-r-operation">
<Search
placeholder="输入项目名称关键字进行搜索"
enterButton="搜索"
size="large"
onSearch={this.searchFun}
className="list-r-Search"
value={search}
onChange={this.changeSearchValue}
/>
<div>
{current_user && current_user.login && (
<Popover
content={newItem}
trigger={["click"]}
placement="bottom"
className="mr50"
>
<Search
placeholder="输入项目名称关键字进行搜索"
enterButton="搜索"
size="large"
onSearch={this.searchFun}
className="list-r-Search"
value={search}
onChange={this.changeSearchValue}
/>
</div>
<div>
{
current_user && current_user.login &&
<Popover content={this.newItem()} trigger={["click"]} placement='bottom' className="mr50">
<a className="ant-dropdown-link">
<span className="color-blue font-16">
<img src={img_new} alt="" width="13px" /> 新建
</span>
<span className="color-blue font-16"><img src={img_new} alt="" width="13px" /> 新建</span>
</a>
</Popover>
)}
}
<Popover
content={menu}
trigger={["click"]}
placement="bottom"
>
<Popover content={this.menu()} trigger={['click']} placement='bottom'>
<a className="ant-dropdown-link">
<span className="color-blue font-16">
排序 <img src={img_array} alt="" width="10px" />
</span>
<span className="color-blue font-16">排序 <img src={img_array} alt="" width="10px" /></span>
</a>
</Popover>
</div>
</div>
<ListItem
{...this.props}
{...this.state}
projects={projectsList}
></ListItem>
{pagination}
<ListItem {...this.props} {...this.state} projects={projectsList} getListData={this.getListData}></ListItem>
{this.pagination(total,limit,page)}
</Spin>
</div>
</div>
</div>
);
)
}
}
export default Index;

86
src/forge/Main/Index.scss Normal file
View File

@ -0,0 +1,86 @@
/* recommandProjects */
.recommandProjects{
display: flex;
max-width: 1200px;
margin:20px auto;
}
.recommandProjects >div{
background-color: #fff;
border-radius: 10px;
width: 220px;
margin-right: 25px;
cursor: pointer;
&:last-child{
margin-right: 0px;
}
}
.recommandProjects > div:hover{
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.1);
}
.recommandProjects > div .mainInfo{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 160px;
border-bottom: 1px solid #eee;
padding:20px;
box-sizing: border-box;
img{
height: 50px;
width:50px;
border-radius: 50%;
}
.name{
font-size: 13px;
color: #666;
height: 18px;
line-height: 18px;
margin-top:12px;
}
.school{
margin-top:12px;
color: #333;
font-size: 16px;
height: 22px;
line-height: 22px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width:100%;
}
}
.recommandProjects{
.baseInfo{
padding:18px 15px;
display: flex;
font-size: 12px;
color:#888;
.look{
i{
margin-right: 5px;
}
margin-right: 10px;
}
.type{
flex:1;
width:0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: right;
}
}
}
.singleBtn{
display: inline-block;
.ant-upload-list-item{
position: absolute;
bottom: 0px;
width: 100%;
left: 0px;
.ant-upload-list-item-name{
text-align: left;
}
}
}

View File

@ -6,26 +6,80 @@ import '../css/index.scss';
import Nodata from '../Nodata';
import './list.css';
import img_parise from '../Images/parise.png';
import SpecialModal from './SpecialModal';
class IndexItem extends Component {
constructor(props){
super(props);
this.state={
visible:false,
user_apply_signatures:[],
project_id:undefined
}
}
TurnToDetail = (login, url) => {
this.props.history.push({
pathname: url,
state: login
})
}
/**
* link:跳转到详情的地址
* user_apply_signatures:是否已经发送访问特殊开源项目的文件
* project_id项目id
* is_secret:是否是特殊开源许可证项目
* id创建者login
* is_member:是否是项目成员(如果是项目成员可以直接进入项目)
* */
projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{
const { user , showLoginDialog } = this.props;
if(is_secret && (!user || (user && !user.login))){
showLoginDialog();
return;
}
let signa = user_apply_signatures && user_apply_signatures[0];
if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){
this.setState({
visible:true,
user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined,
project_id
})
}else{
this.props.history.push(link);
}
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
const { getListData } = this.props;
getListData && getListData(1);
}
render() {
const { projects } = this.props;
const { visible , user_apply_signatures , project_id } = this.state;
const renderList = (
projects && projects.length > 0 ? projects.map((item, key) => {
return (
<div className="p-r-Item" key={key}>
<Link to={`/users/${item.author.login}`} className="show-user-link">
<img className="p-r-photo" alt="" src={getImageUrl(`images/${item.author && item.author.image_url}`)} ></img>
</Link>
{
item.platform === "educoder" ?
<a style={{cursor:"default"}} className="show-user-link">
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
</a>
:
<Link to={`/users/${item.author.login}`} className="show-user-link">
<img className="p-r-photo" alt="" src={getImageUrl(`${item.author && item.author.image_url}`)} ></img>
</Link>
}
<div className="p-r-Infos">
<div className="p-r-name">
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
<a onClick={()=>this.projectHref(`/projects/${item.author.login}/${item.identifier}`,item.user_apply_signatures, item.id,item.is_secret,item.author.login,item.is_member)} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
{item.author.name}/{item.name}
{
item.forked_from_project_id ?
@ -44,19 +98,19 @@ class IndexItem extends Component {
<i className="iconfont icon-jingxiang font-18 color-green" />
</span>:""
}
</Link>
</a>
<span className="p-r-tags">
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> ({item.praises_count})</span>
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork ({item.forked_count})</span>
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> {item.praises_count}</span>
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
</span>
</div>
<p className="break_word task-hide-2 mt8 color-grey-3 " style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<div className="p-r-about">
<span className="p-r-detail">
<span><label>浏览量</label>{item.visits}</span>
{item.category && item.category.id && <span><label>项目类别</label>{item.category.name}</span>}
{item.last_update_time ? <span ><label>更新于</label>{item.time_ago}</span> : ""}
{/* <span><label>浏览量:</label>{item.visits}</span> */}
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
</span>
</div>
@ -67,6 +121,7 @@ class IndexItem extends Component {
)
return (
<div className="project-list minH-670">
<SpecialModal {...this.props} visible={visible} hideModal={this.hideModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
{renderList}
</div>
)

View File

@ -0,0 +1,49 @@
import React , { useEffect , useState } from 'react';
import { Modal } from 'antd';
import UploadSingle from '../Upload/single';
import './Index.scss';
import axios from 'axios';
import { getUrl } from 'educoder';
function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){
const [ id ,setId ] = useState(undefined);
function loadFunc(id){
setId(id);
}
function sure(){
if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){
if(!id || (id && id.length === 0)){
showNotification("请先提交文件进行审核!");
return;
}
const url = `/apply_signatures.json`;
axios.post(url,{
attachment_id:id,
project_id:project_id
}).then(result=>{
if(result && result.data.id){
showNotification("已提交文件,正在等待审核!");
sureModal();
}
})
}else{
sureModal();
}
}
return(
<Modal title="提示" visible={visible} closable={false} onCancel={hideModal} onOk={sure}>
{
!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ?
<div style={{width:"420px",textAlign:'center',margin:"0 auto",paddingBottom:"30px",position:"relative"}}>
<div>该项目为私有项目请先<a href={getUrl(`/api/apply_signatures/template_file`)} className="color-blue">下载</a>开源协议,阅读并填写<br/>相关信息后将协议<UploadSingle size={"5"} load={loadFunc} showNotification={showNotification} className={'singleBtn'}><span className="color-blue" style={{cursor:"pointer"}}>上传</span></UploadSingle>,平台审核通过后即可进入当前项目</div>
</div>
:
<p style={{textAlign:'center'}}>您上传的文件正在审核中,通过后才能访问当前项目</p>
}
</Modal>
)
}
export default SpecialModal;

View File

@ -1,17 +1,9 @@
.lineH2{line-height:2}
/* .t_project_banner {
height: 260px;
background: url(../Images/banner_list.png) no-repeat center;
.t_project_banner {
/* height: 260px;
background: url(../Images/banner_list.jpg) no-repeat center; */
background-color: #050d34;
} */
.banner_list_img{
/* max-height: 260px; */
}
.banner_list_img img{
width: 100%;
height: 100%;
}
.ProjectListIndex{
width: 1200px;
@ -55,7 +47,7 @@
flex-wrap: wrap;
align-items: center;
padding:25px 30px;
border-bottom: 1px solid #eeeeee;
border-bottom: 1px solid #E0E0E0;
}
.list-r-Search{
width: 400px;
@ -77,6 +69,7 @@
color: #fff!important;
}
/* 列表 */
.project-list{
padding:0px 30px;
@ -96,15 +89,10 @@
box-shadow:0px 2px 20px 10px rgba(0,0,0,0.03);
}
.p-r-photo{
width: 40px;
height: 40px;
width: 60px;
height: 60px;
border-radius: 50%;
margin-right: 18px;
}
.p-r-detail{
font-size: 12px;
color: #888888;
line-height: 16px;
margin-right: 22px;
}
.p-r-Infos{
flex: 1;
@ -227,6 +215,18 @@ line-height: 16px;
display: flex;
flex-direction: row;
}
.headerMenu-wrapper li{
position: relative;
text-align: center;
height: 40px;
line-height: 28px;
border:1px solid transparent;
}
.headerMenu-wrapper{
font-size: 16px;
display: flex;
flex-direction: row;
}
.headerMenu-wrapper li{
padding:0px 18px;
position: relative;
@ -243,14 +243,9 @@ line-height: 16px;
margin-right: 8px;
}
.headerMenu-wrapper li a > span{
background-color: #676AF1;
height: 18px;
line-height: 18px;
border-radius: 10px;
display: block;
padding:0px 6px;
margin-left: 5px;
font-size: 11px;
font-size: 16px;
}
.headerMenu-wrapper li.active{
border-radius: 15px;
@ -268,6 +263,7 @@ line-height: 16px;
.ant-tooltip {
max-width: fit-content!important;
}
.detail_tag_btn_name{
padding:0px 10px;
display: flex;
@ -309,6 +305,7 @@ line-height: 16px;
.branch-wrapper > a >i{
color: #5091FF;
margin-right: 5px;
cursor: default;
}
.branch-wrapper a{
display: flex;
@ -426,6 +423,7 @@ line-height: 16px;
padding: 13px 16px!important;
}
.commitKey{
cursor: pointer;
border:1px solid #FD7700;
background-color:#FFF3DC;
color: #FD7700!important;

View File

@ -0,0 +1,35 @@
import React from 'react';
import { AlignCenter , FlexAJ } from '../Component/layout';
import User from '../Component/User';
import { truncateCommitId } from '../common/util';
import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
function Commits({ commits , projectsId , owner }){
return(
<div className="pb20">
{
commits.map((item,key)=>{
return(
<div className="prCommits">
<p className="prCreate">{item.created_at}</p>
<div className="prInfo">
<FlexAJ>
<AlignCenter>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</Link>
<p className="ml15 font-16 color-grey-3 task-hide" style={{maxWidth:"700px"}}>{item.message}</p>
</AlignCenter>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(item.sha)}`} className="color-blue">浏览代码</Link>
</FlexAJ>
<AlignCenter className="mt15">
<User url={getImageUrl(`images/${item.committer && item.committer.image_url}`)} name={`${item.committer && item.committer.name}`}></User><span>提交于{item.time_from_now}</span>
</AlignCenter>
</div>
</div>
)
})
}
</div>
)
}
export default Commits;

86
src/forge/Merge/Files.jsx Normal file
View File

@ -0,0 +1,86 @@
import React ,{useEffect,useState } from 'react';
import { truncateCommitId } from '../common/util';
import { AlignCenter , FlexAJ } from '../Component/layout';
import { Button } from 'antd';
import './merge.css';
function Files({data,history,owner,projectsId}){
const [ files , setFiles ] = useState(data && data.files);
useEffect(()=>{
if(data){
setFiles(data.files);
}
},[data])
function showDown(flag,index,isBin){
if(!isBin){
var lists = files.concat();
lists[index].flag = !flag ? true : false;
lists.splice();
setFiles(lists);
}
}
return(
<div>
<AlignCenter className="color-grey-9 pb10" style={{borderBottom:"1px solid #eee"}}>
<i className="iconfont icon-sanjiaoxing-down mr5"></i>
<span>
共有<span className="color-grey-3"> {data && data.files_count} 个文件被更改</span>包括
{ data && data.total_addition ? <span className="color-green"> {data && data.total_addition} 次插入</span>:"" }
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
</span>
</AlignCenter>
{
files && files.length>0 &&
<div>
{
files.map((item,key)=>{
return(
<div className="files" key={key}>
<FlexAJ className="filesInfo" style={{cursor:item.isBin ? "default":"pointer"}} onClick={()=>showDown(item.flag,key,item.isBin)}>
<AlignCenter>
{!item.isBin ? <i className={!item.flag?"iconfont icon-xiajiantou font-16 mr15 color-grey-9":"iconfont icon-youjiantou font-16 mr15 color-grey-9"}></i>:""}
<i className="iconfont icon-wenjia font-16 mr8 color-grey-9"></i>
<span>{item.name}</span>
</AlignCenter>
<span>
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}${item.sha ? `/branch/${truncateCommitId(item.sha)}?`:"?"}url=${item.name}`)}}>查看文件</Button>
<span className="color-green">+{item.addition}</span>
<span className="color-red ml20">-{item.deletion}</span>
</span>
</FlexAJ>
{
item.sections && item.sections.length >= 1 && !item.flag &&
<div className="filesContent">
{
item.sections.map((i,k)=>{
return(
i.lines && i.lines.length>0 && i.lines.map((item,key)=>{
return(
<div key={k+key} className={(item.type === 2) ? "linesContent add" : item.type === 3 ? "linesContent reduce": item.type===4?"linesContent translate":"linesContent"}>
<span className="lines">
<span>{item.leftIdx && item.leftIdx !=="0" ? item.leftIdx :"" }</span>
<span>{item.rightIdx && item.rightIdx !=="0" ? item.rightIdx :"" }</span>
</span>
<p>{item.content}</p>
</div>
)
})
)
})
}
</div>
}
</div>
)
})
}
</div>
}
</div>
)
}
export default Files;

View File

@ -214,7 +214,7 @@ class MergeDetail extends Component {
)
} else {
return (
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
)
}
}

View File

@ -98,7 +98,7 @@ class MergeItem extends Component {
<span className="ml15">
<Tag className="pr-branch-tag">
<Link
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }?branch=${item.pull_request_head}`}
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/branch/${item.pull_request_head}`}
className="maxW200px hide-1 ver-middle"
>
{item.is_original
@ -116,7 +116,7 @@ class MergeItem extends Component {
</span>
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${projectsId}?branch=${item.pull_request_base}`}
to={`/projects/${owner}/${projectsId}/branch/${item.pull_request_base}`}
className="maxW200px hide-1 ver-middle"
>
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}

View File

@ -5,6 +5,7 @@ import axios from 'axios';
import{ Form , Table , Spin } from 'antd'
import { getImageUrl } from 'educoder';
import {Link} from "react-router-dom";
import { truncateCommitId} from '../common/util';
class MergeSubmit extends Component{
constructor(props){
super(props);
@ -36,7 +37,6 @@ class MergeSubmit extends Component{
}
getDetail=()=>{
const { projectsId , mergeId, owner} = this.props.match.params;
const url = `/projects/${owner}/${projectsId}/pull_requests/${mergeId}.json`;
axios.get(url).then((result)=>{
@ -83,8 +83,16 @@ class MergeSubmit extends Component{
}).catch((error)=>{console.log(error)})
}
title =()=>{
return(
<div className="f-wrap-between" style={{alignItems:"center"}}>
<span className="font-16">提交列表</span>
</div>
)
}
render(){
const { projectsId , owner } = this.props.match.params;
const { titledata } = this.state;
const columns=[{
title:"作者",
@ -102,7 +110,7 @@ class MergeSubmit extends Component{
title:"SHA",
dataIndex: 'sha',
render: (text) => (
<span className="commitKey">{text}</span>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${text}`)}`} className="commitKey">{text}</Link>
)
},{
title:"备注",
@ -118,14 +126,6 @@ class MergeSubmit extends Component{
<span>{text}</span>
)
}]
const title =()=>{
return(
<div className="f-wrap-between" style={{alignItems:"center"}}>
<span className="font-16">提交列表</span>
</div>
)
}
return(
<Spin spinning={this.state.isSpin}>
@ -136,11 +136,9 @@ class MergeSubmit extends Component{
showHeader={false}
size="small"
pagination={false}
title={() => title()}
title={() => this.title()}
/>
</Spin>
// </div>
// </div>
)
}
}

View File

@ -1,6 +1,7 @@
import React, { Component } from "react";
import { Tabs } from 'antd';
import { Link } from "react-router-dom";
import { AlignCenter } from '../Component/layout';
import axios from "axios";
import { getImageUrl } from "educoder";
import {
@ -39,6 +40,9 @@ class MessageCount extends Component {
SpinMerge: false,
edit_spin: false,
pr_status: undefined,
pull_request:undefined,
copyVisible:false,
};
}
@ -47,7 +51,18 @@ class MessageCount extends Component {
SpinFlag: true,
});
this.getDetail();
// this.clickBody();
};
clickBody=()=>{
document.body.addEventListener('click', e => {
let name = e.target.className;
if(name.indexOf("notHide")>-1 || name.indexOf("ant-tabs-tab")>-1 || name==="ant-tabs-nav-scroll"){return;}
this.setState({
copyVisible:false
})
})
}
getDetail = () => {
const { projectsId, mergeId, owner } = this.props.match.params;
@ -55,11 +70,12 @@ class MessageCount extends Component {
axios
.get(url)
.then((result) => {
if (result) {
if (result && result.data) {
this.setState({
data: result.data,
SpinFlag: false,
pr_status: result.data.pull_request.status,
pr_status: result.data.pull_request && result.data.pull_request.status,
pull_request:result.data.pull_request
});
} else {
this.setState({ SpinFlag: false });
@ -106,12 +122,12 @@ class MessageCount extends Component {
SpinMerge: true,
});
const { projectsId , owner } = this.props.match.params;
const { data, title, body, mergekey, pr_status } = this.state;
const url = `/${owner}/${projectsId}/pulls/${data.pull_request.id}/pr_merge.json`;
const { title, body, mergekey, pull_request } = this.state;
const url = `/${owner}/${projectsId}/pulls/${pull_request.id}/pr_merge.json`;
axios
.post(url, {
project_id: projectsId,
id: data.pull_request.id,
id: pull_request.id,
do: mergekey,
body: body,
title: title,
@ -195,9 +211,36 @@ class MessageCount extends Component {
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments imageLayerParent" value={v} />;
return <RenderHtml className="break_word_comments imageLayerParent" value={v} url={this.props.history.location}/>;
};
setCopyVisible=(e)=>{
e.stopPropagation();
this.setState({
copyVisible:true
})
}
copyItem =()=>{
return(
<div className="copyTab notHide">
<Tabs defaultActiveKey="1" className="notHide" animated={false} size={"small"}>
<Tabs.TabPane key="1" tab={<span className="notHide">HTTPS</span>}>{this.returnCopyUrl("https://gitee.com/44886/polhttp.git")}</Tabs.TabPane>
<Tabs.TabPane key="2" tab={<span className="notHide">SSH</span>}>{this.returnCopyUrl("https://gitee.com/44886/polssh.git")}</Tabs.TabPane>
</Tabs>
</div>
)
}
returnCopyUrl=(url)=>{
return(
<div className="df notHide">
<Input value={url} className="notHide" disabled={true}/>
<Button type="primary" ghost className="ml15 notHide">复制</Button>
</div>
)
}
render() {
const { projectsId, mergeId , owner } = this.props.match.params;
@ -208,8 +251,15 @@ class MessageCount extends Component {
isSpin,
ismesrge,
SpinFlag,
copyVisible,
pull_request
} = this.state;
const { current_user, projectDetail } = this.props;
const permission = projectDetail && (projectDetail.permission === "Admin" || projectDetail.permission === "Owner" || projectDetail.permission === "Manager");
const userLogin = current_user && current_user.login;
const operate = userLogin && projectDetail && pr_status === 0 && permission;
const menu = (
<Menu onClick={(e) => this.getOption(e)}>
<Menu.Item key={"merge"} value="合并请求">
@ -238,13 +288,13 @@ class MessageCount extends Component {
<div className="ver-middle">
<span className="mr10 ver-middle">
<span className="font-18 fwb">
{data.issue.subject}
{ data.issue && data.issue.subject}
</span>
</span>
{data.pull_request && (
{pull_request && (
<Tag
className={`pr_tags_${data.pull_request.pull_request_staus}`}
className={`pr_tags_${pull_request.pull_request_staus}`}
>
{pr_status === 1
? "已合并"
@ -258,10 +308,10 @@ class MessageCount extends Component {
<div className="mt15">
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${data.pull_request.is_original?data.pull_request.identifier:projectsId}?branch=${data.pull_request.head}`}
to={`/projects/${owner}/${pull_request.is_original?data.project_identifier:projectsId}/branch/${pull_request.head}`}
className="ver-middle"
>
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head}
{pull_request.is_original ? pull_request.fork_project_user : data.issue.project_author_name}:{pull_request.head}
</Link>
</Tag>
<span className="mr8 ver-middle">
@ -273,11 +323,11 @@ class MessageCount extends Component {
</span>
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${projectsId}?branch=${data.pull_request.base}`}
to={`/projects/${owner}/${projectsId}/branch/${pull_request.base}`}
className="ver-middle"
>
{/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */}
{data.issue.project_author_name}:{data.pull_request.base}
{data.issue.project_author_name}:{pull_request.base}
</Link>
</Tag>
</div>
@ -352,24 +402,29 @@ class MessageCount extends Component {
</div>
</div>
<div className="ml10">
<div className="mt15 text-right">
{current_user && projectDetail &&
pr_status !== 2 &&
projectDetail.permission !=="Reporter" && (
<div className="mt15 text-right" style={{display:"flex",justifyContent:"flex-end"}}>
{/* <span className="composeButton">
<Dropdown overlay={this.copyItem()} visible={copyVisible} onClick={(e)=>this.setCopyVisible(e)}>
<span>复制</span>
</Dropdown>
<span>下载为<i className="iconfont icon-sanjiaoxing-down color-blue"></i></span>
</span> */}
{operate && (
<Button
type="success"
type="green"
ghost
className="ml20"
onClick={()=>{this.props.history.push(`/projects/${owner}/${projectsId}/pulls/${mergeId}/UpdateMerge`);}}
>
编辑
</Button>
)}
{projectDetail && projectDetail.permission !=="Reporter" && pr_status === 0 && (
{operate && (
<Button
type="danger"
ghost
onClick={() => this.closedetail()}
className="ml15"
className="ml20"
loading={isSpin}
>
拒绝
@ -378,14 +433,12 @@ class MessageCount extends Component {
</div>
</div>
</div>
<div className="mt15">
{data.issue.description &&
data.issue.description.length > 0 ? (
this.commentCtx(data.issue.description)
) : (
<span className="color-grey-9 ml3 mr3">没有描述</span>
)}
</div>
{
data.issue.description ?
<div className="mt15">{this.commentCtx(data.issue.description)}</div>
:
<p className="color-grey-9 ml3 mr3 mt15">没有描述</p>
}
</div>
<div className="mt15">
{pr_status === 2 && (
@ -473,14 +526,12 @@ class MessageCount extends Component {
</div>
</div>
<div className=" main">
<MergeFooter
footer_type="show"
order_id={data && data.issue.id}
{...this.props}
{...this.state}
></MergeFooter>
</div>
<MergeFooter
footer_type={true}
order_id={data && data.issue.id}
{...this.props}
{...this.state}
></MergeFooter>
</div>
) : (
""

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import { Input, Select, Button, Spin, Alert } from "antd";
import { Input, Select , Spin, Alert } from "antd";
import axios from "axios";
import "../Order/order.css";
import "./merge.css";
@ -24,21 +24,42 @@ class NewMerge extends Component {
merge_head: false, // 是否向fork后的源项目发起合并请求
default_message: "必须选择不同的分支",
project_id: undefined, // 当前项目的id也即开始发送合并请求的源项目id
merge_project_user: undefined
merge_project_user: undefined,
oldProject:undefined,//保存选择目标分支、跳转页面后会刷新的project
comparesData:undefined,//提交和文件的内容保存compare接口返回的数据
};
}
componentDidMount = () => {
const { projectsId } = this.props.match.params;
this.getmergelist(projectsId);
// 监听回退事件
if (window.history && window.history.pushState) {
window.addEventListener('popstate', this.handleBack, false);
}
};
//获取新建分枝数据
componentDidUpdate=(preProps)=>{
const { project } = this.props;
let oldProject = preProps.project;
if(project && oldProject && (oldProject.id !== project.id)){
this.compareProject(this.state.id,"master","master");
}
}
// 页面销毁取消监听
componentWillUnmount () {
window.removeEventListener('popstate', this.handleBack, false);
};
handleBack=()=>{
const { projectsId } = this.props.match.params;
this.getmergelist(projectsId);
}
//获取新建分支数据
getmergelist = (projectsId) => {
this.setState({isSpin: true})
const { owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/pulls/new.json`;
axios
.get(url)
@ -56,6 +77,7 @@ class NewMerge extends Component {
this.set_default_pull(result.data.branches);
this.set_default_merge(result.data.merge_projects);
}
this.compareProject(result.data.id,"master","master");
this.setState({isSpin: false})
})
.catch((error) => {
@ -64,6 +86,32 @@ class NewMerge extends Component {
});
};
// 获取compare接口
compareProject=(baseid , localBranch , mergeBranch)=>{
const { project } = this.props;
const { owner , projectsId } = this.props.match.params;
let url = `/${owner}/${projectsId}/compare`;
if(project){
if(baseid === project.id){
this.setState({
oldProject:project
})
url += `/${localBranch}...${mergeBranch}.json`;
}else{
const { oldProject } = this.state;
const { author , identifier } =oldProject;
url += `/${mergeBranch}...${author && author.login}/${identifier}:${localBranch}.json`;
}
axios.get(url).then(result=>{
if(result){
this.setState({
comparesData:result.data
})
}
}).catch(error=>{})
}
}
set_default_pull = (branches) => {
if(branches && branches.length>0){
let default_pull = branches.filter((e) => e.name === "master")
@ -117,12 +165,16 @@ class NewMerge extends Component {
selectBrach = (type, value) => {
this.state[type] = value;
this.ischeckmerge();
let { id ,merge , pull } = this.state;
if(type==="pull"){
this.compareProject(id,value,merge);
}else{
this.compareProject(id,pull,value);
}
};
selectProjectName = (value) => {
console.log("value",value)
const { project_id, projects_names,id } = this.state;
const { owner } = this.props.match.params;
const { projects_names,id } = this.state;
let arr = projects_names && projects_names.filter(item=>item.id===value);
let identifier = arr && arr[0].project_id;
let login = arr && arr[0].project_user_login;
@ -138,7 +190,6 @@ class NewMerge extends Component {
})
this.props.history.push(`/projects/${login}/${identifier}/pulls/new`);
this.newMergelist(login,identifier);
};
//判断2分支是否可以合并
@ -146,7 +197,7 @@ class NewMerge extends Component {
ischeckmerge = () => {
this.setState({ isSpin: true });
const { projectsId , owner } = this.props.match.params;
const { pull, merge, project_id, merge_head, id } = this.state;
const { pull, merge , merge_head, id } = this.state;
const url = `/${owner}/${projectsId}/pulls/check_can_merge.json`;
axios.post(url, {
head: pull,
@ -194,9 +245,9 @@ class NewMerge extends Component {
show_message,
default_message,
merge_head,
projects_names,
projects_names,id,comparesData
} = this.state;
const { projectsId } = this.props.match.params;
const renderBrances = (list, type) => {
if (list && list.length > 0) {
return list.map((item, key) => {
@ -228,29 +279,26 @@ class NewMerge extends Component {
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
};
let { project } = this.props;
console.log("222 ",project);
console.log("222111 ",projects_names);
return (
<div>
<div className="main">
<Spin spinning={isSpin}>
<div className="merge-header width100 inline-block">
<div className="width45 pull-left">
<div className="width40 pull-left">
<div className="color-grey-3 mb10 fwb">源分支:</div>
<Input.Group compact className="display-flex">
<Select
defaultValue={project && project.id}
class=" maxW50 hide-1 task-hide"
value={id}
className="hide-1 task-hide flex1"
disabled
style={{maxWidth:"200px"}}
>
{renderProjectNames(projects_names)}
</Select>
<Select
defaultValue={pull}
value={pull}
onSelect={(e) => this.selectBrach("pull", e)}
showSearch
className="minW50 merge-flex1"
className="merge-flex1 flex1"
>
{renderBrances(branches, false)}
</Select>
@ -261,24 +309,22 @@ class NewMerge extends Component {
className={"iconfont icon-youjiang color-grey-c font-32"}
></i>
</div>
<div className="width45 pull-left">
<div className="width40 pull-left">
<div>
<div className="color-grey-3 mb10 fwb">目标分支:</div>
<Input.Group compact className="display-flex">
<Select
defaultValue={project && project.id}
class=" maxW50 hide-1 task-hide"
value={project && project.id}
className="hide-1 task-hide flex1"
onSelect={(e) => this.selectProjectName(e)}
style={{maxWidth:"200px"}}
>
{renderProjectNames(merge_projects)}
</Select>
<Select
defaultValue={merge}
value={merge}
onSelect={(e) => this.selectBrach("merge", e)}
showSearch
className="minW50 merge-flex1"
className="merge-flex1 flex1"
>
{renderBrances(merge_branches, merge_head)}
</Select>
@ -297,10 +343,20 @@ class NewMerge extends Component {
data={data}
merge={merge}
pull={pull}
files_count={comparesData && comparesData.diff && comparesData.diff.files_count}
commits_count={comparesData && comparesData.commits_count}
></MergeForm>
)}
</Spin>
</div>
<MergeFooter
order_id={data && data.issue && data.issue.id}
{...this.props}
{...this.state}
merge={merge}
pull={pull}
comparesData={comparesData}
></MergeFooter>
</div>
);
}

View File

@ -37,11 +37,15 @@ class UpdateMerge extends Component {
merge: result.data.base,
});
} else {
this.setState({ isSpin: false });
this.setState({
isSpin: false,
});
}
})
.catch((error) => {
this.setState({ isSpin: false });
this.setState({
isSpin: false,
});
console.log(error);
});
};
@ -52,6 +56,7 @@ class UpdateMerge extends Component {
<div>
<div className="main">
<Spin spinning={isSpin}>
{" "}
{data ? (
<div>
<div className="merge-header width100 inline-block">
@ -66,17 +71,17 @@ class UpdateMerge extends Component {
defaultValue={data.is_original ? `${data.fork_project_user}:${pull}` : `${pull}`}
className="minW50 merge-flex1"
disabled
></Select>
</Input.Group>
</div>
></Select>{" "}
</Input.Group>{" "}
</div>{" "}
<div className="width10 pull-left text-center mt25">
<i
className={"iconfont icon-youjiang color-grey-c font-32"}
></i>
</div>
></i>{" "}
</div>{" "}
<div className="width45 pull-left">
<div>
<div className="color-grey-3 mb10 fwb">目标分支:</div>
<div className="color-grey-3 mb10 fwb"> 目标分支 : </div>{" "}
<Input.Group compact className="display-flex">
<Button className="merge-header-button maxW50 hide-1 task-hide">
{`${data.project_author}/${data.project_name}`}
@ -85,19 +90,18 @@ class UpdateMerge extends Component {
defaultValue={data.is_original ? `${data.project_login}:${merge}` : `${merge}`}
className="minW50 merge-flex1"
disabled
></Select>
</Input.Group>
</div>
</div>
></Select>{" "}
</Input.Group>{" "}
</div>{" "}
</div>{" "}
</div>
<MergeForm
{...this.props}
merge_type="edit"
data={data}
merge={merge}
pull={pull}
></MergeForm>
></MergeForm>{" "}
</div>
) : (
""

View File

@ -40,4 +40,161 @@ form .ant-cascader-picker, form .ant-select {
}
.merge-header-button{
background:rgba(241,248,255,1);
}
.width70{
width:70%;
}
.width30{
width:30%;
}
.width40{
width:40%;
}
.display-flex{
display: flex!important;
}
.w120{
width: 120px;
}
.w240{
width: 240px;
}
.custom-commit-tabs .ant-tabs-nav .ant-tabs-tab{
padding:14px 0px!important;
}
.custom-commit-tabs .ant-tabs-bar{
border-bottom: none;
}
.custom-commit-tabs .ant-tabs-nav .ant-tabs-tab-active .tabNum{
background-color: #EBF4FE;
}
.custom-commit-tabs .ant-tabs-ink-bar{
width: 34px!important;
}
.tabNum{
display: inline-block;
margin-left:8px ;
border-radius: 10px;
height: 18px;
line-height: 18px;
background-color: #eee;
padding:0px 9px;
font-size: 12px;
}
/* 复制-下载为,组合按钮 */
.composeButton{
display: flex;
border:1px solid #5091FF;
border-radius: 5px;
height: 34px;
line-height: 34px;
}
.composeButton > span{
display: block;
padding:0px 18px;
color: #5091FF;
display: flex;
align-items: center;
border-radius: 5px;
cursor: pointer;
}
.composeButton > span:hover{
background-color: #F1F8FF;
}
.composeButton > span:first-child{
border-radius: 5px 0px 0px 5px;
border-right: 1px solid #5091FF;
}
.ant-btn{
border-radius: 5px;
}
/* 绿色按钮-type="green" */
.ant-btn.ant-btn-green{
border:1px solid #28BD6C;
color: #28BD6C;
}
.copyTab{
min-width: 370px;
padding:0px 18px 22px 18px;
box-shadow: 0px 2px 10px rgba(0,0,0,0.2);
background-color: #fff;
}
.copyTab .ant-tabs-tab{
padding:12px 0px!important;
}
/* pr--提交tab页面 */
.prCommits{
border:1px solid #ddd;
border-top: none;
}
.prCommits:first-child{
border-top: 1px solid #ddd;
}
.prCommits .prCreate{
height: 50px;
line-height: 50px;
padding:0px 25px;
background-color:#fafafa;
color:#333;
font-size: 16px;
border-bottom: 1px solid #ddd;
}
.prCommits .prInfo{
padding:20px 25px;
}
/* pr-文件修改信息页面 */
.files{
border:1px solid #ddd;
margin-top: 15px;
border-radius: 2px;
}
.filesInfo{
padding:10px 15px;
background-color: #fafafa;
}
.filesContent{
border-top: 1px solid #ddd;
}
.linesContent{
display: flex;
min-height: 30px;
line-height: 30px;
color: #333;
flex-wrap: wrap;
}
.linesContent > p{
flex:1;
}
.linesContent .lines{
display: flex;
border-right: 1px solid #ddd;
width: 100px;
padding: 0px 8px;
box-sizing: border-box;
margin-right: 8px;
}
.linesContent .lines > span:first-child{
margin-right: 0px;
}
.linesContent .lines > span{
width: 50%;
text-align: right;
display: block;
color: #888;
}
.linesContent.translate{
background-color:#F1F8FF;
}
.linesContent.translate .lines > span{
border-right: 1px solid transparent;
}
.linesContent.reduce{
background-color:rgba(247, 48, 48, 0.15);;
}
.linesContent.add{
background: rgba(48, 232, 132, 0.15);
}

View File

@ -423,7 +423,7 @@ class merge extends Component {
</Spin>
</div>
) : (
<NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} />
<NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} />
)}
</div>
);

View File

@ -1,45 +1,169 @@
import React, { Component } from "react";
import { Tabs, Empty } from "antd";
import { Tabs, Spin } from "antd";
import "../Order/order.css";
import "./merge.css";
import CodesCommit from "../Main/CoderRootCommit";
import Commits from "./Commits";
import Comments from "../comments/comments";
import Files from "./Files";
import axios from 'axios';
const { TabPane } = Tabs;
class MergeFooter extends Component {
constructor(props) {
constructor(props){
super(props);
this.state = {};
this.state={
pageData:undefined,
commitsData:undefined,
filesData:undefined,
isSpin:false,
activeKey:"1",
commitCount:0,
filesCount:0
}
}
componentDidMount=()=>{
const { footer_type ,data } = this.props;
if(footer_type){
const { projectsId , owner , mergeId } = this.props.match.params;
this.getCommit(owner,projectsId,mergeId);
this.getFile(owner,projectsId,mergeId);
}
this.setState({
activeKey:footer_type ? "1" : "2",
commitCount:data && data.commits_count,
filesCount:data && data.files_count
})
}
componentDidUpdate=(prevProps)=>{
const { comparesData } = this.props;
const { footer_type } = this.props;
if(footer_type){
const { data } = this.props;
if(data !== prevProps.data){
this.setState({
commitCount:data && data.commits_count,
filesCount:data && data.files_count
})
}
}
if(comparesData !== prevProps.comparesData){
this.setState({
activeKey:footer_type ? "1" : "2"
})
this.changeTab(footer_type ? "1" : "2");
}
}
changeTab=(index)=>{
this.setState({
isSpin:true
})
this.setState({
activeKey:index
})
const { footer_type , comparesData } = this.props;
const { projectsId , owner , mergeId } = this.props.match.params;
if(footer_type){
if(index === "2"){
this.getCommit(owner,projectsId,mergeId);
}else if(index === "3"){
this.getFile(owner,projectsId,mergeId);
}else{
this.setState({
isSpin:false
})
}
}else{
this.setState({
commitsData:comparesData.commits,
filesData:comparesData.diff,
commitCount:comparesData.commits_count,
filesCount:comparesData.diff && comparesData.diff.files_count,
isSpin:false
})
}
}
getCommit =(owner,projectsId,mergeId)=>{
const url = `/${owner}/${projectsId}/pulls/${mergeId}/commits.json`;
axios.get(url).then(result=>{
if(result){
this.setState({
commitsData:result.data.commits,
isSpin:false,
commitCount:result.data.commits_count
})
}
}).catch(error=>{})
}
getFile =(owner,projectsId,mergeId)=>{
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
axios.get(url).then(result=>{
if(result){
this.setState({
filesData:result.data,
isSpin:false,
filesCount:result.data.files_count,
})
}
}).catch(error=>{})
}
render() {
const { footer_type, order_id } = this.props;
const { projectsId , owner } = this.props.match.params;
const { footer_type, order_id, data , comparesData } = this.props;
let { isSpin , activeKey , filesCount, commitCount , filesData , commitsData } = this.state;
return (
<div>
<Tabs
defaultActiveKey={footer_type === "show" ? "1" : "2"}
className="custom-commit-tabs"
>
{
footer_type === "show" &&
<TabPane tab={<span className="ml-3 font-16">评论</span>} key="1">
<Comments
order_id={order_id}
showNotification={this.props.showNotification}
only_show_content={true}
{...this.props}
/>
</TabPane>
}
{/* <TabPane tab={<span className="ml-3 font-16"></span>} key="2">
<CodesCommit {...this.props} main_class="pd10"></CodesCommit>
</TabPane> */}
{/* <TabPane tab={<span className="ml-3 font-16"></span>} key="3">
<Empty />
</TabPane> */}
</Tabs>
!footer_type && !comparesData || (comparesData && ((comparesData.commits && comparesData.commits.length===0)||(comparesData && !comparesData.diff)) )?"":
<div className="main" style={{paddingTop:"0px"}}>
<Spin spinning={isSpin}>
<Tabs
activeKey={activeKey}
className="custom-commit-tabs"
animated={false}
onChange={this.changeTab}
>
{
footer_type &&
<TabPane
tab={
<span><span className="font-16">评论</span>
{data && parseInt(data.comments_count) > 0 && <span className="tabNum">{data.comments_count}</span>}
</span>
} key="1">
<Comments
order_id={order_id}
showNotification={this.props.showNotification}
only_show_content={true}
{...this.props}
/>
</TabPane>
}
{
commitsData && commitsData.length > 0 &&
<TabPane tab={<span><span className="font-16">提交</span>
{commitCount > 0 && <span className="tabNum">{commitCount}</span>}
</span>} key="2">
<Commits {...this.props} commits={commitsData} projectsId={projectsId} owner={owner}></Commits>
</TabPane>
}
{
filesData && filesData.files && filesData.files.length>0 &&
<TabPane tab={
<span><span className="font-16">文件</span>
{filesCount > 0 && <span className="tabNum">{filesCount}</span>}
</span>
} key="3">
<Files {...this.props} data={filesData} projectsId={projectsId} owner={owner}/>
</TabPane>
}
</Tabs>
</Spin>
</div>
);
}

View File

@ -138,7 +138,7 @@ class MergeForm extends Component {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId, mergeId , owner } = this.props.match.params;
const { merge, pull, merge_type, data } = this.props;
const { merge, pull, merge_type, data , commits_count , files_count } = this.props;
if (values.issue_tag_ids && values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [parseInt(values.issue_tag_ids)];
} else {
@ -154,7 +154,9 @@ class MergeForm extends Component {
base: merge,
is_original: data && data.is_original,
fork_project_id: data && data.fork_project_id,
merge_user_login: data && data.merge_user_login
merge_user_login: data && data.merge_user_login,
files_count,
commits_count
})
.then((result) => {
if (result) {
@ -221,7 +223,7 @@ class MergeForm extends Component {
};
render() {
const { merge_type, data } = this.props;
const { merge_type } = this.props;
const { getFieldDecorator } = this.props.form;
const { projectsId, mergeId ,owner } = this.props.match.params;
const {
@ -264,7 +266,7 @@ class MergeForm extends Component {
</Form.Item>
<MDEditor
placeholder={"请输入合并请求的描述..."}
height={350}
height={450}
mdID={"merge-new-description"}
initValue={desc}
onChange={this.onContentChange}

View File

@ -38,7 +38,9 @@ class Index extends Component {
project_language_name: undefined,
project_category_name: undefined,
license_name: undefined,
ignore_name: undefined
ignore_name: undefined,
licenseForDisabled:undefined
}
}
componentDidMount = () => {
@ -114,7 +116,7 @@ class Index extends Component {
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
}
let list = _data && _data.map((item) => (
<Option key={item.id} value={item.name}>
<Option key={item.id} value={item.name} onClick={()=>this.selectSerect(item.is_secret)}>
{item.name}
</Option>
));
@ -124,6 +126,17 @@ class Index extends Component {
}
}
selectSerect=(flag)=>{
if(flag){
this.props.form.setFieldsValue({
private:true
})
}
this.setState({
licenseForDisabled:flag
})
}
subMitFrom = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
@ -168,7 +181,8 @@ class Index extends Component {
}
ChangePlatform = (value, e, name, list) => {
this.setOptionsList(list, name, value)
this.setOptionsList(list, name, value);
this.setState({
[name + "_id"]: e.key,
[name + "_name"]: value,
@ -249,6 +263,7 @@ class Index extends Component {
project_category_list,
license_list,
ignore_list,
licenseForDisabled,
mirrorCheck
} = this.state;
@ -434,8 +449,8 @@ class Index extends Component {
style={{ margin: "0px" }}
className="privatePart"
>
{getFieldDecorator('private')(
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
{getFieldDecorator('private',{valuePropName:"checked"})(
<Checkbox value="limit" disabled={licenseForDisabled}>将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
)}
</Form.Item >
{

View File

@ -51,9 +51,7 @@ class Index extends Component {
<div className="grid-item">
<div className="setInputAddon">
<Input
addonBefore={`/${
projectDetail && projectDetail.identifier
}${urlroot}/`}
addonBefore={`/${ projectDetail && projectDetail.identifier }${urlroot}/`}
value={filename}
onChange={this.changeFileName}
placeholder="命名文件..."

View File

@ -54,14 +54,12 @@ class UserSubmitComponent extends Component {
const { getTopCount } = this.props;
getTopCount && getTopCount(values.branchname);
}
let url = values.branchname
? `/projects/${owner}/${projectsId}?branch=${values.branchname}`
: `/projects/${owner}/${projectsId}`;
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/branch/${values.branchname}`: (branch ? `/branch/${branch}` : "")}`;
this.props.history.push(url);
}
})
.catch((error) => {
this.setState({ isSpin: false });
this.setState({ isSpin : false });
console.log(error);
});
} else {
@ -73,7 +71,7 @@ class UserSubmitComponent extends Component {
// 确认修改文件
UpdateFile = () => {
this.setState({ isSpin: true });
const { branch, detail, content, filepath } = this.props;
const { branch, detail, content , currentBranch } = this.props;
const { projectsId , owner } = this.props.match.params;
const { submitType } = this.state;
const url = `/${owner}/${projectsId}/update_file.json`;
@ -82,7 +80,7 @@ class UserSubmitComponent extends Component {
axios
.put(url, {
filepath: detail.path,
branch: branch,
branch: submitType === "1" ? undefined : (currentBranch || branch),
new_branch: submitType === "1" ? values.branchname : undefined,
content: content,
sha: detail.sha,
@ -91,12 +89,9 @@ class UserSubmitComponent extends Component {
.then((result) => {
this.setState({ isSpin: false });
if (result.data && result.data.status === 1) {
let url = values.branchname
? `/projects/${owner}/${projectsId}?branch=${values.branchname}`
: `/projects/${owner}/${projectsId}`;
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/branch/${values.branchname}` : ((currentBranch || branch) ? `/branch/${currentBranch || branch}`:""))}`;
this.props.history.push(url);
this.props.showNotification("修改成功!");
this.props.showNotification("文件修改成功!");
}
})
.catch((error) => {
@ -115,7 +110,7 @@ class UserSubmitComponent extends Component {
const { branch, projectsId , owner } = this.props.match.params;
const { current_user, filepath, projectDetail } = this.props;
const { current_user, filepath, projectDetail , currentBranch } = this.props;
const { editor_type } = this.props;
return (
<div>
@ -175,12 +170,11 @@ class UserSubmitComponent extends Component {
>
<Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{branch}</span>
直接提交至<span className="color-orange">{currentBranch || branch}</span>
</Radio>
<Radio value="1">
<Icon type="pull-request" className="mr5" />
为此提交创建一个<span className="font-bd">新的分支</span>
并发起合并请求
为此提交创建一个<span className="font-bd">新的分支</span>
</Radio>
</Radio.Group>
{

View File

@ -1,6 +1,5 @@
import React, { Component } from "react";
import Editor from "react-monaco-editor";
import UserSubmitComponent from "./UserSubmitComponent";
import "./index.css";
@ -21,7 +20,7 @@ class m_editor extends Component {
render() {
const { editorValue } = this.state;
const { readOnly, editorType, language } = this.props;
const { readOnly, editorType, language , currentBranch } = this.props;
const editor_options = {
lineNumbers: "on",
wordWrap: true, //强制换行
@ -29,6 +28,7 @@ class m_editor extends Component {
lineHeight: 24,
renderLineHighlight: "line",
revealHorizontalRightPadding: 5,
placeholder:"请输入内容",
readOnly: readOnly,
cursorStyle: readOnly ? "underline-thin" : "line",
folding: true,
@ -46,16 +46,17 @@ class m_editor extends Component {
<div>
<div className="branchTable">
<Editor
height="600px"
height="400px"
language={language ? language : "plaintext"}
theme={"vs-grey"}
defaultValue=""
placeholder="请输入内容"
value={editorValue}
options={editor_options}
onChange={this.changeEditor}
editorWillMount={this.editorWillMount}
/>
</div>
{!readOnly && (
<UserSubmitComponent
{...this.props}
@ -63,6 +64,7 @@ class m_editor extends Component {
filepath={`${this.props.filepath}`}
content={editorValue}
editor_type={editorType}
currentBranch={currentBranch}
></UserSubmitComponent>
)}
</div>

View File

@ -53,7 +53,6 @@ class UploadFile extends Component {
{...this.props}
/>
</div>
<div>
<UserSubmitComponent
{...this.props}

View File

@ -182,7 +182,7 @@ class Detail extends Component {
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments imageLayerParent" value={v} />;
return <RenderHtml className="break_word_comments imageLayerParent" value={v} url={this.props.history.location} />;
};
render() {
@ -309,8 +309,10 @@ class Detail extends Component {
<div className="list-left list-left-padding">
<div className="list-right-item-padding background-f boder-4">
<p className="grid-item-left pb15">
<span className="issue_detail_info">分支:</span>
<span>{data && data.branch_name ? data.branch_name : "--"}</span>
<span className="issue_detail_info">负责人:</span>
<span>
{data && data.assign_user_name ? data.assign_user_name : "--"}
</span>
</p>
<p className="grid-item-left pb15">
<span className="issue_detail_info">标签:</span>
@ -344,12 +346,6 @@ class Detail extends Component {
<span className="issue_detail_info">分类:</span>
<span>{data && data.tracker ? data.tracker : "--"}</span>
</p>
<p className="grid-item-left pb15">
<span className="issue_detail_info">负责人:</span>
<span>
{data && data.assign_user_name ? data.assign_user_name : "--"}
</span>
</p>
<p className="grid-item-left pb15">
<span className="issue_detail_info">开始日期:</span>
<span>{data && data.start_date ? data.start_date : "--"}</span>
@ -363,6 +359,10 @@ class Detail extends Component {
<span className="issue_detail_info">完成度:</span>
<span>{data && data.done_ratio ? data.done_ratio : "--"}</span>
</p>
<p className="grid-item-left pb15">
<span className="issue_detail_info">分支:</span>
<span>{data && data.branch_name ? data.branch_name : "--"}</span>
</p>
</div>
</div>
</div>

View File

@ -251,7 +251,7 @@ class Milepost extends Component {
})
}
</div>
: <NoneData _html="暂时还没有相关数据!" />
: <NoneData _html="暂时还没有相关数据!" />
}
{
data && data.versions_count > limit ?

View File

@ -271,7 +271,7 @@ class MilepostDetail extends Component {
<div className="setItemStyle">
{
search_count === 0 ?
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
:
issues && issues.length>0 && issues.map((item,key)=>{
return(

View File

@ -1,9 +1,7 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Popconfirm, Tag } from 'antd'
import { Popconfirm } from 'antd'
import { TagInfo } from '../Utils/TagColor';
class OrderItem extends Component {
constructor(props) {
super(props);
@ -54,7 +52,7 @@ class OrderItem extends Component {
{current_user && current_user.login && checkbox}
<div className="flex-1">
<p className="mb10 df" style={{alignItems:"center"}}>
<Link to={`/projects/${owner}/${projectsId}/issues/${item.id}/detail`} target="_blank" title={item.name} className="hide-1 font-16 color-grey-3 lineh-30 mr10" style={{maxWidth:"300px"}}>{item.name}</Link>
<Link to={`/projects/${owner}/${projectsId}/issues/${item.id}/detail`} target="_blank" title={item.name} className="hide-1 font-16 color-grey-3 lineh-30 mr10" style={{maxWidth:"370px"}}>{item.name}</Link>
{TagInfo(item.priority,"mr10")}
</p>
<p className="color-grey-6 font-12">

View File

@ -362,7 +362,7 @@ class Tags extends Component {
</div>
</div>
:
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
}
{
data && data.issue_tags_count > limit ?

View File

@ -4,6 +4,12 @@
padding-left: 20px;
box-sizing: border-box;
}
.attachment-list-div:hover {
background-color: #e6f7ff;
}
.attachment-list-div:hover .attachment-list-delete {
display: block !important;
}
.searchBanner{
display: flex;

View File

@ -52,12 +52,9 @@ class NewMilepost extends Component {
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/milestones.json`;
let time = undefined;
if (this.state.selectedValue === undefined) {
} else {
time = this.state.selectedValue.format("YYYY-MM-DD")
if (this.state.selectedValue) {
time = this.state.selectedValue.format("YYYY-MM-DD");
}
axios.post(url, {
...values,
project_id: projectsId,
@ -68,10 +65,8 @@ class NewMilepost extends Component {
this.setState({ isSpin: false })
this.props.history.push(`/projects/${owner}/${projectsId}/milestones`);
}
}).catch(error => {
this.setState({ isSpin: false })
console.log(error);
})
}else{
this.setState({ isSpin: false })
@ -105,7 +100,7 @@ class NewMilepost extends Component {
required: true, message: '请输入标题'
}],
})(
<Input placeholder="标题" />
<Input placeholder="标题" autoComplete="off"/>
)}
</Form.Item>
</div>

View File

@ -187,6 +187,9 @@
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
.topWrapper_select.wrapperStyle li{
width:90px;
}
.topWrapper_select li {
text-align: center;
cursor: pointer;
@ -222,7 +225,7 @@
flex-wrap: wrap;
align-content: center;
border-bottom: 1px solid #eee;
padding: 16px 20px;
padding: 16px 0px 16px 20px;
}
.issueNo {
padding: 0px 5px;
@ -383,7 +386,7 @@
}
/* 任务标签列表 */
.tagList > div {
border-bottom: 1px dashed #f4f4f4;
border-bottom: 1px dashed #efefef;
display: flex;
justify-content: space-around;
padding: 15px 0px;
@ -561,12 +564,6 @@ a.issue-type-button.active:hover {
.attachment-list-delete {
display: none;
}
.attachment-list-div:hover {
background-color: #e6f7ff;
}
.attachment-list-div:hover .attachment-list-delete {
display: block !important;
}
.attachment-list-a {
color: rgba(0, 0, 0, 0.65) !important;
}

View File

@ -212,7 +212,10 @@ class order extends Component {
<Menu.Item
key={item.id}
onClick={(e) => this.getOption(e, id, item.name, toGet)}
style={{textAlign:item.color ? "left" :"center",padding:"6px 15px"}}
>
{/* 标签前面的颜色tag */}
{item.color && <span className="tagColor" style={{backgroundColor:`${item.color}`}}></span>}
{item.name}
</Menu.Item>
);
@ -239,6 +242,8 @@ class order extends Component {
this.setState({
search: value,
isSpin: true,
checkedValue:[],
all:undefined
});
const { status_type } = this.state;
@ -258,7 +263,10 @@ class order extends Component {
assigned_to_ids: "负责人",
status_ids: "状态",
done_ratios: "完成度",
fixed_version_ids:"里程碑",
paix: "排序",
checkedValue:[],
all:undefined
});
this.state.select_params = {
search: undefined,
@ -324,19 +332,19 @@ class order extends Component {
id: id,
},
})
.then((result) => {
if (result) {
const { status_type } = this.state;
.then((result) => {
if (result) {
const { status_type } = this.state;
this.getIssueList(status_type);
}
})
.catch((error) => {
console.log(error);
});
this.getIssueList(status_type);
}
})
.catch((error) => {
console.log(error);
});
};
islogin() {
islogin=()=>{
this.props.showLoginDialog();
}
renderNew =()=>{
@ -349,9 +357,7 @@ class order extends Component {
)
}else{
return(
<a className="topWrapper_btn ml10" onClick={this.islogin}>
+&nbsp;创建任务
</a>
<a className="topWrapper_btn ml10" onClick={this.islogin}>+&nbsp;创建任务</a>
)
}
}
@ -471,7 +477,7 @@ class order extends Component {
})
const { checkedValue } = this.state;
const { projectsId , owner } = this.props.match.params;
const url = `/projects/${owner}/${projectsId}/issues/clean.json`;
const url = `/${owner}/${projectsId}/issues/clean.json`;
axios.post(url, {
ids: checkedValue
}).then(result => {
@ -608,7 +614,7 @@ class order extends Component {
</div>
{
checkedValue && checkedValue.length > 0 ?
<ul className="topWrapper_select">
<ul className="topWrapper_select wrapperStyle">
<li className="mr20">
<Dropdown
className="topWrapperSelect"
@ -628,7 +634,7 @@ class order extends Component {
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
className="topWrapperSelect wrapperStyle"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_version,
"更换里程碑",
@ -645,7 +651,7 @@ class order extends Component {
</li>
<li className="mr20">
<Dropdown
className="topWrapperSelect"
className="topWrapperSelect wrapperStyle"
overlay={this.renderMenu(
issue_chosen && issue_chosen.issue_status,
"修改状态",
@ -802,7 +808,7 @@ class order extends Component {
</div>
{search_count === 0 ? (
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
) : (
<div style={{ minHeight: "500px" }}>
<Checkbox.Group name="issues" onChange={this.checkIssues} value={checkedValue} style={{ width: "100%" }}>

View File

@ -34,6 +34,8 @@ class order_form extends Component {
subject: "",
get_attachments: undefined,
show_token: false,
cannot_edit: false,
issue_current_user: true
};
}
componentDidUpdate=(prevPros)=>{
@ -116,7 +118,7 @@ class order_form extends Component {
return list.map((item, key) => {
return (
<Option key={key + 1} value={String(item.id)}>
{item.name}
{item.color && <span className="tagColor" style={{backgroundColor:`${item.color}`}}></span>}{item.name}
</Option>
);
});
@ -263,6 +265,7 @@ class order_form extends Component {
});
this.setState({
done_ratio: "0",
issue_current_user: true,
});
} else if (e === "3") {
this.props.form.setFieldsValue({
@ -270,6 +273,11 @@ class order_form extends Component {
});
this.setState({
done_ratio: "100",
issue_current_user: true,
});
}else if (e === "5") {
this.setState({
issue_current_user: false,
});
}
};
@ -371,19 +379,13 @@ class order_form extends Component {
</div>
<div className="list-left list-left-padding issue-edit-form-right">
<div className="pd20 background-f issue-form-right">
<Form.Item>
{getFieldDecorator("branch_name", {
rules: []
})(
<Form.Item label="指派成员">
{getFieldDecorator("assigned_to_id", {rules: []})(
<Select>
<Option value={""}>分支未指定</Option>
{branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
<Option value={""}>未指派成员</Option>
{this.renderSelect(
issue_chosen && issue_chosen.assign_user
)}
</Select>
)}
</Form.Item>
@ -452,16 +454,6 @@ class order_form extends Component {
)}
</Form.Item>
<Form.Item label="指派成员">
{getFieldDecorator("assigned_to_id", {rules: []})(
<Select>
<Option value={""}>未指派成员</Option>
{this.renderSelect(
issue_chosen && issue_chosen.assign_user
)}
</Select>
)}
</Form.Item>
<Form.Item label="开始日期">
<DatePicker
value={start_date ? moment(start_date, "YYYY-MM-DD") : null}
@ -485,28 +477,22 @@ class order_form extends Component {
</Select>
)}
</Form.Item>
{/* <Form.Item label="">
<Switch
checkedChildren="是"
unCheckedChildren="否"
defaultChecked={false}
checked={issue_type && issue_type === "2"}
onChange={this.change_issue_type}
/>
<Form.Item label="指定分支">
{getFieldDecorator("branch_name", {
rules: []
})(
<Select>
<Option value={""}>分支未指定</Option>
{branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
)}
</Form.Item>
{(show_token || (issue_type && issue_type === "2")) && (
<Form.Item label="token">
{getFieldDecorator("token", {
rules: [
{
required: true,
message: "请填写token值",
},
],
initialValue: token,
})(<Input placeholder="请填写token值" />)}
</Form.Item>
)} */}
</div>
</div>
</Form>

View File

@ -1,8 +1,11 @@
import React , { useState } from 'react';
import React , { useEffect, useState } from 'react';
import SelectBranch from '../Branch/Select';
import Title from '../Component/Title';
import styled from 'styled-components';
import { Blueline , FlexAJ , NumUl , GreenUnder , AlignCenter , WhiteBack } from '../Component/layout';
import { AlignCenter , WhiteBack , FlexAJ } from '../Component/layout';
import axios from 'axios';
import { Button, Select , Pagination } from 'antd';
import { getBranch } from '../GetData/getData';
const Div = styled.div`{
padding:20px 30px;
@ -10,19 +13,92 @@ const Div = styled.div`{
}`
export default ((props)=>{
const LIMIT = 15;
const [ branch , setBranch ] = useState("master");
const [ branchList , setBranchList ] = useState(undefined);
const [ protectBranch , setProtectBranch ] = useState("master");
const [ protectBranchList , setProtectBranchList ] = useState(undefined);
const [ count , setCount ] = useState(0);
const [ page , setPage ] = useState(1);
let defaultBranch = props.defaultBranch;
useEffect(()=>{
if(defaultBranch){
setBranch(defaultBranch);
setProtectBranch(defaultBranch);
}
},[defaultBranch]);
const { projectsId , owner } = props.match.params;
const projectDetail = props.projectDetail;
function resetSetting(){
useEffect(()=>{
if(defaultBranch){
setBranch(defaultBranch);
}
},[defaultBranch]);
useEffect(()=>{
if(owner){
getBranchs(projectsId,owner);
getProtectBranchList(owner,projectsId);
}
},[owner])
// 获取已经设置过分支保护的分支列表
function getProtectBranchList(owner,repo){
const url = `/${owner}/${repo}/protected_branches.json`;
axios.get(url,{
params:{
page,limit:LIMIT
}
}).then(result=>{
if(result){
setCount(result.data.total_count);
setProtectBranchList(result.data.protected_branches);
}
}).catch(error=>{})
}
// 获取分支列表(下拉、过滤掉已经设置过分支保护的分支)
async function getBranchs(id,owner){
let re = await getBranch(id,owner);
setBranchList(re);
}
// 设为默认分支
function resetSetting(){
const url = `/${owner}/${projectsId}.json`;
axios.put(url, {
default_branch:branch
})
.then((result) => {
if (result) {
props.showNotification(`分支设置成功!`);
}
})
.catch((error) => {
console.log(error);
});
}
// 跳转
function settingRule(protectBranch){
props.history.push(`/projects/${owner}/${projectsId}/setting/branch/${protectBranch}`);
}
// 翻页
function changePageNum(page){
setPage(page);
}
return(
<WhiteBack>
<Title>分支设置</Title>
<Div>
<div className="pb20" style={{borderBottom:"1px solid #eee"}}>
<p className="color-grey-3 mb10">默认分支</p>
<div className="pb20" style={{borderBottom:"1px dashed #eee"}}>
<p className="color-grey-3 mb10 font-18">默认分支</p>
<p className="mb10">默认分支被视作为代码库中的基本分支是所有克隆代码提交合并请求的目标分支</p>
<AlignCenter>
<SelectBranch
@ -31,20 +107,49 @@ export default ((props)=>{
projectsId={projectsId}
changeBranch={setBranch}
owner={owner}
history={props.history}
branchList = {branchList}
tagflag={false}
/>
<a className="color-blue ml20" onClick={resetSetting()}>设为默认分支</a>
<a className="color-blue ml20" onClick={()=>resetSetting()}>设为默认分支</a>
</AlignCenter>
</div>
<div>
<FlexAJ className="pt20">
<span className="color-grey-3">保护分支规则</span>
<Blueline>+&nbsp;新建规则</Blueline>
</FlexAJ>
<NumUl>
<li>限制分支的推送合并强制推送相关请去<GreenUnder>仓库设置</GreenUnder></li>
<li>一个分支同时只能有一个保护分支规则生效越早创建的规则优先级越高</li>
<li>保护分支规则只影响状态是保护分支的分支常规分支只读分支都不影响</li>
</NumUl>
<div className="mt10">
<p className="color-grey-3 mb10 font-18">分支保护</p>
<AlignCenter>
<SelectBranch
branch={protectBranch}
repo_id={ projectDetail && projectDetail.repo_id}
projectsId={projectsId}
changeBranch={setProtectBranch}
owner={owner}
history={props.history}
branchList = {branchList}
tagflag={false}
/>
<a className={ protectBranchList && protectBranchList.length > 0?"color-blue ml20":"color-grey ml20"} onClick={()=>settingRule(protectBranch)}>设置分支保护</a>
</AlignCenter>
{
protectBranchList && protectBranchList.length > 0 &&
<div className="protectBranchList">
{
protectBranchList.map((item,key)=>{
return(
<FlexAJ>
<span>{item.branch_name}</span>
<Button onClick={()=>settingRule(item.branch_name)}>编辑</Button>
</FlexAJ>
)
})
}
</div>
}
{
count > LIMIT &&
<div className="mt15 mb20" style={{textAlign:"center"}}>
<Pagination simple current={page} pageSize={LIMIT} total={count} onChange={changePageNum}></Pagination>
</div>
}
</div>
</Div>
</WhiteBack>

View File

@ -1,60 +1,305 @@
import React , { forwardRef , useCallback } from 'react';
import { Form , Input , Select , Button } from 'antd';
import Title from '../Component/Title';
import { WhiteBack , Cancel } from '../Component/layout';
import styled from 'styled-components';
import React, { forwardRef, useCallback, useState, useEffect } from "react";
import { Form, InputNumber , Select, Button , Checkbox , Radio } from "antd";
import Title from "../Component/Title";
import { Cancel } from "../Component/layout";
import axios from "axios";
const {Option} = Select;
const Div = styled.div`{
padding:20px 30px;
}`
export default Form.create()(
forwardRef(( { form })=>{
const { getFieldDecorator } = form;
forwardRef(({ form, match, history , showNotification }) => {
const [ protect , setProtect ] = useState(false);
const [ protects , setProtects ] = useState(false);
const [ mergeOptions , setMergeOptions ] = useState(undefined);
const [ approveOptions , setApproveOptions ] = useState(undefined);
const [ options , setOptions ] = useState(undefined);
const [ list, setList ] = useState(undefined);
const { projectsId, owner , branch } = match.params;
const { getFieldDecorator, validateFields , setFieldsValue , getFieldsValue } = form;
useEffect(() => {
const url = `/${owner}/${projectsId}/collaborators.json`;
axios.get(url).then((result) => {
setList(result.data.members);
})
.catch((error) => {});
}, []);
useEffect(()=>{
if(branch){
//
getGuardDetail(owner,projectsId,branch);
}
},[]);
function getGuardDetail(owner,projectsId,branch){
const url = `/${owner}/${projectsId}/protected_branches/${branch}/edit.json`;
axios.get(url).then((result)=>{
if(result){
setProtect(result.data.protected);
setProtects(result.data.protected);
let protected_branch = result.data.protected_branch;
if(protected_branch){
let enable_push = protected_branch.enable_push_whitelist ? 2 : protected_branch.enable_push ? 1 : 0;
setFieldsValue({
...protected_branch,
enable_push
})
setOptions(enable_push);
setMergeOptions(protected_branch.enable_merge_whitelist);
setApproveOptions(protected_branch.enable_approvals_whitelist);
console.log("111",getFieldsValue("enable_status_check"));
}
}
}).catch(error=>{});
}
function saveBranchRule() {
validateFields((error, values) => {
if (!error) {
let url = "";
if(protects){
// true
url = `/${owner}/${projectsId}/protected_branches/${branch}.json`;
}else{
//
url = `/${owner}/${projectsId}/protected_branches.json`;
}
axios({
method:!protects ? "post" : (protect ? "patch" : "delete"),
url,
params:
{
branch_name:branch,
enable_push:values.enable_push !== 0 ?false : true,
enable_push_whitelist:values.enable_push === 2 ? true : false,
...values
}
}).then(result=>{
if(result){
showNotification("保存成功!");
}
}).catch(error=>{})
}
});
}
const helper = useCallback(
(label, name, rules, widget , className , isRequired ) => (
(label, name, rules, widget, className, isRequired,flag) => (
<div className={className}>
<span className={isRequired?"required":""}>{label}</span>
<span className={isRequired ? "required" : ""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
{getFieldDecorator(name, { rules, validateFirst: true , valuePropName:flag ? "checked":"value" })(widget)}
</Form.Item>
</div>
),
[]
);
return(
<WhiteBack>
<Title>新建保护分支规则</Title>
<Div>
//
function changeProtect(e){
setProtect(e.target.checked);
}
// 线
function changeProtectOption(e){
setOptions(e.target.value);
}
//
function changeMergeOption(e){
setMergeOptions(e.target.checked);
}
//
function changeWhitelistUsernameOption(e){
setApproveOptions(e.target.checked);
}
return (
<div style={{backgroundColor:"#fff"}}>
<Title>新建'{branch}'保护分支规则</Title>
<Form>
<div style={{padding:"20px 30px"}}>
{helper(
"设置分支/通配符",
"sign",
[{ required: true, message: "请输入分支/通配符" }],
<Input placeholder="请输入分支名称或通配符规则" />,'setStyleRule'
)}
<p className="color-grey-8 mb20">例如设置为master则对名称为master的分支生效设置为*-stable release*则对名称符合此通配符的所有保护分支生效</p>
{helper(
"可推送代码成员",
"psuhmember",
"",
"branchProtect",
[],
<Select placeholder="请选择仓库成员" >
<Option value="0">请选择仓库成员</Option>
</Select>,'setSelectWidth'
<Checkbox checked={protect} onChange={changeProtect}>
启用分支保护<span className="color-grey-9 ml5 font-12">组织删除并限制Git推送和合并到分支</span>
</Checkbox>,
"setStyleRule"
)}
{helper(
"可合并Pull Request成员",
"pullmember",
[],
<Select placeholder="请选择仓库成员" >
<Option value="0">请选择仓库成员</Option>
</Select>,'setSelectWidth'
)}
<div className="df pb30">
<Button type="primary">保存</Button>
<Cancel className="ml30">取消</Cancel>
<div className="pl25 shortStyle">
{helper(
"",
"enable_push",
[],
<Radio.Group disabled={!protect} onChange={changeProtectOption}>
<Radio className="columsRadio" value={0}>
禁用推送<span className="color-grey-9 ml5 font-12">此分支不允许推送</span>
</Radio>
<Radio className="columsRadio" value={1}>
启用推送<span className="color-grey-9 ml5 font-12">任何拥有写访问权限的人将被允许推送到此分支(但不能强行推送)</span>
</Radio>
<Radio className="columsRadio" value={2}>
启用推送白名单<span className="color-grey-9 ml5 font-12">只有列入白名单的用户或团队才能被允许推送到此分支(但不能强行推送)</span>
</Radio>
</Radio.Group>,
""
)}
<div className="pl25 pt5 pb5 mb15">
{helper(
"",
"push_whitelist_usernames",
[],
<Select
mode="multiple"
placeholder="搜索用户"
style={{ width: '100%' }}
disabled={!protect || (options ===undefined || options !== 2)}
>
{list && list.map(item => (
<Select.Option key={item.id} value={item.login}>
{item.name}
</Select.Option>
))}
</Select>,
"setStyleRule"
)}
</div>
{helper(
"",
"enable_merge_whitelist",
[],
<Checkbox disabled={!protect} checked={mergeOptions} onChange={changeMergeOption}>
启用合并白名单<span className="color-grey-9 ml5 font-12">仅允许白名单用户或团队合并合并请求到此分支</span>
</Checkbox>,
"setStyleRule"
)}
<div className="pl25 pt5 pb5">
{helper(
"",
"merge_whitelist_usernames",
[],
<Select
mode="multiple"
placeholder="搜索用户"
style={{ width: '100%' }}
disabled={!protect || !mergeOptions}
>
{list && list.map(item => (
<Select.Option key={item.id} value={item.login}>
{item.name}
</Select.Option>
))}
</Select>,
"setStyleRule"
)}
</div>
{helper(
"",
"enable_status_check",
[],
<Checkbox disabled={!protect}>
启用状态检查
</Checkbox>,
"setStyleRule",false,true
)}
<div style={{display:"flex",alignItems:"center"}}>
{helper(
"所需的批准数",
"required_approvals",
[],
<InputNumber min={0} style={{width:"140px"}}/>,
"inlineFlex"
)}
<span className="color-grey-9 ml5 font-12">只允许合并有足够审核人数的拉取请求</span>
</div>
{helper(
"",
"enable_approvals_whitelist",
[],
<Checkbox name="enable_approvals_whitelist" disabled={!protect} checked={approveOptions} onChange={changeWhitelistUsernameOption}>
批准仅限列入白名单的用户或团队<span className="color-grey-9 ml5 font-12">只有白名单用户或团队的审核才能计数 没有批准的白名单,任何有写访问权限的人的审核都将计数</span>
</Checkbox>,
"setStyleRule"
)}
<div className="pl25 pt5 pb5 mb15">
{helper(
"",
"approvals_whitelist_usernames",
[],
<Select
mode="multiple"
placeholder="搜索用户"
style={{ width: '100%' }}
disabled={!protect || !approveOptions}
>
{list && list.map(item => (
<Select.Option key={item.id} value={item.login}>
{item.name}
</Select.Option>
))}
</Select>,
"setStyleRule"
)}
</div>
{helper(
"",
"block_on_rejected_reviews",
[],
<Checkbox disabled={!protect} name="block_on_rejected_reviews">
拒绝审核阻止了合并<span className="color-grey-9 ml5 font-12">如果官方审查人员要求作出改动即使有足够的批准合并也不允许</span>
</Checkbox>,
"setStyleRule",false,true
)}
{helper(
"",
"dismiss_stale_approvals",
[],
<Checkbox disabled={!protect} name="dismiss_stale_approvals">
取消过时的批准<span className="color-grey-9 ml5 font-12">当新的提交更改合并请求内容被推送到分支时旧的批准将被撤销</span>
</Checkbox>,
"setStyleRule",false,true
)}
{helper(
"",
"require_signed_commits",
[],
<Checkbox disabled={!protect} name="require_signed_commits">
需要签名提交
</Checkbox>,
"setStyleRule",false,true
)}
{helper(
"",
"block_on_outdated_branch",
[],
<Checkbox disabled={!protect} name="block_on_outdated_branch">
如果拉取请求已经过时阻止合并<span className="color-grey-9 ml5 font-12">当头部分支落后基础分支时不能合并</span>
</Checkbox>,
"setStyleRule",false,true
)}
</div>
</Div>
</WhiteBack>
)
<div className="df pb30 pt20">
<Button type="primary" onClick={saveBranchRule}>
保存
</Button>
<Cancel
className="ml30"
onClick={() => {
history.push(`/projects/${owner}/${projectsId}/setting/branch`);
}}
>
取消
</Cancel>
</div>
</div>
</Form>
</div>
);
})
)
);

View File

@ -290,8 +290,10 @@ class Collaborator extends Component {
return "text-green";
} else if (role === "Developer") {
return "text-primary";
} else {
} else if(role === "Reporter"){
return "text-yellow";
}else{
return "text-gray";
}
};
const member_roles = (item) => {
@ -302,7 +304,11 @@ class Collaborator extends Component {
<label className={get_color(item.role)}>
{operation && operation[0].name}
</label>
) : (
) :
item.is_apply_signature ?
<label className="text-grey">外围贡献者</label>
:
(
<Dropdown overlay={setRoles(`${item.id}`)} placement={"bottomCenter"}>
<span className={get_color(item.role)}>
{operation && operation[0].name}
@ -360,6 +366,11 @@ class Collaborator extends Component {
dataIndex: "email",
render: (text) => <span>{text}</span>,
},
{
title: "Token值",
dataIndex: "token",
render: (text) => <span>{text}</span>,
},
{
title: roleTitle,
dataIndex: "role_name",
@ -493,7 +504,7 @@ class Collaborator extends Component {
rowKey={(record) => record.id}
></Table>
) : (
<NoneData _html="暂时还没有相关数据!" />
<NoneData _html="暂时还没有相关数据!" />
)}
</div>
</Spin>

View File

@ -28,6 +28,10 @@ const Tags = Loadable({
loader: () => import("./new_tags"),
loading: Loading,
});
const Special = Loadable({
loader: () => import("./SpecialProject"),
loading: Loading,
});
const Manage = Loadable({
loader: () => import("./ManageWeb"),
loading: Loading,
@ -40,11 +44,12 @@ class Index extends Component {
render() {
const { projectsId , owner } = this.props.match.params;
const { pathname } = this.props.history.location;
const { projectDetail } = this.props;
const flag = pathname === `/projects/${owner}/${projectsId}/setting`;
return (
<Box className="ProjectListIndex">
<Short>
<div className="ProjectListIndex">
<div style={{width:"28%",borderRadius:"5px",marginBottom:"30%"}}>
<ul className="list-l-Menu">
<li className={flag ? "active" : ""}>
<p>
@ -65,18 +70,18 @@ class Index extends Component {
</Link>
</p>
</li>
{/* <li
<li
className={
pathname.indexOf("setting/branch") > -1 ? "active" : ""
}
>
<p>
<Link to={`/projects/${projectsId}/setting/branch`} className="w-100">
<Link to={`/projects/${owner}/${projectsId}/setting/branch`} className="w-100">
<i className="iconfont icon-fenzhi font-20 mr10"></i>
分支设置
</Link>
</p>
</li> */}
</li>
<li
className={pathname.indexOf("setting/tags") > -1 ? "active" : ""}
>
@ -87,6 +92,20 @@ class Index extends Component {
</Link>
</p>
</li>
{
projectDetail && projectDetail.permission && (projectDetail.permission === "Owner" || projectDetail.permission === "Admin") ?
<li
className={pathname.indexOf("setting/special") > -1 ? "active" : ""}
>
<p>
<Link to={`/projects/${owner}/${projectsId}/setting/special`} className="w-100">
<i className="iconfont icon-jingyan font-18 mr10"></i>
特殊开源许可证项目管理
</Link>
</p>
</li>
:""
}
{/* <li
className={
@ -101,9 +120,9 @@ class Index extends Component {
</p>
</li> */}
</ul>
</Short>
<Long>
<Gap>
</div>
<div style={{width:"72%",borderRadius:"5px",marginBottom:"30px"}}>
<div style={{paddingLeft:"20px",boxSizing:"border-box"}}>
<Switch {...this.props}>
{/* 协作者 */}
<Route
@ -112,7 +131,15 @@ class Index extends Component {
<Collaborator {...this.props} {...props} {...this.state} />
)}
></Route>
<Route
path="/projects/:owner/:projectsId/setting/special"
render={(props) => (
<Special {...this.props} {...props} {...this.state} />
)}
></Route>
{/* 修改仓库信息 */}
<Route
path="/projects/:owner/:projectsId/setting/tags"
render={(props) => (
@ -120,7 +147,7 @@ class Index extends Component {
)}
></Route>
<Route
path="/projects/:owner/:projectsId/setting/branch/new"
path="/projects/:owner/:projectsId/setting/branch/:branch"
render={(props) => (
<BranchNew {...this.props} {...props} {...this.state} />
)}
@ -128,7 +155,7 @@ class Index extends Component {
<Route
path="/projects/:owner/:projectsId/setting/branch"
render={(props) => (
<Branch {...this.props} {...props} {...this.state} />
<Branch {...this.props} {...props } {...this.state} />
)}
></Route>
<Route
@ -151,9 +178,9 @@ class Index extends Component {
)}
></Route>
</Switch>
</Gap>
</Long>
</Box>
</div>
</div>
</div>
);
}
}

View File

@ -15,11 +15,11 @@ class Setting extends Component {
CategoryList: undefined,
LanguageList: undefined,
private_check: undefined,
is_secret:false
};
}
componentDidUpdate=(prevPros)=>{
console.log("dddd",this.props.checkIfLogin());
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
@ -53,10 +53,11 @@ class Setting extends Component {
.then((result) => {
if (result) {
this.props.form.setFieldsValue({
...result.data,
...result.data
});
this.setState({
private_check: result.data.private,
is_secret:result.data.is_secret
});
}
})
@ -145,7 +146,6 @@ class Setting extends Component {
});
};
changePrivate = (e) => {
console.log(e);
this.setState({
private_check: e.target.checked,
});
@ -154,10 +154,10 @@ class Setting extends Component {
render() {
const { getFieldDecorator } = this.props.form;
const { CategoryList, LanguageList, private_check } = this.state;
const { CategoryList, LanguageList, private_check , is_secret } = this.state;
return (
<div>
<WhiteBack>
<WhiteBack style={{paddingBottom:"20px"}}>
<Title>基本设置</Title>
<Form className="baseForm">
<Form.Item label="项目名称">
@ -179,6 +179,7 @@ class Setting extends Component {
<Checkbox
checked={private_check}
onChange={this.changePrivate}
disabled={is_secret}
>
将仓库设为私有
</Checkbox>

View File

@ -0,0 +1,186 @@
import React , { useEffect , useState} from 'react';
import { Input , Table , Pagination, Button , Dropdown , Menu } from 'antd';
import { Banner , WhiteBack , AlignCenterBetween } from '../Component/layout';
import axios from 'axios';
const { Search } = Input;
const LIMIT = 15;
function SpecialProject(props){
const [ page , setPage] = useState(1);
const [ searchValue , SetSearchValue ] = useState(undefined);
const [ total , setTotal ] = useState(0);
const [ list , setList ] = useState(undefined);
const [ status , setStatus ] = useState(undefined);
const [ loading ,setLoading ] = useState(true);
const { owner , projectsId} = props.match.params;
const { project_id } = props;
useEffect(()=>{
if(project_id){
setLoading(true);
Init(searchValue, status);
}
},[page,project_id]);
function Init(search,status){
const url = `/apply_signatures.json`;
axios.get(url,{
params:{
project_id,
page,limit:LIMIT,search,status
}
}).then(result=>{
setLoading(false);
if(result){
setList(result.data.apply_signatures);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
function changePage(page){
setLoading(true);
setPage(page);
}
const column = [
{
dataIndex:"column",
key:1,
width:"12%",
title:"序号",
render:(txt,item,index)=>{
return `${index+1}`
}
},
{
dataIndex:"name",
key:2,
title:"申请人",
render:(text,item,m)=>{
return item.user && <span className="task-hide" style={{maxWidth:"139px",display:"block"}}>{item.user.name}</span>
}
},
{
dataIndex:"email",
key:2,
title:"邮箱",
width:"22%",
render:(text,item,m)=>{
return item.user && <span>{item.user.email}</span>
}
},
{
dataIndex:"attachment",
key:3,
title:"附件",
width:"28%",
render:(text,item,m)=>{
return item.attachment && <a className="task-hide" style={{maxWidth:"173px",display:"block"}} href={`${item.attachment.path}`}>{item.attachment.filename}</a>
}
},
{
dataIndex:"operation",
key:4,
width:"18%",
title:"操作",
render:(text, item) =>{
return(
<React.Fragment>
{
item.status === "waiting" &&
<span>
<Button size="small" onClick={()=>operation(item.id,"unpassed")}>拒绝</Button>
<Button size="small" onClick={()=>operation(item.id,"passed")} type={"primary"} className="ml20">同意</Button>
</span>
}
{
item.status === "unpassed" &&
<span style={{color:"#ff041c"}}>已拒绝</span>
}
{
item.status === "passed" &&
<span style={{color:"#13b4f1"}}>已同意</span>
}
</React.Fragment>
)
}
}
]
// &
function operation(ids,s){
setLoading(true);
const url = `/apply_signatures/${ids}.json`;
axios.put(url,{
project_id:project_id,
status:s
}).then(result=>{
setLoading(false);
if(result){
props.showNotification(`${s==="passed"?"同意":"拒绝"}此申请已操作成功!`);
Init(searchValue,status);
}
}).catch(error=>{setLoading(false)})
}
function searchList(){
setLoading(true);
Init(searchValue,status);
}
const menu=(
<Menu onClick={chooseStatus}>
<Menu.Item key="all">全部</Menu.Item>
<Menu.Item key="waiting">审核中</Menu.Item>
<Menu.Item key="unpassed">已拒绝</Menu.Item>
<Menu.Item key="passed">已同意</Menu.Item>
</Menu>
)
function chooseStatus(e){
setStatus(e.key);
Init(searchValue, e.key);
}
return(
<WhiteBack style={{minHeight:"500px"}}>
<Banner>项目管理</Banner>
<AlignCenterBetween style={{padding:"10px 20px",textAlign:"right"}}>
<Search
placeholder="请输入用户姓名或者邮箱搜索"
allowClear
enterButton="搜索"
style={{width:400}}
size="middle"
value={searchValue}
onChange={(e)=>SetSearchValue(e.target.value)}
onSearch={searchList}
/>
<Dropdown overlay={menu} placement="bottomRight">
<span>
<span style={{color:status ? "color-blue" : "color-grey-3"}}>{status ==="waiting"?"审核中":status==="unpassed"?"已拒绝":status==="passed"?"已同意":"全部"}</span>
<i className="iconfont icon-xiajiantou color-grey-9 font-14 ml8"></i>
</span>
</Dropdown>
</AlignCenterBetween>
<Table
columns={column}
rowKey={(record) => record.id}
pagination={false}
dataSource={list}
loading={loading}
></Table>
{
total > LIMIT &&
<div className="center mt20 mb20">
<Pagination simple current={page} total={total} pageSize={LIMIT} onChange={changePage}></Pagination>
</div>
}
</WhiteBack>
)
}
export default SpecialProject;

View File

@ -410,7 +410,7 @@ class NewTags extends Component {
</div>
);
} else {
return <NoneData _html="暂时还没有相关数据!" />;
return <NoneData _html="暂时还没有相关数据!" />;
}
};

View File

@ -139,6 +139,7 @@
.padding15-10{
padding:15px 10px;
}
.center{text-align: center;}
.w-100{width: 100%;}
.fwb{font-weight: 600;}
.text-black{color: #333;}
@ -151,6 +152,9 @@
.text-yellow{color: #FF6E21 !important;}
.text-delete{color: #BBBBBB; }
.text-delete:hover{color: #db2828; }
.text-grey{
color: #999;
}
.new-tag-div{
padding: 15px;
height: 75px;
@ -187,7 +191,29 @@
width: 100%;
}
}
.shortStyle{
.setStyleRule{
min-height: 35px;
}
.columsRadio{
display: block;
height: 30px;
line-height: 30px;
}
.ant-row.ant-form-item{
margin-bottom: 0px;
}
}
.inlineFlex{
display: flex;
align-items: center;
& > span{
margin-right: 10px;
color: #666;
}
}
.setStyleRule{
min-height: 35px;
.ant-row.ant-form-item{
margin-bottom: 10px;
}
@ -196,4 +222,22 @@
.ant-select.ant-select-enabled{
width: 100%;
}
}
.setHeight{
.ant-select-selection,.ant-select-selection__rendered{
height: 40px;
line-height: 40px;
}
}
.protectBranchList{
border:1px solid #eee;
border-radius: 5px;
margin-top: 25px;
&>div{
padding:5px 15px;
border-bottom: 1px solid #eee;
}
&>div:last-child{
border-bottom: none;
}
}

Some files were not shown because too many files have changed in this diff Show More