会员创建/编辑新闻以及文章

This commit is contained in:
谢思 2023-09-21 09:33:48 +08:00
parent cf4f5be9ed
commit 7cb34610a4
14 changed files with 1152 additions and 34 deletions

372
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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 (
<div style={editorBoxClass}>
<Spin spinning={loading} tip="上传中,请耐心等待">
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode="default"
style={{ borderBottom: '1px solid #ccc' }}
/>
<Editor
defaultConfig={editorConfig}
value={value}
onCreated={setEditor}
onChange={(editor) => setValue && setValue(editor.getHtml())}
mode="default"
style={{ height: '500px', overflowY: 'hidden' }}
/>
</Spin>
</div>
);
}
export default MyEditor;

View File

@ -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 = (
<Menu>
<Menu.Item>
<a onClick={()=>{addNew("richEditor")}}>富文本编辑器</a>
</Menu.Item>
<Menu.Item>
<a onClick={()=>{addNew("mdEditor")}}>MD编辑器</a>
</Menu.Item>
</Menu>
);
useEffect(()=>{
@ -34,7 +45,7 @@ function Main(props){
getMainList();
} else {
getCateList();
}
}
getHotList();
}
},[id])
@ -45,6 +56,14 @@ function Main(props){
}
}, [newCateId])
function addNew(type){
if(role && role.role === "Manager"){
window.open(role.docManageUrl);
}else{
history.push(`/zone/${deptId}/news/add?type=${type}`)
}
}
function getMainList(){
getNewsAllList(id).then(result=>{
if(result){
@ -109,7 +128,17 @@ function Main(props){
<div>
<div className="main_content">
<div className="boxmain">
<p className="in_title">{ tempConfig[temp].mainTitle }</p>
<div className='titleButBox'>
<p className="in_title">{tempConfig[temp].mainTitle}</p>
{role && role.role !== "None" && <div className='createButs'>
{role.role === "Member" && <Button type="primary" ghost className='mr20'>
<Link to={`/zone/${deptId}/news/self`}>我的文章</Link>
</Button>}
<Dropdown overlay={menu}>
<Button icon='plus' type="primary" ghost>新建</Button>
</Dropdown>
</div>}
</div>
{
mainList && mainList.length>0 &&
(

View File

@ -0,0 +1,172 @@
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 === "<p><br></p>"
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(
<div className='boxmain pt30 newsCreateBox pb100'>
<Breadcrumb separator=">">
<Breadcrumb.Item href={`/zone/${deptId}/news`}>{tempConfig[temp].mainTitle}</Breadcrumb.Item>
<Breadcrumb.Item>{isEdit ? '编辑' : '新建'}文章</Breadcrumb.Item>
</Breadcrumb>
<div className='formBox'>
<Form {...layout} onSubmit={submit}>
<Form.Item label="标题">
{getFieldDecorator("name", {
rules:[{ required:true,message:"请输入文章标题!" }]
})(
<Input placeholder="请输入文章标题" maxLength={ 200 } width="220px"/>
)}
</Form.Item>
<Form.Item label="概览">
{getFieldDecorator("summary", {
rules:[{ required:true,message:"请输入概览!" }]
})(
<Input.TextArea placeholder="请输入概览" maxLength={ 200 } width="220px"/>
)}
</Form.Item>
<Form.Item label="栏目">
{getFieldDecorator("dirId", {
rules:[{ required:true,message:"请选择文章所属栏目!" }]
})(
<Select placeholder="请选择文章所属栏目">
{dirList && dirList.map(item=>{
return <Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
})}
</Select>
)}
</Form.Item>
<Form.Item label="内容" wrapperCol={{span: 21}}>
{getFieldDecorator("content",{
rules:[{required:true,message:"请输入内容!"}],
})(
type === "richEditor" ? <RichEditor uploadUrl={`${httpUrl}/file/common/upload`} videoUploadUrl={`${httpUrl}/file/common/upload?type=cms`} setValue={(value)=>{setFieldsValue({"content": value})}}/> : <MdEditor
placeholder={"请输入详细介绍"}
height={500}
mdID={"order-new-description"}
initValue={value}
onChange={(value)=>{setFieldsValue({"content": value})}}
imageExpand={false}
></MdEditor>
)}
</Form.Item>
<Form.Item label="首图" extra="建议图片比例宽为32上传jpg、jpeg、webp、png、svg、gif、bmp格式的图片">
<UploadImage maxSize={ 5 } getImageUrl={ (url) => setImageUrl(url) } url={ imageUrl ? imageUrl : undefined} action={ getZoneUrl(`/api/cms/common/upload`) } />
</Form.Item>
<Form.Item wrapperCol={{ offset: 2 }}>
<Button className='mr20' onClick={()=>{history.go(-1)}}>取消</Button>
<Button type="primary" htmlType="submit" loading={loading}>提交</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
export default Form.create()(NewsCreate);

View File

@ -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(()=>{
@ -140,7 +140,7 @@ function SelfList(props){
<span><i className="iconfont icon-a-31shijian mr5 font-15"></i>{moment(i.createTime).format("YYYY/MM/DD")}</span>
</span>
<span className="s-info-right">
<a href="" style={{color:"#466aff"}}><i className="iconfont icon-a-bianji12 mr5 font-14"></i>编辑</a>
<a href={`/zone/${deptId}/${source ? 'source' : 'news'}/${i.id}/edit`} style={{color:"#466aff"}}><i className="iconfont icon-a-bianji12 mr5 font-14"></i>编辑</a>
<a style={{color:"#d81017",marginLeft:"25px"}}onClick={()=>{setVisible(true);setDeleId(i.id)}}><i className="iconfont icon-fuzhi-shanchu mr5 font-14"></i>删除</a>
</span>
</div>

View File

@ -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(
<div className={`${temp}_source_box`}>
<div className="source_h">
<p className="in_title">资源发布</p>
<div style={{marginTop:"30px",textAlign:"center"}}>
<Search
<div style={{marginTop:"30px",textAlign:"center"}} className='titleButBox'>
<Search
placeholder="请输入资源名称"
onSearch={onSourceSearch}
style={{width:'645px',borderColor:"#fff",boxShadow:"0px 0px 10px rgba(61, 85, 183, 0.1)"}}
@ -84,6 +91,12 @@ function Source(props){
allowClear
enterButton={temp === "zone" ? <span><i className="iconfont icon-sousuo5 font-15"/>搜索</span> :undefined}
/>
{role && role.role !== "None" && <div className='createButs'>
{role.role === "Member" && <Button size='large' type="primary" ghost className='mr20'>
<Link to={`/zone/${deptId}/source/self`}>我的资源</Link>
</Button>}
<Button size='large' icon='plus' type="primary" ghost onClick={addSource}>新建</Button>
</div>}
</div>
</div>
<div className="sources">

View File

@ -0,0 +1,233 @@
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(
<div className='boxmain pt30 newsCreateBox pb100 sourceCreateBox'>
<Breadcrumb separator=">">
<Breadcrumb.Item><Link className="primaryColor" to={`/zone/${deptId}/source`}>资源列表</Link></Breadcrumb.Item>
<Breadcrumb.Item>{isEdit ? '编辑' : '新建'}资源</Breadcrumb.Item>
</Breadcrumb>
<div className='formBox'>
<Form {...layout} onSubmit={submit}>
<Form.Item label="资源名称">
{getFieldDecorator("name", {
rules:[{ required:true,message:"请输入资源名称!" }]
})(
<Input placeholder="请输入资源名称" maxLength={ 200 } width="220px"/>
)}
</Form.Item>
<Form.Item label="资源领域">
{getFieldDecorator("domainId", {
rules:[{ required:true,message:"请选择资源领域!" }]
})(
<Select placeholder="请选择资源领域">
{zoneList && zoneList.map(item =>{
return <Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
})}
</Select>
)}
</Form.Item>
<Form.Item label="资源简介">
{getFieldDecorator("summary", {
rules:[{ required:true,message:"请输入资源简介!" }]
})(
<Input.TextArea placeholder="请输入资源简介" maxLength={ 200 } width="220px"/>
)}
</Form.Item>
<Form.Item label="资源附件">
{getFieldDecorator("fileList", {
rules:[{ required:true,message:"请上传资源附件!" }]
})(
<Upload action={getZoneUrl(`/api/file/common/upload?type=resource`)} showUploadList={false} beforeUpload={beforeUpload} onChange={onChange} withCredentials={true}>
<Button>
<Icon type="upload" />单击上传
</Button>
</Upload>
)}
</Form.Item>
{/* 附件展示 */}
<div className="sourceFilesBox">
{files && files.map((item, index)=>{
const {uid, status, response, name, zoneResourceType} = item;
return <div key={index} className="sourseFileItem mb15">
{status === "uploading" ? <Icon type="loading" className='mr10'/> : <Icon type="file" className='mr10'/>}
<span className="fileName task-hide">{name}</span>
<span className='mr20 ml20' style={{width: '100px'}}>{response && response.fileSize}</span>
<span className='mr50'>{zoneResourceType && zoneResourceType.name}</span>
<Icon type="delete" onClick={()=>{deleteFile(uid)}}/>
</div>
})}
</div>
<Form.Item wrapperCol={{ offset: 2 }}>
<Button className='mr20' onClick={()=>{history.go(-1)}}>取消</Button>
<Button type="primary" htmlType="submit" loading={loadingBut}>提交</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
export default Form.create()(SourceCreate);

View File

@ -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
});
}

View File

@ -7,7 +7,6 @@ function beforeFetch(actionUrl){
}
const service = axios.create({
headers:{Authorization:"a57ec217a1963611f9a0ff591b305dc3d5b3ba1f"},
baseURL: actionUrl,
timeout: 1800000, // 请求超时时间
});

View File

@ -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';
@ -21,6 +21,10 @@ 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 +68,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 +89,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,6 +125,7 @@ function Index(props){
setId(data.id);
if(data.id){
getAdminUrl(data.id);
getRole(data.id)
}
}
}).catch(console.error())
@ -129,6 +140,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(
<div className="information_main">
{ (!sourcedetail && deptId!=="apply") && (id ? <PublicBanner {...props} data={data} temp={ temp } adminUrl={adminUrl}/> : <div style={{ width: '100%', height: '450px' }}></div>)}
@ -139,10 +159,22 @@ function Index(props){
<SourceSelfList {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
<Route
path="/zone/:deptId/news/add"
render={(p) => (
<NewsCreate {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>
<Route
path="/zone/:deptId/news/:id/edit"
render={(p) => (
<NewsCreate {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>
<Route
path="/zone/:deptId/news/:cateId"
render={(p) => (
<Main {...props} {...p} id={id} temp={ temp }/>
<Main {...props} {...p} id={id} temp={ temp } role={role}/>
)}
></Route>
<Route
@ -157,6 +189,18 @@ function Index(props){
<SourceSelfList {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
<Route
path="/zone/:deptId/source/add"
render={(p) => (
<SourceCreate {...props} {...p} id={id} temp={ temp } data={data}/>
)}
></Route>
<Route
path="/zone/:deptId/source/:sourceid/edit"
render={(p) => (
<SourceCreate {...props} {...p} id={id} temp={ temp }/>
)}
></Route>
<Route
path="/zone/:deptId/source/:sourceid"
render={(p) => (
@ -166,7 +210,7 @@ function Index(props){
<Route
path="/zone/:deptId/source"
render={(p) => (
<Source {...props} {...p} id={id} temp={ temp }/>
<Source {...props} {...p} id={id} temp={ temp } role={role}/>
)}
></Route>
<Route
@ -184,7 +228,7 @@ function Index(props){
<Route
path="/zone/:deptId/news"
render={(p) => (
<Main {...props} {...p} id={id} temp={ temp }/>
<Main {...props} {...p} id={id} temp={ temp } role={role}/>
)}
></Route>
{data && data.helperShow === 1 && <Route

View File

@ -1521,6 +1521,47 @@
}
}
}
// 新增文章/资源
.titleButBox{
width: 1200px;
margin: 0 auto;
position: relative;
.createButs{
position: absolute;
right: 0;
top: 0;
button{
border-color: var(--primary-color);
color: var(--primary-color);
&:hover{
border-color: var(--light-color);
color: var(--light-color);
}
}
}
}
// 新增文章
.newsCreateBox{
.formBox{
background-color: #fff;
border-radius: 4px;
padding: 30px 35px 50px;
}
}
// 新增资源
.sourceCreateBox{
.sourceFilesBox{
margin-left: 93px;
}
.sourseFileItem{
display: flex;
align-items: center;
}
.fileName{
max-width: 400px;
display: inline-block;
}
}
.primaryColor{
color: var(--primary-color)!important;
}

View File

@ -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;

View File

@ -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",