diff --git a/package-lock.json b/package-lock.json
index 29895360..fa7933b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -489,11 +489,21 @@
"resolved": "http://173.15.15.82:8081/repository/npm-all/@tootallnate/once/-/once-1.1.2.tgz",
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
},
+ "@transloadit/prettier-bytes": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz",
+ "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA=="
+ },
"@types/estree": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ=="
},
+ "@types/event-emitter": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.3.tgz",
+ "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q=="
+ },
"@types/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
@@ -663,6 +673,158 @@
}
}
},
+ "@uppy/companion-client": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.2.tgz",
+ "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==",
+ "requires": {
+ "@uppy/utils": "^4.1.2",
+ "namespace-emitter": "^2.0.1"
+ }
+ },
+ "@uppy/core": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz",
+ "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
+ "requires": {
+ "@transloadit/prettier-bytes": "0.0.7",
+ "@uppy/store-default": "^2.1.1",
+ "@uppy/utils": "^4.1.3",
+ "lodash.throttle": "^4.1.1",
+ "mime-match": "^1.0.2",
+ "namespace-emitter": "^2.0.1",
+ "nanoid": "^3.1.25",
+ "preact": "^10.5.13"
+ }
+ },
+ "@uppy/store-default": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmmirror.com/@uppy/store-default/-/store-default-2.1.1.tgz",
+ "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ=="
+ },
+ "@uppy/utils": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmmirror.com/@uppy/utils/-/utils-4.1.3.tgz",
+ "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==",
+ "requires": {
+ "lodash.throttle": "^4.1.1"
+ }
+ },
+ "@uppy/xhr-upload": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
+ "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
+ "requires": {
+ "@uppy/companion-client": "^2.2.2",
+ "@uppy/utils": "^4.1.2",
+ "nanoid": "^3.1.25"
+ }
+ },
+ "@wangeditor/basic-modules": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
+ "integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
+ "requires": {
+ "is-url": "^1.2.4"
+ }
+ },
+ "@wangeditor/code-highlight": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz",
+ "integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==",
+ "requires": {
+ "prismjs": "^1.23.0"
+ }
+ },
+ "@wangeditor/core": {
+ "version": "1.1.19",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz",
+ "integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
+ "requires": {
+ "@types/event-emitter": "^0.3.3",
+ "event-emitter": "^0.3.5",
+ "html-void-elements": "^2.0.0",
+ "i18next": "^20.4.0",
+ "scroll-into-view-if-needed": "^2.2.28",
+ "slate-history": "^0.66.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.22.15.tgz",
+ "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
+ "requires": {
+ "regenerator-runtime": "^0.14.0"
+ }
+ },
+ "i18next": {
+ "version": "20.6.1",
+ "resolved": "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz",
+ "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==",
+ "requires": {
+ "@babel/runtime": "^7.12.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+ }
+ }
+ },
+ "@wangeditor/editor": {
+ "version": "5.1.23",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz",
+ "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
+ "requires": {
+ "@uppy/core": "^2.1.1",
+ "@uppy/xhr-upload": "^2.0.3",
+ "@wangeditor/basic-modules": "^1.1.7",
+ "@wangeditor/code-highlight": "^1.0.3",
+ "@wangeditor/core": "^1.1.19",
+ "@wangeditor/list-module": "^1.0.5",
+ "@wangeditor/table-module": "^1.1.4",
+ "@wangeditor/upload-image-module": "^1.0.2",
+ "@wangeditor/video-module": "^1.1.4",
+ "dom7": "^3.0.0",
+ "is-hotkey": "^0.2.0",
+ "lodash.camelcase": "^4.3.0",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.debounce": "^4.0.8",
+ "lodash.foreach": "^4.5.0",
+ "lodash.isequal": "^4.5.0",
+ "lodash.throttle": "^4.1.1",
+ "lodash.toarray": "^4.4.0",
+ "nanoid": "^3.2.0",
+ "slate": "^0.72.0",
+ "snabbdom": "^3.1.0"
+ }
+ },
+ "@wangeditor/editor-for-react": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/editor-for-react/-/editor-for-react-1.0.6.tgz",
+ "integrity": "sha512-KJNSfgMr5Blzae3oyaiz20flMKHZHnvsz4bCYQKDCUs/qkvC+xNTnwedlCmhGP187oPWPEypCIYI8Zg6sz0psQ=="
+ },
+ "@wangeditor/list-module": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/list-module/-/list-module-1.0.5.tgz",
+ "integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ=="
+ },
+ "@wangeditor/table-module": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.4.tgz",
+ "integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w=="
+ },
+ "@wangeditor/upload-image-module": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz",
+ "integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA=="
+ },
+ "@wangeditor/video-module": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.4.tgz",
+ "integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg=="
+ },
"@webassemblyjs/ast": {
"version": "1.9.0",
"resolved": "http://173.15.15.82:8081/repository/npm-all/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -4065,6 +4227,11 @@
"webpack-sources": "^1.0.1"
}
},
+ "compute-scroll-into-view": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
+ "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="
+ },
"concat": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz",
@@ -4850,6 +5017,15 @@
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
"dev": true
},
+ "d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "requires": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
"d3-color": {
"version": "1.4.1",
"resolved": "http://173.15.15.82:8081/repository/npm-all/d3-color/-/d3-color-1.4.1.tgz",
@@ -5397,6 +5573,14 @@
"resolved": "http://173.15.15.82:8081/repository/npm-all/dom-walk/-/dom-walk-0.1.2.tgz",
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
},
+ "dom7": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz",
+ "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
+ "requires": {
+ "ssr-window": "^3.0.0-alpha.1"
+ }
+ },
"domain-browser": {
"version": "1.2.0",
"resolved": "http://173.15.15.82:8081/repository/npm-all/domain-browser/-/domain-browser-1.2.0.tgz",
@@ -5749,11 +5933,40 @@
"is-symbol": "^1.0.2"
}
},
+ "es5-ext": {
+ "version": "0.10.62",
+ "resolved": "https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.62.tgz",
+ "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+ "requires": {
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.3",
+ "next-tick": "^1.1.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
"es6-promise": {
"version": "4.2.8",
"resolved": "http://173.15.15.82:8081/repository/npm-all/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
+ "es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "requires": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
"escalade": {
"version": "3.1.1",
"resolved": "http://173.15.15.82:8081/repository/npm-all/escalade/-/escalade-3.1.1.tgz",
@@ -6405,6 +6618,15 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true
},
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
"eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
@@ -6566,6 +6788,21 @@
}
}
},
+ "ext": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz",
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
+ "requires": {
+ "type": "^2.7.2"
+ },
+ "dependencies": {
+ "type": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmmirror.com/type/-/type-2.7.2.tgz",
+ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
+ }
+ }
+ },
"extend": {
"version": "3.0.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/extend/-/extend-3.0.2.tgz",
@@ -8702,6 +8939,11 @@
"void-elements": "3.1.0"
}
},
+ "html-void-elements": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz",
+ "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A=="
+ },
"html-webpack-plugin": {
"version": "4.5.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz",
@@ -9755,6 +9997,11 @@
"is-extglob": "^1.0.0"
}
},
+ "is-hotkey": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz",
+ "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw=="
+ },
"is-in-browser": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
@@ -9945,6 +10192,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "is-url": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
+ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
+ },
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@@ -10946,6 +11198,16 @@
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
"dev": true
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
+ },
"lodash.cond": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz",
@@ -10975,6 +11237,11 @@
"integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==",
"dev": true
},
+ "lodash.foreach": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+ "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ=="
+ },
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@@ -11010,6 +11277,11 @@
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
+ "lodash.toarray": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+ "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw=="
+ },
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -11340,6 +11612,14 @@
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
+ "mime-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz",
+ "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
+ "requires": {
+ "wildcard": "^1.1.0"
+ }
+ },
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
@@ -11576,11 +11856,21 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
},
+ "namespace-emitter": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
+ "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g=="
+ },
"nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
+ "nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA=="
+ },
"nanomatch": {
"version": "1.2.13",
"resolved": "http://173.15.15.82:8081/repository/npm-all/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -11638,6 +11928,11 @@
"resolved": "http://173.15.15.82:8081/repository/npm-all/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
+ "next-tick": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz",
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
+ },
"nice-try": {
"version": "1.0.5",
"resolved": "http://173.15.15.82:8081/repository/npm-all/nice-try/-/nice-try-1.0.5.tgz",
@@ -13561,6 +13856,11 @@
"resolved": "http://173.15.15.82:8081/repository/npm-all/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
},
+ "preact": {
+ "version": "10.17.1",
+ "resolved": "https://registry.npmmirror.com/preact/-/preact-10.17.1.tgz",
+ "integrity": "sha512-X9BODrvQ4Ekwv9GURm9AKAGaomqXmip7NQTZgY7gcNmr7XE83adOMJvd3N42id1tMFU7ojiynRsYnY6/BRFxLA=="
+ },
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -13601,6 +13901,11 @@
"ansi-styles": "^3.0.0"
}
},
+ "prismjs": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz",
+ "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q=="
+ },
"private": {
"version": "0.1.8",
"resolved": "http://173.15.15.82:8081/repository/npm-all/private/-/private-0.1.8.tgz",
@@ -16355,7 +16660,7 @@
},
"sass-loader": {
"version": "7.3.1",
- "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-7.3.1.tgz",
+ "resolved": "http://173.15.15.82:8081/repository/npm-all/sass-loader/-/sass-loader-7.3.1.tgz",
"integrity": "sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA==",
"dev": true,
"requires": {
@@ -16521,6 +16826,14 @@
"resolved": "https://registry.npmjs.org/scroll-into-view/-/scroll-into-view-1.16.2.tgz",
"integrity": "sha512-vyTE0i27o6eldt9xinjHec41Dw05y+faoI+s2zNKJAVOdbA5M2XZrYq/obJ8E+QDQulJ2gDjgui9w9m9RZSRng=="
},
+ "scroll-into-view-if-needed": {
+ "version": "2.2.31",
+ "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
+ "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
+ "requires": {
+ "compute-scroll-into-view": "^1.0.20"
+ }
+ },
"scrollama": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/scrollama/-/scrollama-3.2.0.tgz",
@@ -17159,6 +17472,43 @@
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
},
+ "slate": {
+ "version": "0.72.8",
+ "resolved": "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz",
+ "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
+ "requires": {
+ "immer": "^9.0.6",
+ "is-plain-object": "^5.0.0",
+ "tiny-warning": "^1.0.3"
+ },
+ "dependencies": {
+ "immer": {
+ "version": "9.0.21",
+ "resolved": "https://registry.npmmirror.com/immer/-/immer-9.0.21.tgz",
+ "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
+ },
+ "is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
+ }
+ }
+ },
+ "slate-history": {
+ "version": "0.66.0",
+ "resolved": "https://registry.npmmirror.com/slate-history/-/slate-history-0.66.0.tgz",
+ "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==",
+ "requires": {
+ "is-plain-object": "^5.0.0"
+ },
+ "dependencies": {
+ "is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
+ }
+ }
+ },
"slice-ansi": {
"version": "1.0.0",
"resolved": "http://173.15.15.82:8081/repository/npm-all/slice-ansi/-/slice-ansi-1.0.0.tgz",
@@ -17181,6 +17531,11 @@
"resolved": "http://173.15.15.82:8081/repository/npm-all/slick-carousel/-/slick-carousel-1.8.1.tgz",
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA=="
},
+ "snabbdom": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.5.1.tgz",
+ "integrity": "sha512-wHMNIOjkm/YNE5EM3RCbr/+DVgPg6AqQAX1eOxO46zYNvCXjKP5Y865tqQj3EXnaMBjkxmQA5jFuDpDK/dbfiA=="
+ },
"snapdragon": {
"version": "0.8.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -17514,6 +17869,11 @@
"tweetnacl": "~0.14.0"
}
},
+ "ssr-window": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz",
+ "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA=="
+ },
"ssri": {
"version": "5.3.0",
"resolved": "http://173.15.15.82:8081/repository/npm-all/ssri/-/ssri-5.3.0.tgz",
@@ -18557,6 +18917,11 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+ },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -20760,6 +21125,11 @@
}
}
},
+ "wildcard": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz",
+ "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
+ },
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
diff --git a/package.json b/package.json
index c549382c..6f96decb 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,8 @@
"dependencies": {
"@monaco-editor/react": "^2.3.0",
"@novnc/novnc": "^1.1.0",
+ "@wangeditor/editor": "^5.1.23",
+ "@wangeditor/editor-for-react": "^1.0.6",
"actioncable": "^5.2.4-3",
"ahooks": "^2.10.14",
"antd": "^3.26.15",
diff --git a/src/common/educoder.js b/src/common/educoder.js
index 7b14824a..6575c503 100644
--- a/src/common/educoder.js
+++ b/src/common/educoder.js
@@ -7,7 +7,7 @@ export {
getImageUrl as getImageUrl,getImageUrlAbsolute as getImageUrlAbsolute,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, getZoneUrl as getZoneUrl, 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,
- turnbar,returnbar,setSeoMeta as setSeoMeta , IsPC as IsPC
+ turnbar,returnbar,setSeoMeta as setSeoMeta , IsPC as IsPC, addMeta as addMeta
} from './UrlTool';
export { setmiyah as setmiyah } from './Component';
diff --git a/src/forge/Component/RichEditor/index.jsx b/src/forge/Component/RichEditor/index.jsx
new file mode 100644
index 00000000..2a15b968
--- /dev/null
+++ b/src/forge/Component/RichEditor/index.jsx
@@ -0,0 +1,124 @@
+import React, { useState, useEffect } from 'react';
+import { Editor, Toolbar } from '@wangeditor/editor-for-react';
+import '@wangeditor/editor/dist/css/style.css';
+import cookie from 'react-cookies';
+import { message, Spin } from 'antd';
+import axios from 'axios';
+
+// 富文本编辑器
+function MyEditor(props) {
+ const {value, setValue, uploadUrl, videoUploadUrl} = props;
+ // editor 实例
+ const [editor, setEditor] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ // 模拟 ajax 请求,异步设置 html
+ useEffect(() => {
+ if(value && setValue){
+ setValue(value);
+ }
+ }, []);
+
+ // 工具栏配置
+ const toolbarConfig = {};
+ // 隐藏 代办
+ toolbarConfig.excludeKeys = [
+ 'todo'
+ ]
+
+ // 编辑器配置
+ const editorConfig = {
+ placeholder: '请输入内容...',
+ MENU_CONF:{
+ uploadImage:{
+ server: uploadUrl,
+ headers: {
+ Authorization: cookie.load('autologin_trustie')
+ },
+ withCredentials: true,
+ fieldName: "file",
+ maxFileSize: 20 * 1024 * 1024,
+ allowedFileTypes: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml", "image/bmp"],
+ customInsert(res, insertFn){
+ const {url} = res;
+ insertFn(url, "图片", url);
+ },
+ onBeforeUpload(file){
+ const {type, name} = Object.values(file)[0];
+ const typeRange = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml", "image/bmp"];
+ const suffix = name && name.split(".")[1];
+ const isType = typeRange.indexOf(type) !== -1 && suffix !== "tiff";
+ if(!isType){
+ message.error("只能上传jpg、jpeg、webp、png、svg、gif、bmp格式的图片!")
+ return false;
+ }
+ return file;
+ },
+ onError(file, err) {
+ message.error(`${file.name} 上传出错, ${err}` )
+ },
+ },
+ uploadVideo:{
+ // 自定义上传视频
+ async customUpload(file, insertFn){
+ if (!file.type.includes("video")) {
+ return message.error("请上传视频格式的文件!");
+ } else if (file.size / 1024 / 1024 > 200) {
+ return message.error("请上传200M以内的文件!");
+ }
+ const formData = new FormData();
+ formData.append("file", file);
+ setLoading(true);
+ axios.post(videoUploadUrl || uploadUrl, formData, {headers: {Authorization: cookie.load('autologin_trustie')}}).then(res=>{
+ setLoading(false);
+ if(res && res.data && res.data.code === 200){
+ insertFn(res.data.url)
+ }else{
+ message.error(res && res.data && res.data.msg)
+ }
+ })
+ }
+ }
+ }
+ };
+
+ // 及时销毁 editor ,重要!
+ useEffect(() => {
+ return () => {
+ if (editor === null) return;
+ editor.destroy();
+ setEditor(null);
+ };
+ }, [editor]);
+
+ const editorBoxClass = {
+ border: '1px solid #ccc',
+ zIndex: 100,
+ 'video': {
+ maxWidth: '100%'
+ }
+ }
+
+ return (
+
+
+
+ setValue && setValue(editor.getHtml())}
+ mode="default"
+ style={{ height: '500px', overflowY: 'hidden' }}
+ />
+
+
+ );
+}
+
+export default MyEditor;
\ No newline at end of file
diff --git a/src/forge/Information/Pages/apply.jsx b/src/forge/Information/Pages/apply.jsx
index 2d5c29d6..bbb63880 100644
--- a/src/forge/Information/Pages/apply.jsx
+++ b/src/forge/Information/Pages/apply.jsx
@@ -5,7 +5,7 @@ import { postCreateZone } from '../api';
const { TextArea } = Input;
const phonereg = /^([1][3456789])\d{9}$/
-const idenReg = /^[a-zA-Z][a-zA-Z0-9-_]{0,18}[a-zA-Z]+$/g
+const idenReg = /^[a-zA-Z][a-zA-Z0-9-_]{0,18}[a-zA-Z]$/g
function Apply(props){
const { form } = props;
const { getFieldDecorator , validateFields } = form;
@@ -39,12 +39,12 @@ function Apply(props){
}
- function checkIndentity(rule, value, callback){
- if(value && !idenReg.test(value)){
- callback("专区标识长度2-20,只能以字母开头结尾,可包含数字、下划线、中划线");
- }
- callback();
- }
+ // function checkIndentity(rule, value, callback){
+ // if(value && !idenReg.test(value)){
+ // callback("专区标识长度2-20,只能以字母开头结尾,可包含数字、下划线、中划线");
+ // }
+ // callback();
+ // }
return(
@@ -93,8 +93,8 @@ function Apply(props){
{getFieldDecorator("key",{
rules:[
{ required: true,message:"请输入专区域名标识" },
- { validator: checkIndentity }
- ]
+ { pattern: /^[a-zA-Z][a-zA-Z0-9_-]{0,18}[a-zA-Z]$/, message: "长度2-20,只能包含数字、字母、下划线、中划线,必须以字母开头结尾"},
+ ]
})(
)}
diff --git a/src/forge/Information/Pages/main.jsx b/src/forge/Information/Pages/main.jsx
index 04d33aa1..9fe9137f 100644
--- a/src/forge/Information/Pages/main.jsx
+++ b/src/forge/Information/Pages/main.jsx
@@ -1,7 +1,7 @@
import React , { useState , useEffect } from 'react';
-import { Menu , Spin , Skeleton } from 'antd';
+import { Menu , Spin , Skeleton, Button, Dropdown } from 'antd';
import Hot from '../Component/hot';
-import { Box , LongWidth } from '../../Component/layout';
+import { Box , FlexAJ, LongWidth } from '../../Component/layout';
import { Link } from 'react-router-dom';
import Lists from './newsList';
import guideArrow from '../img/guideArrow.png';
@@ -24,7 +24,18 @@ function Main(props){
const [ isSpin , setIsSpin ] = useState(true);
const [ newCateId , setNewCateId ] = useState(undefined);
const { deptId , cateId } = props.match.params;
- const { id, temp } = props;
+ const { id, temp, role, history } = props;
+
+ const menu = (
+
+ );
useEffect(()=>{
@@ -34,7 +45,7 @@ function Main(props){
getMainList();
} else {
getCateList();
- }
+ }
getHotList();
}
},[id])
@@ -109,7 +120,17 @@ function Main(props){
-
{ tempConfig[temp].mainTitle }
+
+
{tempConfig[temp].mainTitle}
+ {role && role.role !== "None" &&
+ {role.role === "Member" && }
+ {role.role === "Member" ?
+
+ : }
+
}
+
{
mainList && mainList.length>0 &&
(
diff --git a/src/forge/Information/Pages/newsCreate.jsx b/src/forge/Information/Pages/newsCreate.jsx
new file mode 100644
index 00000000..84483c79
--- /dev/null
+++ b/src/forge/Information/Pages/newsCreate.jsx
@@ -0,0 +1,175 @@
+import React,{ useState , useEffect } from 'react';
+import { Breadcrumb, Button, Form, Input, message, Select } from 'antd';
+import { getZoneUrl } from 'educoder';
+import MdEditor from '../../../modules/tpm/challengesnew/tpm-md-editor';
+import RichEditor from '../../Component/RichEditor';
+import UploadImage from '../../Team/Component/UploadImage';
+import { tempConfig } from '../tempInfo';
+import '../index.scss';
+import { Base64 } from 'js-base64';
+import { addNewsByDirId, getDirListById, getNewsDetailByAu, updateDoc } from '../api';
+import { httpUrl } from '../fetch';
+
+function NewsCreate(props){
+ const {history, id} = props;
+ const temp = props.temp;
+ const { getFieldDecorator, validateFields , setFieldsValue, setFields } = props.form;
+ const { deptId, id: newsId } = props.match.params;
+ const pathname = props.location.pathname;
+ const [type, setType] = useState(new URLSearchParams(props.location.search.substring(1)).get('type'));
+ const [value, setValue] = useState(undefined);
+ const [imageUrl, setImageUrl] = useState(undefined)
+ const [dirList, setDirList] = useState(undefined);
+ const [loading, setLoading] = useState(false);
+ const [isEdit, setIsEdit] = useState(false);
+ const layout = {
+ labelCol: { span: 2 },
+ wrapperCol: { span: 14 },
+ };
+
+ useEffect(()=>{
+ id && getDircList();
+ },[id])
+
+ useEffect(()=>{
+ if(pathname){
+ if(pathname.endsWith("/edit")){
+ setIsEdit(true);
+ getNewsDetail();
+ }else{
+ setIsEdit(false);
+ }
+ }
+ },[pathname])
+
+ function getDircList(){
+ getDirListById(id).then(res=>{
+ if(res){
+ setDirList(res.data.rows);
+ }
+ })
+ }
+
+ function getNewsDetail() {
+ getNewsDetailByAu(newsId).then(res=>{
+ if(res && res.data){
+ const {name, summary, cmsDir, content, headImg, editorType} = res.data.data;
+ setType(editorType === "rich_editor" ? 'richEditor' : 'mdEditor')
+ setFieldsValue({
+ name,
+ summary,
+ dirId: cmsDir && cmsDir.id,
+ content: Base64.decode(content),
+ headImg
+ });
+ setImageUrl(headImg);
+ setValue(Base64.decode(content));
+ }
+ })
+ }
+
+ // 新建文章
+ function submit(e){
+ e.preventDefault();
+ validateFields((err, fieldsValue)=>{
+ const hasContent = type === "richEditor" && fieldsValue.content === "
"
+ if(err || hasContent){
+ hasContent && setFields({content: {value:fieldsValue.content,errors:[new Error('请输入内容!')]}});
+ return;
+ }
+ setLoading(true);
+ const params = {
+ ...fieldsValue,
+ editorType: type === "richEditor" ? "rich_editor" : "markdown_editor",
+ headImg: imageUrl,
+ content: Base64.encode(fieldsValue.content)
+ }
+ if(isEdit){
+ delete params.editorType;
+ return updateDoc(newsId, params).then(res=>{
+ const {data:{code, msg}} = res;
+ setLoading(false);
+ if(code === 200){
+ message.success("更新成功");
+ history.push(`/zone/${deptId}/news/self`);
+ }else{
+ message.error(msg || '更新失败,请联系管理员!')
+ }
+ })
+ }
+ addNewsByDirId(fieldsValue.dirId, params).then(res=>{
+ const {data:{code, msg}} = res;
+ setLoading(false);
+ if(code === 200){
+ message.success("新增成功");
+ history.push(`/zone/${deptId}/news/self`);
+ }else{
+ message.error(msg || '新增失败,请联系管理员!')
+ }
+ })
+ })
+ }
+
+ return(
+
+
+ {tempConfig[temp].mainTitle}
+ {isEdit ? '编辑' : '新建'}文章
+
+
+
+ {getFieldDecorator("name", {
+ rules:[{ required:true,message:"请输入文章标题!" },
+ {type: 'string', max: 200, message: "最大长度200"},
+ {pattern: /^[^<>[\]/\\]+$/, message: "不能输入特殊字符:< > [ ] / \\"}]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("summary", {
+ rules:[{ required:true,message:"请输入概览!" },
+ {type: 'string', max: 200, message: "最大长度200"}]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("dirId", {
+ rules:[{ required:true,message:"请选择文章所属栏目!" }]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("content",{
+ rules:[{required:true,message:"请输入内容!"}],
+ })(
+ type === "richEditor" ? {setFieldsValue({"content": value})}}/> : {setFieldsValue({"content": value})}}
+ imageExpand={false}
+ >
+ )}
+
+
+ setImageUrl(url) } url={ imageUrl ? imageUrl : undefined} action={ getZoneUrl(`/api/cms/common/upload`) } />
+
+
+
+
+
+
+
+
+ )
+}
+export default Form.create()(NewsCreate);
\ No newline at end of file
diff --git a/src/forge/Information/Pages/newsDetail.jsx b/src/forge/Information/Pages/newsDetail.jsx
index 50e58767..b98da833 100644
--- a/src/forge/Information/Pages/newsDetail.jsx
+++ b/src/forge/Information/Pages/newsDetail.jsx
@@ -7,7 +7,7 @@ import { getNewsDetail } from '../api';
import { IsPC } from 'educoder';
import { tempConfig } from '../tempInfo';
import Acce from '../Component/mobile/accessory';
-
+import { addMeta, setSeoMeta } from 'educoder';
function NewsDetail(props){
@@ -44,6 +44,21 @@ function NewsDetail(props){
}
},[id])
+ useEffect(()=>{
+ // 设置网页标题
+ if(detail){
+ const { name, cmsDir, summary} = detail;
+ document.title = `${ name }/${ cmsDir.name }`;
+ addMeta('Keywords', `${ name },${ cmsDir.name },${ summary }`);
+ }
+ return componentWillUnmount
+ }, [detail])
+
+ function componentWillUnmount() {
+ document.title= zonedetail.name;
+ setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
+ }
+
function getDetails(){
setIsSpin(true)
getNewsDetail(id).then(result=>{
diff --git a/src/forge/Information/Pages/selfList.jsx b/src/forge/Information/Pages/selfList.jsx
index 5df34fde..fce4407b 100644
--- a/src/forge/Information/Pages/selfList.jsx
+++ b/src/forge/Information/Pages/selfList.jsx
@@ -18,8 +18,8 @@ function SelfList(props){
const [ visible ,setVisible ] = useState(false);
const [ deleId , setDeleId] = useState(undefined);
const pathname = props.location.pathname;
+ const { deptId} = props.match.params;
const { id , temp } = props;
- const { deptId } = props.match.params;
const limit = 15;
useEffect(()=>{
@@ -141,7 +141,7 @@ function SelfList(props){
{moment(i.createTime).format("YYYY/MM/DD")}
- 编辑
+ 编辑
{setVisible(true);setDeleId(i.id)}}>删除
diff --git a/src/forge/Information/Pages/source.jsx b/src/forge/Information/Pages/source.jsx
index 06c22e4f..eed911c1 100644
--- a/src/forge/Information/Pages/source.jsx
+++ b/src/forge/Information/Pages/source.jsx
@@ -1,5 +1,5 @@
import React , { useEffect , useState } from 'react';
-import { Input , Pagination, Spin, Tag } from 'antd';
+import { Button, Input , Pagination, Spin, Tag } from 'antd';
import SourceIcon from '../img/sourceIcon.png';
import { Link } from 'react-router-dom';
import axios from 'axios';
@@ -23,8 +23,7 @@ function Source(props){
const [ search , setSearch ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true);
const limit = 20;
- const { id , temp } = props;
-
+ const { id , temp, history, role } = props;
useEffect(()=>{
id && getLists();
@@ -70,12 +69,20 @@ function Source(props){
setPage(1);
}
+ function addSource(){
+ if(role && role.role === "Manager"){
+ window.open(role.resourceManageUrl);
+ }else{
+ history.push(`/zone/${deptId}/source/add`)
+ }
+ }
+
return(
资源发布
-
-
+ 搜索 :undefined}
/>
+ {role && role.role !== "None" &&
+ {role.role === "Member" && }
+
+
}
diff --git a/src/forge/Information/Pages/sourceCreate.jsx b/src/forge/Information/Pages/sourceCreate.jsx
new file mode 100644
index 00000000..526df0e1
--- /dev/null
+++ b/src/forge/Information/Pages/sourceCreate.jsx
@@ -0,0 +1,235 @@
+import React,{ useState , useEffect } from 'react';
+import { Breadcrumb, Button, Form, Icon, Input, message, Select, Upload } from 'antd';
+import { getZoneUrl } from 'educoder';
+import '../index.scss';
+import { Link } from 'react-router-dom';
+import { getTypeByFileId, getSourceZoneList, addResource, getSourceDetailByAu, updateMyResource } from '../api';
+
+function SourceCreate(props){
+ const {history, id} = props;
+ const { getFieldDecorator, validateFields , setFieldsValue, setFields } = props.form;
+ const { deptId, sourceid} = props.match.params;
+ const pathname = props.location.pathname;
+ const [ zoneList , setZoneList ] = useState(undefined);
+ const [files, setFiles] = useState([]);
+ const [loadingBut, setLoadingBut] = useState(false);
+ const [isEdit, setIsEdit] = useState(false);
+
+ const layout = {
+ labelCol: { span: 2 },
+ wrapperCol: { span: 14 },
+ };
+
+ useEffect(()=>{
+ id && getZoneList();
+ },[id])
+
+ useEffect(()=>{
+ if(pathname){
+ if(pathname.endsWith("/edit")){
+ setIsEdit(true);
+ getSourceDetail();
+ }else{
+ setIsEdit(false);
+ }
+ }
+ },[pathname])
+
+ function getSourceDetail() {
+ getSourceDetailByAu(sourceid).then(res=>{
+ if(res && res.data){
+ const {name, domainId, summary, fileList} = res.data.data;
+ const fileMap = fileList.map(item=>{
+ const {fileId, fileSizeInfo, fileOriginName, zoneResourceType: {id, name}} = item;
+ return {
+ uid: fileId,
+ status: "done",
+ response: {fileId: fileId, fileSize: fileSizeInfo},
+ name: fileOriginName,
+ zoneResourceType:{id, name}
+ }
+ })
+ setFiles(fileMap);
+ setFieldsValue({
+ name,
+ domainId,
+ summary,
+ fileList: fileMap
+ });
+ }
+ })
+ }
+
+ function getZoneList(){
+ getSourceZoneList(id).then(response=>{
+ if(response && response.data){
+ setZoneList(response.data.rows);
+ }
+ }).catch(error=>{})
+ }
+
+ // 新建文章
+ function submit(e){
+ e.preventDefault();
+ validateFields((err, fieldsValue)=>{
+ if(err || !files.length){
+ !files.length && setFields({fileList: {value:undefined,errors:[new Error('请上传资源附件!')]}});
+ return;
+ }
+ const fileIds = files.map(item=>{return item.response.fileId}).toString();
+ const params = {
+ ...fieldsValue,
+ zoneId: id,
+ fileIds
+ }
+ delete params.fileList;
+ if(isEdit){
+ delete params.zoneId;
+ params.id= parseInt(sourceid, 10);
+ updateMyResource(params).then((res)=>{
+ const {data:{code, msg}} = res;
+ if(code === 200){
+ message.success("编辑成功");
+ history.push(`/zone/${deptId}/source/self`);
+ }else{
+ message.error(msg || '编辑失败,请联系管理员!')
+ }
+ })
+ return;
+ }
+ addResource(params).then((res)=>{
+ const {data:{code, msg}} = res;
+ if(code === 200){
+ message.success("新增成功");
+ history.push(`/zone/${deptId}/source/self`);
+ }else{
+ message.error(msg || '新增失败,请联系管理员!')
+ }
+ })
+ })
+ }
+
+ function beforeUpload(file){
+ if (file.size > 200 * 1024 * 1024) {
+ message.error('单个文件限制200MB以内');
+ return false;
+ }
+ if(files){
+ const sameNameFIles = files.filter(item=>item.name === file.name);
+ if(sameNameFIles.length >= 1){
+ message.error("请不要重复上传同名文件!");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ async function onChange({file, fileList: fileListByUpload}){
+ if(file && (file.status === "done" || file.status === 'uploading' || file.status === 'removed')){
+ setLoadingBut(true);
+ const fileList = [...files];
+ const index = fileList.findIndex(item=>item.uid === file.uid);
+ if(index !== -1){
+ fileList[index] = file;
+ }else{
+ fileList.push(file);
+ }
+ setFiles(fileList);
+ if(!file.response) return
+ if(file.response.code !== 200){
+ message.error(file.response.msg || '上传失败,请联系管理员!')
+ fileList.pop()
+ setFiles([...fileList]);
+ setLoadingBut(false);
+ }else{
+ // 获取此附件的资源类别
+ await getTypeByFileId(id, file.response.fileId).then((res)=>{
+ const {data:{code, data: data1, msg}} = res;
+ if(code !== 200){
+ return message.error(msg);
+ }
+ fileList[fileList.length-1].zoneResourceType = {
+ id: data1.id,
+ name: data1.name
+ }
+ })
+ setFiles([...fileList]);
+ setLoadingBut(false);
+ }
+ }
+ }
+
+ function deleteFile(uid){
+ const fileList = files.filter(item=>item.uid !== uid);
+ setFiles(fileList);
+ }
+
+ return(
+
+
+ 资源列表
+ {isEdit ? '编辑' : '新建'}资源
+
+
+
+ {getFieldDecorator("name", {
+ rules:[{ required:true,message:"请输入资源名称!" },
+ {type: 'string', max: 200, message: "最大长度200"}]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("domainId", {
+ rules:[{ required:true,message:"请选择资源领域!" }]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("summary", {
+ rules:[{ required:true,message:"请输入资源简介!" },
+ {type: 'string', max: 300, message: "最大长度300"}]
+ })(
+
+ )}
+
+
可上传多个资源文件,单个文件限制200MB以内 }>
+ {getFieldDecorator("fileList", {
+ rules:[{ required:true,message:"请上传资源附件!" }]
+ })(
+
+
+
+ )}
+
+ {/* 附件展示 */}
+
+ {files && files.map((item, index)=>{
+ const {uid, status, response, name, zoneResourceType} = item;
+ return
+ {status === "uploading" ? : }
+ {name}
+ {response && response.fileSize}
+ {zoneResourceType && zoneResourceType.name}
+ {deleteFile(uid)}}/>
+
+ })}
+
+
+
+
+
+
+
+
+ )
+}
+export default Form.create()(SourceCreate);
\ No newline at end of file
diff --git a/src/forge/Information/Pages/sourceDetail.jsx b/src/forge/Information/Pages/sourceDetail.jsx
index d94f8536..9b06fa4c 100644
--- a/src/forge/Information/Pages/sourceDetail.jsx
+++ b/src/forge/Information/Pages/sourceDetail.jsx
@@ -9,11 +9,13 @@ import { Base64 } from 'js-base64';
import { httpUrl } from '../fetch';
import { AlignCenter, FlexAJ } from '../../Component/layout';
import SourceIcon from '../img/sourceIcon.png';
+import { addMeta, setSeoMeta } from 'educoder';
function SourceDetail(props){
const { deptId , sourceid } = props.match.params;
const [ detail , setDetail ] = useState(undefined);
+ const zonedetail = props.data;
useEffect(()=>{
if(sourceid){
@@ -21,6 +23,21 @@ function SourceDetail(props){
}
},[sourceid])
+ useEffect(()=>{
+ // 设置网页标题
+ if(detail){
+ const { name, domainName, summary} = detail;
+ document.title = `${ name }/${ domainName }`;
+ addMeta('Keywords', `${ name },${ domainName },${ summary }`);
+ }
+ return componentWillUnmount
+ }, [detail])
+
+ function componentWillUnmount() {
+ document.title= zonedetail.name;
+ setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`)
+ }
+
function getDetails(){
getSourceDetail(sourceid).then(response=>{
if(response){
diff --git a/src/forge/Information/api.js b/src/forge/Information/api.js
index 9a226ea5..2496268c 100644
--- a/src/forge/Information/api.js
+++ b/src/forge/Information/api.js
@@ -17,6 +17,13 @@ export function getCheckZoneRole(id) {
});
}
+export function getCurrentRole(id) {
+ return fetch({
+ url: `/zone/zoneFront/${id}/checkCurrentRole`,
+ method: 'get',
+ });
+}
+
/********首页接口******/
export function getHomePageList(id) {
return fetch({
@@ -115,6 +122,13 @@ export function applyJoin(id,data) {
}
// 资源模块
+export function addResource(data) {
+ return fetch({
+ url: `/zone/zoneFront/addResource`,
+ method: 'post',
+ data: data
+ });
+}
export function getSourceTypeList(id){
return fetch({
url:`/zone/open/${id}/resourceType/list`,
@@ -158,7 +172,82 @@ export function delSourceMyList(id){
export function postCreateZone(data) {
return fetch({
url: `/zone/application`,
+ })
+}
+
+// 根据文件id获取专区下资源类别
+export function getTypeByFileId(zoneId, fileId){
+ return fetch({
+ url:`/zone/resourceType/zone/${zoneId}/getResourceTypeByFileId/${fileId}`,
+ method: 'get'
+ })
+}
+
+// 新增领域
+export function addSourceType(data) {
+ return fetch({
+ url: `/zone/resourceType`,
method: 'post',
data: data
});
+}
+
+// 修改当前文件对应的资源类别
+export function updateResourceTypeByFileId(data) {
+ return fetch({
+ url: '/zone/resourceType/updateResourceTypeByFileId',
+ method: 'PUT',
+ data: data
+ });
+}
+
+// 获取文章领域列表
+export function getDirListById(id){
+ return fetch({
+ url:`/cms/doc/open/zone/${id}/dirList`,
+ method: 'get'
+ })
+}
+
+// 新增文章
+export function addNewsByDirId(dirId, data) {
+ return fetch({
+ url: `/cms/doc/dir/${dirId}`,
+ method: 'post',
+ data: data
+ });
+}
+
+// 获取文章详细信息(需要用户权限)
+export function getNewsDetailByAu(id){
+ return fetch({
+ url:`/cms/doc/${id}`,
+ method: 'get',
+ })
+}
+
+// 修改文章详细信息(需要用户权限)
+export function updateDoc(id, data) {
+ return fetch({
+ url: `/cms/doc/${id}`,
+ method: 'PUT',
+ data: data
+ });
+}
+
+// 获取资源详细信息(需要用户权限)
+export function getSourceDetailByAu(id){
+ return fetch({
+ url:`/zone/zoneFront/myResource/${id}`,
+ method: 'get',
+ })
+}
+
+// 修改资源详细信息(需要用户权限)
+export function updateMyResource(data) {
+ return fetch({
+ url: `/zone/zoneFront/editResource`,
+ method: 'PUT',
+ data: data
+ });
}
\ No newline at end of file
diff --git a/src/forge/Information/fetch.js b/src/forge/Information/fetch.js
index ddb0df2b..d7491da4 100644
--- a/src/forge/Information/fetch.js
+++ b/src/forge/Information/fetch.js
@@ -1,5 +1,6 @@
import axios from 'axios';
import { message , notification } from 'antd';
+import cookie from 'react-cookies';
function beforeFetch(actionUrl){
if (window.location.href.indexOf('localhost') < 0) {
@@ -8,6 +9,7 @@ function beforeFetch(actionUrl){
const service = axios.create({
headers:{Authorization:"0cd46d63363af9205eb7ccecff574309ce069a97"},
+ // headers:{Authorization: cookie.load("autologin_trustie")},
baseURL: actionUrl,
timeout: 1800000, // 请求超时时间
});
diff --git a/src/forge/Information/index.jsx b/src/forge/Information/index.jsx
index 14960da6..e8b70855 100644
--- a/src/forge/Information/index.jsx
+++ b/src/forge/Information/index.jsx
@@ -8,7 +8,7 @@ import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC"
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../../Loading";
-import { getMainInfos , getCheckZoneRole } from './api';
+import { getMainInfos , getCheckZoneRole, getCurrentRole } from './api';
import PublicBanner from "./Component/publicBanner";
import './index.scss';
import { IsPC } from 'educoder';
@@ -16,11 +16,17 @@ import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import { tempEnum } from "./tempInfo";
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
+import { setSeoMeta } from 'educoder';
+
const SourceDetail = Loadable({
loader: () => import("./Pages/sourceDetail"),
loading: Loading,
});
+const SourceCreate = Loadable({
+ loader: () => import("./Pages/sourceCreate"),
+ loading: Loading,
+});
const VIP = Loadable({
loader: () => import("./Pages/zoneVIP"),
loading: Loading,
@@ -64,6 +70,10 @@ const NewsList = Loadable({
loader: () => import("./Pages/newsList"),
loading: Loading,
});
+const NewsCreate = Loadable({
+ loader: () => import("./Pages/newsCreate"),
+ loading: Loading,
+});
const Main = Loadable({
loader: () => import("./Pages/main"),
@@ -81,8 +91,10 @@ function Index(props){
const { deptId } = props.match.params;
const [ id , setId ] = useState(undefined);
const [ temp , setTemp ] = useState(tempEnum.zone);
+ const [ role , setRole ] = useState(undefined);
const { pathname } = props.history.location;
const sourcedetail = pathname.indexOf(`/zone/${deptId}/newdetail/`)>-1 && IsPC();
+ const {current_user} = props;
useEffect(()=>{
if(deptId && deptId!=="apply"){
@@ -115,7 +127,9 @@ function Index(props){
setId(data.id);
if(data.id){
getAdminUrl(data.id);
+ getRole(data.id)
}
+ setSeoMeta(`${data.name},`, data.name, data.subTitle, `/zone/${deptId}`)
}
}).catch(console.error())
}
@@ -129,6 +143,15 @@ function Index(props){
}
}).catch(error=>{})
}
+
+ function getRole(id){
+ if(current_user && current_user.login){
+ getCurrentRole(id).then(res=>{
+ setRole(res.data.data);
+ }).catch(error=>{})
+ }
+ }
+
return(
{ (!sourcedetail && deptId!=="apply") && (id ?
: )}
@@ -139,10 +162,22 @@ function Index(props){
)}
>
+ (
+
+ )}
+ >
+ (
+
+ )}
+ >
(
-
+
)}
>
)}
>
+ (
+
+ )}
+ >
+ (
+
+ )}
+ >
(
-
+
)}
>
(
-
+
)}
>
(
-
+
)}
>
{data && data.helperShow === 1 && import("./website/mySiteList"),
loading: Loading,
});
+const CreateSite = Loadable({
+ loader: () => import("./website/createSite"),
+ loading: Loading,
+});
function Index(props){
const { current_user,mygetHelmetapi , checkIfLogin } = props;
const { pathname } = props.location;
const notice_url = mygetHelmetapi && mygetHelmetapi.common && mygetHelmetapi.common.notice;
+ const {id_card_verify, website_permission} = current_user;
const [ avatarVisible , setAvatarVisible ] = useState(false);
const [active, setActive] = useState(1);
- console.log('active', active);
useEffect(()=>{
if(checkIfLogin() === false){
- props.history.push('/login');
+ props.history.push(`/login?go_page=${pathname}`);
}
},[])
useEffect(()=>{
- console.log('pathname', pathname, ["/settings/profile"].indexOf(pathname));
+ const pattern = /^\/settings\/installbot\/\d+$/;
if(["/settings/profile"].indexOf(pathname) !== -1){
setActive(1);
}else if(["/settings/emails", "/settings/phone", "/settings/password", "/settings/cancel"].indexOf(pathname) !== -1){
@@ -100,11 +104,11 @@ function Index(props){
setActive(5);
}else if(["/settings/CLA"].indexOf(pathname) !== -1){
setActive(6);
- }else if(["/settings/mybot"].indexOf(pathname) !== -1){
+ }else if(["/settings/mybot", "/settings/mybot/new"].indexOf(pathname) !== -1){
setActive(7);
- }else if(["/settings/installbot"].indexOf(pathname) !== -1){
+ }else if(["/settings/installbot"].indexOf(pathname) !== -1 || pattern.test(pathname)){
setActive(8);
- }else if(["/settings/mysite"].indexOf(pathname) !== -1){
+ }else if(["/settings/mysite", "/settings/mysite/create"].indexOf(pathname) !== -1){
setActive(9);
}
}, [pathname])
@@ -154,10 +158,10 @@ function Index(props){
我的Bot
Bot安装
- {/*
@@ -262,6 +266,13 @@ function Index(props){
)}
>
+ {/* 创建站点 */}
+ {id_card_verify && website_permission && (
+
+ )}
+ >}
{/* 个人建站 */}
{
+ document.title = "创建站点";
+ }, []);
+
+ useEffect(()=>{
+ axios.get(`/site_pages/themes.json`, {params: {language_frame: language}}).then(res=>{
+ if(res && res.status === 200){
+ setThemes(res.data.themes);
+ setTheme(res.data.themes[0])
+ }
+ })
+ }, [language])
+
+ useEffect(()=>{
+ if(theme && theme.clone_url && theme && theme.clone_url.indexOf("/") > -1){
+ let arr = theme && theme.clone_url.split("/");
+ let first = arr[arr.length-1];
+ if(first.indexOf(".") > -1){
+ let second = first.split('.')[0];
+ if(!second)return;
+ setFieldsValue({
+ repository_name:second,
+ name:second
+ })
+ }else{
+ setFieldsValue({
+ repository_name:first
+ })
+ }
+ }
+ }, [theme])
+
+ function submit(e) {
+ e.preventDefault();
+ validateFieldsAndScroll((err, values) => {
+ if (!err) {
+ axios.post(`/projects/page_migrate.json`,{
+ ...values,
+ clone_addr: theme && theme.clone_url,
+ theme: theme && theme.name,
+ user_id: current_user.user_id
+ }).then(res=>{
+ if(res && res.status === 200){
+ message.success("新建成功");
+ history.push(`/settings/mysite`);
+ }
+ })
+ }
+ });
+ }
+
+ return (
+
+ 我的站点 / 新建站点
+
+ {getFieldDecorator("site_name", {
+ rules: [{ required: true, message: "请输入站点名称" },
+ {type: 'string', max: 50, min: 1, message: "长度1-50"}],
+ })()}
+
+
+ {getFieldDecorator("identifier", {
+ rules: [{ required: true, message: "请输入站点标识" },
+ {pattern: /^[a-zA-Z0-9]{2,100}$/, message: '长度2-100,只能包含数字和字母'}],
+ })(
+ {
+ setTag(e.target.value);
+ }}
+ placeholder="请输入站点标识"
+ />
+ )}
+
+ http://{current_user.login}.kingchan.cn/{tag}
+
+
+
+ {getFieldDecorator("language_frame", {initialValue: 0})(
+
+ )}
+
+
+
+ {themes && themes.map(item=>{
+ const {image, name, clone_url} = item;
+ return {setTheme(item)}}>
+
+
})
+
{name}
+
+ })}
+
+
+ 项目配置
+ 我们会为您生成一个项目,来管理您的个人主页,请配置您的项目信息
+
+
+
+
+ {/* / 0.87 */}
+
+ {getFieldDecorator("repository_name", {
+ rules: [{ required: true, message: "请输入项目标识" },
+ {pattern: /^[a-zA-Z0-9][a-zA-Z0-9_.-]{2,100}[a-zA-Z0-9]$/, message: "长度2-100,只能包含数字、字母、下划线、中划线、英文句号,必须以数字和字母开头,不能以下划线/中划线/英文句号开头和结尾"}],
+ })(
+
+ )}
+
+
+
+ {getFieldDecorator("name", {
+ rules: [{ required: true, message: "请输入项目名称" },
+ {type: 'string', max: 50, min: 1, message: "长度1-50"}],
+ })(
+
+ )}
+
+
+ {getFieldDecorator("description", {
+ rules: [{type: 'string', max: 200, message: "长度200"}]
+ })(
+
+ )}
+
+
+
+
+
+
+
+ );
+}
+export default Form.create()(CreateSite);
diff --git a/src/forge/SecuritySetting/website/index.scss b/src/forge/SecuritySetting/website/index.scss
index 89b9d18c..35214ccf 100644
--- a/src/forge/SecuritySetting/website/index.scss
+++ b/src/forge/SecuritySetting/website/index.scss
@@ -1,8 +1,33 @@
-.default_head{
+.mySites_head{
height: 65px;
line-height: 64px;
border-bottom: 1px solid rgba(224, 230, 245, 1);
color:#151d40;
font-size:17px;
- padding-bottom:20px;
+}
+.createSiteForm{
+ .themeBox{
+ text-align: center;
+ position: relative;
+ cursor: pointer;
+ }
+ .icon-wancheng{
+ position: absolute;
+ right: 4px;
+ top: -7px;
+ color: #e5e3e0;
+ &.active{
+ color: #ffa13a;
+ }
+ }
+}
+.siteBox{
+ padding: 15px 0;
+ border-bottom: 1px dashed #e0e6f5;
+ .siteName{
+ color: #05101a;
+ &:active, &:hover{
+ color: $primary-color;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/forge/SecuritySetting/website/mySiteList.jsx b/src/forge/SecuritySetting/website/mySiteList.jsx
index 4c241777..338c7967 100644
--- a/src/forge/SecuritySetting/website/mySiteList.jsx
+++ b/src/forge/SecuritySetting/website/mySiteList.jsx
@@ -1,16 +1,88 @@
import React, { useState, useEffect, Fragment } from "react";
-import { Button, Icon, message, Modal } from "antd";
+import { Button, Pagination, Spin } from "antd";
import './index.scss';
+import '../../users/Material/Index.scss';
+import '../bot/exploit/index.scss'
+import axios from "axios";
+import Nodata from "../../Nodata";
+import { FlexAJ } from "../../Component/layout";
function MySiteList(props){
- const {current_user} = props;
+ const {current_user, history} = props;
+ const {id_card_verify, website_permission} = current_user;
+ const [total, setTotal] = useState(0);
+ const [pages, setPages] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [page, setPage] = useState(1);
useEffect(()=>{
document.title='我的站点';
+ window.scrollTo(0,0);
}, [])
- return
- 我的站点
-
+ useEffect(()=>{
+ if(id_card_verify){
+ setLoading(true);
+ // 获取站点列表
+ axios.get(`/site_pages.json`, {params: {limit: 15, page: page}}).then(res=>{
+ if(res && res.status === 200){
+ const {total_count, pages} = res.data;
+ setPages(pages);
+ setTotal(total_count);
+ }
+ setLoading(false);
+ })
+ }
+ }, [id_card_verify, page])
+
+ return
+
+ 我的站点
+ {id_card_verify && website_permission && }
+
+ {/* 站点权限被管理员关闭 */}
+ {id_card_verify && !website_permission && 您的站点权限被锁定,请联系平台管理员。
}
+ {/* 未通过实名认证 */}
+ {!id_card_verify &&
+ 您尚未通过实名认证,无法使用此服务,如需使用,请先进行实名认证。
+
+ }
+
+ {/* 通过实名认证 */}
+ {id_card_verify &&
+ {!loading && total === 0 ?
+
个人建站是一个免费的静态网页托管服务,您可以使用 个人建站服务托管个人主页、项目站点等静态网页。
+
+
:
+ {pages && pages.map(item=>{
+ const {owner, repo, url, state, state_description, build_state} = item
+ return
+
+
+ {state && build_state ?
{window.open(url)}}>{item.site_name} :
{item.site_name}}
+
{state ? build_state ? "已部署" : "未部署" : '被关闭'}
+
+ 主题: {item.theme}
+ |
+ 建站工具:{item.language_frame}
+
+ {!state &&
关闭原因:{state_description}
}
+
+
+
+ })}
+
+
{setPage(page)}}
+ total = {total}
+ hideOnSinglePage
+ >
+
+
}
+ }
+
}
export default MySiteList;
\ No newline at end of file
diff --git a/src/forge/Server/Index.jsx b/src/forge/Server/Index.jsx
index ef62dc12..18abf376 100644
--- a/src/forge/Server/Index.jsx
+++ b/src/forge/Server/Index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import { Route, Switch } from 'react-router-dom';
import "./index.scss";
import Loadable from 'react-loadable';
@@ -18,7 +18,22 @@ const Reposyncer = Loadable({
loader: () => import('./reposyncer'),
loading: Loading,
})
+// 个人建站服务
+const Pages = Loadable({
+ loader: () => import('./pages'),
+ loading: Loading,
+})
function ServerIndex(props){
+ const { projectDetail } = props;
+ const { owner , projectsId } = props.match.params;
+
+ useEffect(()=>{
+ // 非项目协作者不可进入服务tab (3397)
+ if(projectDetail && projectDetail.permission === ""){
+ props.history.push(`/${owner}/${projectsId}`);
+ }
+ }, [projectDetail])
+
return(
@@ -32,6 +47,12 @@ function ServerIndex(props){
() => ()
}
>
+ {/* 个人建站服务 */}
+ {projectDetail && projectDetail.author.type === "User" && ()
+ }
+ >}
(
)
diff --git a/src/forge/Server/List.jsx b/src/forge/Server/List.jsx
index e1c59ff1..14677090 100644
--- a/src/forge/Server/List.jsx
+++ b/src/forge/Server/List.jsx
@@ -7,7 +7,7 @@ function Main(props){
const { owner , projectsId } = props.match.params;
const [ has_trace_user , setHas_trace_user ] = useState(false);
- const { current_user , resetUserInfo, projectDetail, showNotification } = props;
+ const { current_user , resetUserInfo, projectDetail, showNotification, isDeveloper, isManager, isReporter } = props;
useEffect(()=>{
// 更新网页标题
@@ -64,6 +64,16 @@ function Main(props){
查看详情
*/}
+ {projectDetail && projectDetail.author.type === "User" &&
+
+
+ 个人建站服务
+
+ 支持Hugo、Jekyll、Hexo静态网站服务
+
+ 查看详情
+
+ }
)
diff --git a/src/forge/Server/pages/index.jsx b/src/forge/Server/pages/index.jsx
new file mode 100644
index 00000000..84c0abf1
--- /dev/null
+++ b/src/forge/Server/pages/index.jsx
@@ -0,0 +1,207 @@
+import React, { Fragment, useEffect, useState } from 'react';
+import { Spin, message, Button, Form, Input, Select, Descriptions, Alert } from 'antd';
+import axios from 'axios';
+import SelectBranch from '../../../forge/Branch/Select';
+import './index.scss';
+
+function Pages(props) {
+ const {current_user, history, form, projectDetail, defaultBranch, isManager} = props;
+ const { owner , projectsId } = props.match.params;
+ const {id_card_verify} = current_user;
+ const { getFieldDecorator, validateFieldsAndScroll } = form;
+ const [reload, setReload] = useState(undefined);
+ const [loading, setLoading] = useState(false);
+ const [pageInfo, setPageInfo] = useState(undefined);
+ const [tag, setTag] = useState(undefined);
+ const [branch, setBranch ] = useState(null);
+ const [building, setBuilding] = useState(false);
+ const [isBuild, setIsBuild] = useState(false);
+ const [result, setResult] = useState(undefined);
+
+ useEffect(()=>{
+ // 更新网页标题
+ if(projectDetail){
+ const { author, name} = projectDetail;
+ document.title = `个人建站-${author.name}/${name}`;
+ }
+ }, [projectDetail])
+
+ useEffect(()=>{
+ if(id_card_verify){
+ setLoading(true);
+ // 获取站点列表
+ axios.get(`/site_pages/x.json`, {params:{owner, repo: projectsId}}).then(res=>{
+ if(res && res.status === 200){
+ const {last_build_info} = res.data.data
+ setPageInfo(res.data.data);
+ last_build_info && last_build_info.length && setResult(last_build_info);
+ }
+ setLoading(false);
+ })
+ }
+ }, [id_card_verify, reload])
+
+ // 基于仓库创建站点
+ function submit(e) {
+ e.preventDefault();
+ validateFieldsAndScroll((err, values) => {
+ if (!err) {
+ axios.post(`/site_pages.json`,{
+ ...values,
+ owner,
+ repo: projectsId
+ }).then(res=>{
+ if(res && res.status === 200){
+ setReload(Math.random());
+ message.success("创建成功");
+ }
+ })
+ }
+ });
+ }
+
+ // 部署
+ function startBuild(){
+ setBuilding(true);
+ axios.post(`/site_pages/${pageInfo.id}/build.json`,{
+ owner,
+ repo: projectsId,
+ branch: branch || defaultBranch
+ }).then(res=>{
+ if(res && res.data && res.data.status === 0){
+ setResult(res.data.data);
+ }else{
+ message.error((res && res.data && res.data.message) || "部署失败,请稍后重试");
+ }
+ setReload(Math.random());
+ setIsBuild(false);
+ setBuilding(false);
+ })
+ }
+
+ return (
+
+
+ 个人建站服务{!pageInfo && !loading && id_card_verify && isManager && ' - 新建站点'}
+
+ {/* 未通过实名认证 */}
+ {!id_card_verify &&
+ 您尚未通过实名认证,无法使用此服务,如需使用,请先进行实名认证。
+
+ }
+ {id_card_verify && isManager &&
+ {/* 未开通 */}
+ {!pageInfo ?
+ {getFieldDecorator("site_name", {
+ rules: [{ required: true, message: "请输入站点名称" },
+ {type: 'string', max: 50, min: 1, message: "长度1-50"}],
+ })()}
+
+
+ {getFieldDecorator("identifier", {
+ rules: [{ required: true, message: "请输入站点标识" },
+ {pattern: /^[a-zA-Z0-9]{2,100}$/, message: '长度2-100,只能包含数字和字母'}],
+ })(
+ {
+ setTag(e.target.value);
+ }}
+ placeholder="请输入站点标识"
+ />
+ )}
+
+ http://{current_user.login}.kingchan.cn/{tag}
+
+
+
+ {getFieldDecorator("language_frame", {initialValue: 0})(
+
+ )}
+
+
+
+
+
+ : pageInfo.state ?
+ {/* 已开通 */}
+
+
+ {pageInfo.last_build_at && window.open(pageInfo.url)}} className= {pageInfo.last_build_at && 'theme-btn'}>{pageInfo.site_name}
+ {pageInfo.build_state === null ? '未部署' : pageInfo.build_state ? "已部署" : "部署失败"}
+
+ {pageInfo.last_build_at && window.open(pageInfo.url)}} className= {pageInfo.last_build_at && 'theme-btn'}>{pageInfo.url}
+ {pageInfo.language_frame}
+ {pageInfo.created_at}
+ {pageInfo.last_build_at && {pageInfo.last_build_at}}
+
+ {!isBuild &&
}
+ {isBuild &&
+
部署
+
+ 部署分支:
+ {setBranch(params)}}
+ owner={owner}
+ history={props.history}
+ tagflag={false}
+ branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
+ >
+ 选择您要部署的分支
+
+
+
+
+
+
}
+
:
+ {/* 站点权限被关闭 */}
+ {pageInfo &&
}
+
}
+ {result &&
+
部署结果
+
{result.map(item=>
{item}
)}
+
}
+ }
+ {!isManager &&
+ {/* 非管理员权限 */}
+ {pageInfo && pageInfo.state &&
+ {pageInfo.last_build_at && window.open(pageInfo.url)}} className= {pageInfo.last_build_at && 'theme-btn'}>{pageInfo.site_name}
+ {pageInfo.last_build_at && window.open(pageInfo.url)}} className= {pageInfo.last_build_at && 'theme-btn'}>{pageInfo.url}
+ {pageInfo.language_frame}
+ {pageInfo.created_at}
+ {pageInfo.last_build_at && {pageInfo.last_build_at}}
+ }
+
}
+
+ )
+}
+export default Form.create()(Pages);
\ No newline at end of file
diff --git a/src/forge/Server/pages/index.scss b/src/forge/Server/pages/index.scss
new file mode 100644
index 00000000..ab9cfa4d
--- /dev/null
+++ b/src/forge/Server/pages/index.scss
@@ -0,0 +1,27 @@
+.buildResult{
+ padding: 10px 20px;
+ background-color: rgb(20, 20, 20);
+ color: white;
+}
+.theme-btn{
+ color: $primary-color;
+ cursor: pointer;
+}
+.pageStateBox{
+ border: 1px solid $primary-color;
+ border-radius: 5px;
+ color: $primary-color;
+ padding: 4px 6px 4px;
+ background-color: rgba(70, 106, 255, 0.09);
+ line-height: 12px;
+ &.public{
+ background-color: rgba(58, 213, 115, 0.08);
+ border-color: #25c589;
+ color: #25c589;
+ }
+ &.private{
+ background-color: rgba(230, 126, 34, 0.08);
+ border-color: rgba(230, 126, 34, 1);
+ color: rgba(230, 126, 34, 1);
+ }
+}
\ No newline at end of file
diff --git a/src/forge/Team/Component/UploadImage.jsx b/src/forge/Team/Component/UploadImage.jsx
index d70d6238..eb1d4a68 100644
--- a/src/forge/Team/Component/UploadImage.jsx
+++ b/src/forge/Team/Component/UploadImage.jsx
@@ -7,6 +7,7 @@ const TokenKey = 'autologin_trustie';
function UploadImage({ getImage , url, getImageId, maxSize = 2, action = getUploadActionUrl(), getImageUrl }){
const [ imageUrl , setImageUrl ] = useState(undefined);
+ const [loading, setLoading] = useState(false);
useEffect(()=>{
setImageUrl(url);
},[url])
@@ -33,7 +34,9 @@ function UploadImage({ getImage , url, getImageId, maxSize = 2, action = getUplo
}
// 上传完成后
function handleChange(info){
+ setLoading(true);
if(info && info.file && info.file.status === "done"){
+ setLoading(false);
getImageId && getImageId(info.file.response.id);
getImageUrl && getImageUrl(info.file.response.url)
getBase64(info.file.originFileObj, imageUrl =>
@@ -58,7 +61,7 @@ function UploadImage({ getImage , url, getImageId, maxSize = 2, action = getUplo
:
}
diff --git a/src/forge/css/index.scss b/src/forge/css/index.scss
index 65cd5c35..71576442 100644
--- a/src/forge/css/index.scss
+++ b/src/forge/css/index.scss
@@ -331,19 +331,20 @@ form{
border: 1px solid #DDDDDD !important;
background-color: #fff !important;
}
-.ant-btn.ant-btn-background-ghost{
- border-color: #D0D0D0;
-}
-.ant-btn.ant-btn-background-ghost.ant-btn-primary:hover{
- background-color:$primary-color!important;
- border-color: $primary-color;
- color: #fff;
-}
-.ant-btn.ant-btn-background-ghost.ant-btn-danger:hover{
- background-color: #DF0002!important;
- border-color: #DF0002;
- color: #fff;
-}
+// ghost模式按钮:如有影响,单独修改
+// .ant-btn.ant-btn-background-ghost{
+// border-color: #D0D0D0;
+// }
+// .ant-btn.ant-btn-background-ghost.ant-btn-primary:hover{
+// background-color:$primary-color!important;
+// border-color: $primary-color;
+// color: #fff;
+// }
+// .ant-btn.ant-btn-background-ghost.ant-btn-danger:hover{
+// background-color: #DF0002!important;
+// border-color: #DF0002;
+// color: #fff;
+// }
.newPopUl{
li{
height: 30px;
diff --git a/src/forge/users/Material/Index.jsx b/src/forge/users/Material/Index.jsx
index 56f6799b..c1503684 100644
--- a/src/forge/users/Material/Index.jsx
+++ b/src/forge/users/Material/Index.jsx
@@ -35,7 +35,7 @@ function Index(props){
break;
case '/settings/verification':
setType('4');
- documentTitle = "身份认证";
+ documentTitle = "实名认证";
break;
default:
setType('2');
@@ -55,7 +55,7 @@ function Index(props){
{props.history.push('/settings/phone')}}>手机号管理
{props.history.push('/settings/emails')}}>邮箱管理
{props.history.push('/settings/password')}}>密码管理
- {/* {props.history.push('/settings/verification')}}>身份认证 */}
+ {props.history.push('/settings/verification')}}>实名认证
{props.history.push('/settings/cancel')}}>账号注销
}
diff --git a/src/forge/users/Material/verification.jsx b/src/forge/users/Material/verification.jsx
index 2fb68414..cd6fdd1f 100644
--- a/src/forge/users/Material/verification.jsx
+++ b/src/forge/users/Material/verification.jsx
@@ -9,7 +9,7 @@ import { getImageUrl } from '../../../common/UrlTool';
export default Form.create()(
forwardRef((props)=>{
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
- const { resetUserInfo , current_user } = props;
+ const { current_user } = props;
const [loading, setLoading] = useState(false);
const [data, setData] = useState(undefined);
const [reload, setReload] = useState(undefined);
@@ -18,7 +18,7 @@ export default Form.create()(
if(current_user && current_user.login){
setLoading(true);
// 获取用户身份认证信息
- axios.get(`http://ng.learnerhub.net/api/identity_verifications.json`).then(res=>{
+ axios.get(`/identity_verifications.json`).then(res=>{
setLoading(false);
if(res && res.status === 200){
if(res.data && res.data.status === 0){
@@ -38,7 +38,7 @@ export default Form.create()(
validateFields((error, values) => {
if (!error) {
if(data){
- axios.put(`http://ng.learnerhub.net/api/identity_verifications/${data.id}.json`, values).then(res => {
+ axios.put(`/identity_verifications/${data.id}.json`, values).then(res => {
if(res && res.status === 200){
message.success("提交成功");
setReload(Math.random());
@@ -46,7 +46,7 @@ export default Form.create()(
}).catch((error) => {});
}else{
// 新增
- axios.post(`http://ng.learnerhub.net/api/identity_verifications.json`, values).then(res=>{
+ axios.post(`/identity_verifications.json`, values).then(res=>{
if(res && res.status === 200){
message.success("提交成功");
setReload(Math.random());
@@ -67,15 +67,16 @@ export default Form.create()(
)}
{data.state === "已拒绝" &&
- 您提交的身份信息未提供,原因:{data.description || "无,如有需要请联系平台管理员"}
+ 您提交的身份信息未审核通过,原因:{data.description || "无,如有需要请联系平台管理员"}
}
- {data.state === "已通过" &&
}
+ {data.state === "已通过" &&
}
)}
{getFieldDecorator("name", {
- rules: [{ required: true, message: "请输入真实姓名" }],
+ rules: [{ required: true, message: "请输入真实姓名" },
+ {type: 'string', max: 50, min: 1, message: "长度1-50"}],
})(
)}
-
+
{getFieldDecorator("number", {
rules: [
{ required: true, message: "请输入大陆身份证号码" },
diff --git a/src/modules/tpm/challengesnew/tpm-md-editor.js b/src/modules/tpm/challengesnew/tpm-md-editor.js
index 5d147a27..6b835f37 100644
--- a/src/modules/tpm/challengesnew/tpm-md-editor.js
+++ b/src/modules/tpm/challengesnew/tpm-md-editor.js
@@ -9,7 +9,8 @@ import 'codemirror/lib/codemirror.css';
import './css/newquestion.css';
const $ = window.$
-const mdIcons = ["bold", "italic", "del", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "inline-latex", "latex", '|', "image", "table", '|', "line-break", "watch", "clear","fullscreen"];
+const mdIcons = ["bold", "italic", "del", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "image", "table", '|', "line-break", "watch", "clear","fullscreen"];
+const mdIconsHasLatex = ["bold", "italic", "del", "|", "list-ul", "list-ol", "|", "code", "code-block", "link", "|", "inline-latex", "latex", '|', "image", "table", '|', "line-break", "watch", "clear","fullscreen"];
const NULL_CH = '▁';
@@ -74,7 +75,7 @@ function md_elocalStorage(editor, mdu, id) {
return tid
}
-export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch=true, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , isQuoteIssue = false , changeAtWhoLoginList, owner, projectsId , isFocus = true}) => {
+export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch=true, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , isQuoteIssue = false , changeAtWhoLoginList, owner, projectsId , isFocus = true, showLatexButton = true}) => {
const editorEl = useRef();
const resizeBarEl = useRef();
@@ -353,7 +354,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "JPG", "JPEG", "GIF", "PNG", "BMP", "WEBP"],
imageUploadURL: getUploadActionUrl(),
toolbarIcons: function () {
- return showNullButton ? [...mdIcons, 'null-button'] : mdIcons
+ return showLatexButton ? mdIconsHasLatex : mdIcons
},
toolbarIconsClass: {
"line-break": "fa-minus",