From 03878eec5a861f21ba247f1c81d1e8238c26ca65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sun, 18 Jun 2023 10:02:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker_env/web/Dockerfile | 2 +- web/src/components/file-uploader/index.js | 32 + .../file-uploader/lib/cropper-uploader.vue | 377 ++++++++++ .../file-uploader/lib/cropper/index.vue | 420 +++++++++++ .../file-uploader/lib/cropper/vue-cropper.js | 367 ++++++++++ .../file-uploader/lib/file-uploader.vue | 666 ++++++++++++++++++ .../file-uploader/lib/files-format.vue | 96 +++ .../file-uploader/lib/images-format.vue | 133 ++++ .../file-uploader/lib/loading-spin.svg | 6 + .../selector-table/selector-table.vue | 22 +- 10 files changed, 2114 insertions(+), 7 deletions(-) create mode 100644 web/src/components/file-uploader/index.js create mode 100644 web/src/components/file-uploader/lib/cropper-uploader.vue create mode 100644 web/src/components/file-uploader/lib/cropper/index.vue create mode 100644 web/src/components/file-uploader/lib/cropper/vue-cropper.js create mode 100644 web/src/components/file-uploader/lib/file-uploader.vue create mode 100644 web/src/components/file-uploader/lib/files-format.vue create mode 100644 web/src/components/file-uploader/lib/images-format.vue create mode 100644 web/src/components/file-uploader/lib/loading-spin.svg diff --git a/docker_env/web/Dockerfile b/docker_env/web/Dockerfile index dfa928a..74b0e8b 100644 --- a/docker_env/web/Dockerfile +++ b/docker_env/web/Dockerfile @@ -4,6 +4,6 @@ COPY web/. . RUN npm install --registry=https://registry.npm.taobao.org RUN npm run build -FROM nginx:alpine +FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/nginx:alpine COPY ./docker_env/nginx/my.conf /etc/nginx/conf.d/my.conf COPY --from=0 /web/dist /usr/share/nginx/html diff --git a/web/src/components/file-uploader/index.js b/web/src/components/file-uploader/index.js new file mode 100644 index 0000000..f0de3e6 --- /dev/null +++ b/web/src/components/file-uploader/index.js @@ -0,0 +1,32 @@ +import D2pImagesFormat from './lib/images-format' +import D2pFilesFormat from './lib/files-format' +import 'cropperjs/dist/cropper.css' +import D2pUploader from 'd2p-extends/src/uploader' + +function install (Vue, options) { + Vue.component('d2p-file-uploader', () => import('./lib/file-uploader')) + Vue.component('d2p-images-format', D2pImagesFormat) + Vue.component('d2p-cropper-uploader', () => import('./lib/cropper-uploader')) + Vue.component('d2p-cropper', () => import('./lib/cropper')) + Vue.component('d2p-files-format', D2pFilesFormat) + + if (options != null) { + Vue.use(D2pUploader, options) + } +} + +const createAllUploadedValidator = (getFormComponentRef) => { + return (rule, value, callback) => { + const ref = getFormComponentRef(rule.fullField) + if (ref && ref.isHasUploadingItem()) { + callback(new Error('还有未上传完成的文件')) + return + } + callback() + } +} + +export default { + install, + createAllUploadedValidator +} diff --git a/web/src/components/file-uploader/lib/cropper-uploader.vue b/web/src/components/file-uploader/lib/cropper-uploader.vue new file mode 100644 index 0000000..43320dd --- /dev/null +++ b/web/src/components/file-uploader/lib/cropper-uploader.vue @@ -0,0 +1,377 @@ + + + + + diff --git a/web/src/components/file-uploader/lib/cropper/index.vue b/web/src/components/file-uploader/lib/cropper/index.vue new file mode 100644 index 0000000..58adcdc --- /dev/null +++ b/web/src/components/file-uploader/lib/cropper/index.vue @@ -0,0 +1,420 @@ + + + + + diff --git a/web/src/components/file-uploader/lib/cropper/vue-cropper.js b/web/src/components/file-uploader/lib/cropper/vue-cropper.js new file mode 100644 index 0000000..e57a3c8 --- /dev/null +++ b/web/src/components/file-uploader/lib/cropper/vue-cropper.js @@ -0,0 +1,367 @@ +import Cropper from 'cropperjs' + +const previewPropType = typeof window === 'undefined' + ? [String, Array] + : [String, Array, Element, NodeList] + +export default { + render (h) { + return h('div', { style: this.containerStyle }, [ + h('img', { + ref: 'img', + attrs: { + src: this.src, + alt: this.alt || 'image', + style: 'max-width: 100%' + }, + style: this.imgStyle + }) + ]) + }, + props: { + // Library props + containerStyle: Object, + src: { + type: String, + default: '' + }, + alt: String, + imgStyle: Object, + + // CropperJS props + viewMode: Number, + dragMode: String, + initialAspectRatio: Number, + aspectRatio: Number, + data: Object, + preview: previewPropType, + responsive: { + type: Boolean, + default: true + }, + restore: { + type: Boolean, + default: true + }, + checkCrossOrigin: { + type: Boolean, + default: true + }, + checkOrientation: { + type: Boolean, + default: true + }, + modal: { + type: Boolean, + default: true + }, + guides: { + type: Boolean, + default: true + }, + center: { + type: Boolean, + default: true + }, + highlight: { + type: Boolean, + default: true + }, + background: { + type: Boolean, + default: true + }, + autoCrop: { + type: Boolean, + default: true + }, + autoCropArea: Number, + movable: { + type: Boolean, + default: true + }, + rotatable: { + type: Boolean, + default: true + }, + scalable: { + type: Boolean, + default: true + }, + zoomable: { + type: Boolean, + default: true + }, + zoomOnTouch: { + type: Boolean, + default: true + }, + zoomOnWheel: { + type: Boolean, + default: true + }, + wheelZoomRatio: Number, + cropBoxMovable: { + type: Boolean, + default: true + }, + cropBoxResizable: { + type: Boolean, + default: true + }, + toggleDragModeOnDblclick: { + type: Boolean, + default: true + }, + + // Size limitation + minCanvasWidth: Number, + minCanvasHeight: Number, + minCropBoxWidth: Number, + minCropBoxHeight: Number, + minContainerWidth: Number, + minContainerHeight: Number, + + // callbacks + ready: Function, + cropstart: Function, + cropmove: Function, + cropend: Function, + crop: Function, + zoom: Function + }, + mounted () { + const { containerStyle, src, alt, imgStyle, ...data } = this.$options.props + const props = {} + + for (const key in data) { + if (this[key] !== undefined) { + props[key] = this[key] + } + } + + this.cropper = new Cropper(this.$refs.img, props) + }, + methods: { + // Reset the image and crop box to their initial states + reset () { + return this.cropper.reset() + }, + + // Clear the crop box + clear () { + return this.cropper.clear() + }, + + // Init crop box manually + initCrop () { + return this.cropper.crop() + }, + + /** + * Replace the image's src and rebuild the cropper + * @param {string} url - The new URL. + * @param {boolean} [onlyColorChanged] - Indicate if the new image only changed color. + * @returns {Object} this + */ + replace (url, onlyColorChanged = false) { + return this.cropper.replace(url, onlyColorChanged) + }, + + // Enable (unfreeze) the cropper + enable () { + return this.cropper.enable() + }, + + // Disable (freeze) the cropper + disable () { + return this.cropper.disable() + }, + + // Destroy the cropper and remove the instance from the image + destroy () { + return this.cropper.destroy() + }, + + /** + * Move the canvas with relative offsets + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} offsetY - The relative offset distance on the y-axis. + * @returns {Object} this + */ + move (offsetX, offsetY) { + return this.cropper.move(offsetX, offsetY) + }, + + /** + * Move the canvas to an absolute point + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Object} this + */ + moveTo (x, y = x) { + return this.cropper.moveTo(x, y) + }, + + /** + * Zoom the canvas with a relative ratio + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this + */ + relativeZoom (ratio, _originalEvent) { + return this.cropper.zoom(ratio, _originalEvent) + }, + + /** + * Zoom the canvas to an absolute ratio + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this + */ + zoomTo (ratio, _originalEvent) { + return this.cropper.zoomTo(ratio, _originalEvent) + }, + + /** + * Rotate the canvas with a relative degree + * @param {number} degree - The rotate degree. + * @returns {Object} this + */ + rotate (degree) { + return this.cropper.rotate(degree) + }, + + /** + * Rotate the canvas to an absolute degree + * @param {number} degree - The rotate degree. + * @returns {Object} this + */ + rotateTo (degree) { + return this.cropper.rotateTo(degree) + }, + + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Object} this + */ + scaleX (scaleX) { + return this.cropper.scaleX(scaleX) + }, + + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Object} this + */ + scaleY (scaleY) { + return this.cropper.scaleY(scaleY) + }, + + /** + * Scale the image + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Object} this + */ + scale (scaleX, scaleY = scaleX) { + return this.cropper.scale(scaleX, scaleY) + }, + + /** + * Get the cropped area position and size data (base on the original image) + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. + */ + getData (rounded = false) { + return this.cropper.getData(rounded) + }, + + /** + * Set the cropped area position and size with new data + * @param {Object} data - The new data. + * @returns {Object} this + */ + setData (data) { + return this.cropper.setData(data) + }, + + /** + * Get the container size data. + * @returns {Object} The result container data. + */ + getContainerData () { + return this.cropper.getContainerData() + }, + + /** + * Get the image position and size data. + * @returns {Object} The result image data. + */ + getImageData () { + return this.cropper.getImageData() + }, + + /** + * Get the canvas position and size data. + * @returns {Object} The result canvas data. + */ + getCanvasData () { + return this.cropper.getCanvasData() + }, + + /** + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Object} this + */ + setCanvasData (data) { + return this.cropper.setCanvasData(data) + }, + + /** + * Get the crop box position and size data. + * @returns {Object} The result crop box data. + */ + getCropBoxData () { + return this.cropper.getCropBoxData() + }, + + /** + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Object} this + */ + setCropBoxData (data) { + return this.cropper.setCropBoxData(data) + }, + + /** + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. + */ + getCroppedCanvas (options = {}) { + return this.cropper.getCroppedCanvas(options) + }, + + /** + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Object} this + */ + setAspectRatio (aspectRatio) { + return this.cropper.setAspectRatio(aspectRatio) + }, + + /** + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Object} this + */ + setDragMode (mode) { + return this.cropper.setDragMode(mode) + } + } +} diff --git a/web/src/components/file-uploader/lib/file-uploader.vue b/web/src/components/file-uploader/lib/file-uploader.vue new file mode 100644 index 0000000..7a0c5ca --- /dev/null +++ b/web/src/components/file-uploader/lib/file-uploader.vue @@ -0,0 +1,666 @@ + + + + diff --git a/web/src/components/file-uploader/lib/files-format.vue b/web/src/components/file-uploader/lib/files-format.vue new file mode 100644 index 0000000..7fc52c6 --- /dev/null +++ b/web/src/components/file-uploader/lib/files-format.vue @@ -0,0 +1,96 @@ + + + + diff --git a/web/src/components/file-uploader/lib/images-format.vue b/web/src/components/file-uploader/lib/images-format.vue new file mode 100644 index 0000000..8e4b4d2 --- /dev/null +++ b/web/src/components/file-uploader/lib/images-format.vue @@ -0,0 +1,133 @@ + + + + diff --git a/web/src/components/file-uploader/lib/loading-spin.svg b/web/src/components/file-uploader/lib/loading-spin.svg new file mode 100644 index 0000000..4dbb3ac --- /dev/null +++ b/web/src/components/file-uploader/lib/loading-spin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/src/components/selector-table/selector-table.vue b/web/src/components/selector-table/selector-table.vue index d76c824..e213b59 100644 --- a/web/src/components/selector-table/selector-table.vue +++ b/web/src/components/selector-table/selector-table.vue @@ -2,7 +2,7 @@
@@ -16,7 +16,7 @@ size="mini" border :row-key="dict.value" - style="width: 400px" + style="width: 600px" max-height="200" height="200" :highlight-current-row="!_elProps.tableConfig.multiple" @@ -25,8 +25,10 @@ > - + + + { + queryList.push(res.prop) + }) + params.query = `{${Array.from(new Set(queryList)).join(',')}}` return request({ url: url, params: params, @@ -241,10 +247,14 @@ export default { if (that.dict.params) { dictParams = { ...that.dict.params } } + const queryList = ['id', label, value] + this._elProps.tableConfig.columns.map(res => { + queryList.push(res.prop) + }) const params = { page: that.pageConfig.page, limit: that.pageConfig.limit, - query: `{${label},${value}}` + query: `{${Array.from(new Set(queryList)).join(',')}}` } if (that.search) { params.search = that.search