From 1969ccdad1e5135a4d6fba46826dc916a9e40a42 Mon Sep 17 00:00:00 2001 From: haoxuan <haoxuan> Date: 星期二, 12 九月 2023 15:08:17 +0800 Subject: [PATCH] 应用中心 2023-9-12 --- src/pages/ai/FileUpload/uploader.vue | 189 + src/pages/ai/FileUpload/common/mixins.js | 14 src/pages/ai/FileUpload/file.vue | 469 +++ src/pages/desktop/index/components/ToolsEntry.vue | 2 src/pages/ai/FileUpload/common/uploader-simple.js | 1612 +++++++++++++ src/pages/ai/FileUpload/unsupport.vue | 30 src/pages/ai/FileUpload/list.vue | 43 public/apps.json | 27 src/pages/ai/FileUpload/index.vue | 306 ++ src/pages/ai/FileUpload/common/utils.js | 28 src/pages/ai/FileUpload/files.vue | 42 src/pages/ai/index/App.vue | 3180 ++++++++----------------- src/pages/ai/index/detail.vue | 1117 +++++++++ /dev/null | 0 src/pages/ai/FileUpload/btn.vue | 69 src/pages/ai/FileUpload/drop.vue | 64 public/images/app-mid/knowledge.png | 0 src/pages/ai/FileUpload/common/file-events.js | 3 src/pages/ai/index/api.ts | 8 19 files changed, 5,074 insertions(+), 2,129 deletions(-) diff --git a/public/apps.json b/public/apps.json index c35a2d7..276db05 100644 --- a/public/apps.json +++ b/public/apps.json @@ -8,8 +8,8 @@ "type": "2", "url": "/view/ai/", "title": "搴旂敤涓績", - "width": 1243, - "height": 670, + "width": 1036, + "height": 742, "iconBlob": "", "icon": "../../images/app-mid/algorithm-store.png", "version": "1.0.0", @@ -209,6 +209,29 @@ "progressMsg": "" }, { + "id": "fa5674ee-70cf-4e22-8a06-c17429fb777", + "name": "涓撳鐭ヨ瘑搴�", + "package": "knowledge", + "type": "2", + "url": "/view/knowledge/", + "title": "涓撳鐭ヨ瘑搴�", + "width": 1500, + "height": 750, + "iconBlob": "", + "icon": "../../images/app-mid/knowledge.png", + "version": "1.0.0", + "create_time": "2020-10-09 14:00:08", + "create_by": "", + "update_time": "", + "update_by": "", + "isDelete": 0, + "isDefault": false, + "remoteVersion": "", + "installed": true, + "isUpgrade": false, + "progressMsg": "" + }, + { "id": "1e51abbf-a4dd-4cf9-9eee-2149102d6d43", "name": "绯荤粺鐩戞帶", "package": "systemMonitor", diff --git a/public/images/app-mid/knowledge.png b/public/images/app-mid/knowledge.png new file mode 100644 index 0000000..5c188f4 --- /dev/null +++ b/public/images/app-mid/knowledge.png Binary files differ diff --git a/src/pages/ai/FileUpload/btn.vue b/src/pages/ai/FileUpload/btn.vue new file mode 100644 index 0000000..c72b67c --- /dev/null +++ b/src/pages/ai/FileUpload/btn.vue @@ -0,0 +1,69 @@ +<template> + <label class="uploader-btn" ref="btn" v-show="support"> + <slot></slot> + </label> +</template> + +<script> +import { uploaderMixin, supportMixin } from './common/mixins' + +const COMPONENT_NAME = 'uploader-btn' + +export default { + name: COMPONENT_NAME, + mixins: [uploaderMixin, supportMixin], + props: { + directory: { + type: Boolean, + default: false + }, + single: { + type: Boolean, + default: false + }, + attrs: { + type: Object, + default() { + return {} + } + }, + sourceType: { + type: Number, + } + }, + + mounted() { + this.uploader.uploader.assignBrowse(this.$refs.btn, this.directory, this.single, this.attrs) + this.$nextTick(() => { + let props = {accept:''}; + if(this.sourceType == 1){ + props.accept = '.mp4'; + }else if(this.sourceType == 2){ + props.accept = '.jpg,.jpeg,.png'; + }else if(this.sourceType == 3){ + props.accept = '.tar,.tar.gz,.gz'; + } + this.uploader.uploader.assignBrowse(this.$refs.btn, this.directory, this.single, this.attrs) + }) + } +} +</script> + +<style> +.uploader-btn { + display: inline-block; + position: relative; + padding: 4px 8px; + font-size: 100%; + line-height: 1.4; + color: #666; + border: 1px solid #666; + cursor: pointer; + border-radius: 2px; + background: none; + outline: none; +} +.uploader-btn:hover { + /* background-color: rgba(0, 0, 0, 0.08); */ +} +</style> diff --git a/src/pages/ai/FileUpload/common/file-events.js b/src/pages/ai/FileUpload/common/file-events.js new file mode 100644 index 0000000..2aba807 --- /dev/null +++ b/src/pages/ai/FileUpload/common/file-events.js @@ -0,0 +1,3 @@ +const events = ['fileProgress', 'fileSuccess', 'fileComplete', 'fileError'] + +export default events diff --git a/src/pages/ai/FileUpload/common/mixins.js b/src/pages/ai/FileUpload/common/mixins.js new file mode 100644 index 0000000..efab3b0 --- /dev/null +++ b/src/pages/ai/FileUpload/common/mixins.js @@ -0,0 +1,14 @@ +export const uploaderMixin = { + inject: ['uploader'] +} + +export const supportMixin = { + data () { + return { + support: true + } + }, + mounted () { + this.support = this.uploader.uploader.support + } +} diff --git a/src/pages/ai/FileUpload/common/uploader-simple.js b/src/pages/ai/FileUpload/common/uploader-simple.js new file mode 100644 index 0000000..b0a0d16 --- /dev/null +++ b/src/pages/ai/FileUpload/common/uploader-simple.js @@ -0,0 +1,1612 @@ +/*! + * Uploader - Uploader library implements html5 file upload and provides multiple simultaneous, stable, fault tolerant and resumable uploads + * @version v0.5.4 + * @author dolymood <dolymood@gmail.com> + * @link https://github.com/simple-uploader/Uploader + * @license MIT + */ +!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Uploader=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ + var utils = _dereq_('./utils') + + function Chunk (uploader, file, offset) { + utils.defineNonEnumerable(this, 'uploader', uploader) + utils.defineNonEnumerable(this, 'file', file) + utils.defineNonEnumerable(this, 'bytes', null) + this.offset = offset + this.tested = false + this.retries = 0 + this.pendingRetry = false + this.preprocessState = 0 + this.readState = 0 + this.loaded = 0 + this.total = 0 + this.chunkSize = this.uploader.opts.chunkSize + this.startByte = this.offset * this.chunkSize + this.endByte = this.computeEndByte() + this.xhr = null + } + + var STATUS = Chunk.STATUS = { + PENDING: 'pending', + UPLOADING: 'uploading', + READING: 'reading', + SUCCESS: 'success', + ERROR: 'error', + COMPLETE: 'complete', + PROGRESS: 'progress', + RETRY: 'retry' + } + + utils.extend(Chunk.prototype, { + + _event: function (evt, args) { + args = utils.toArray(arguments) + args.unshift(this) + this.file._chunkEvent.apply(this.file, args) + }, + + computeEndByte: function () { + var endByte = Math.min(this.file.size, (this.offset + 1) * this.chunkSize) + if (this.file.size - endByte < this.chunkSize && !this.uploader.opts.forceChunkSize) { + // The last chunk will be bigger than the chunk size, + // but less than 2 * this.chunkSize + endByte = this.file.size + } + return endByte + }, + + getParams: function () { + return { + chunkNumber: this.offset + 1, + chunkSize: this.uploader.opts.chunkSize, + currentChunkSize: this.endByte - this.startByte, + totalSize: this.file.size, + identifier: this.file.uniqueIdentifier, + filename: this.file.name, + relativePath: this.file.relativePath, + totalChunks: this.file.chunks.length + } + }, + + getTarget: function (target, params) { + if (!params.length) { + return target + } + if (target.indexOf('?') < 0) { + target += '?' + } else { + target += '&' + } + return target + params.join('&') + }, + + test: function () { + this.xhr = new XMLHttpRequest() + this.xhr.addEventListener('load', testHandler, false) + this.xhr.addEventListener('error', testHandler, false) + var testMethod = utils.evalOpts(this.uploader.opts.testMethod, this.file, this) + var data = this.prepareXhrRequest(testMethod, true) + this.xhr.send(data) + + var $ = this + function testHandler (event) { + var status = $.status(true) + if (status === STATUS.ERROR) { + $._event(status, $.message()) + $.uploader.uploadNextChunk() + } else if (status === STATUS.SUCCESS) { + $._event(status, $.message()) + $.tested = true + } else if (!$.file.paused) { + // Error might be caused by file pause method + // Chunks does not exist on the server side + $.tested = true + $.send() + } + } + }, + + preprocessFinished: function () { + // Compute the endByte after the preprocess function to allow an + // implementer of preprocess to set the fileObj size + this.endByte = this.computeEndByte() + this.preprocessState = 2 + this.send() + }, + + readFinished: function (bytes) { + this.readState = 2 + this.bytes = bytes + this.send() + }, + + send: function () { + var preprocess = this.uploader.opts.preprocess + var read = this.uploader.opts.readFileFn + if (utils.isFunction(preprocess)) { + switch (this.preprocessState) { + case 0: + this.preprocessState = 1 + preprocess(this) + return + case 1: + return + } + } + switch (this.readState) { + case 0: + this.readState = 1 + read(this.file, this.file.fileType, this.startByte, this.endByte, this) + return + case 1: + return + } + if (this.uploader.opts.testChunks && !this.tested) { + this.test() + return + } + + this.loaded = 0 + this.total = 0 + this.pendingRetry = false + + // Set up request and listen for event + this.xhr = new XMLHttpRequest() + this.xhr.upload.addEventListener('progress', progressHandler, false) + this.xhr.addEventListener('load', doneHandler, false) + this.xhr.addEventListener('error', doneHandler, false) + + var uploadMethod = utils.evalOpts(this.uploader.opts.uploadMethod, this.file, this) + var data = this.prepareXhrRequest(uploadMethod, false, this.uploader.opts.method, this.bytes) + this.xhr.send(data) + + var $ = this + function progressHandler (event) { + if (event.lengthComputable) { + $.loaded = event.loaded + $.total = event.total + } + $._event(STATUS.PROGRESS, event) + } + + function doneHandler (event) { + var msg = $.message() + $.processingResponse = true + $.uploader.opts.processResponse(msg, function (err, res) { + $.processingResponse = false + if (!$.xhr) { + return + } + $.processedState = { + err: err, + res: res + } + var status = $.status() + if (status === STATUS.SUCCESS || status === STATUS.ERROR) { + delete this.data + $._event(status, res) + status === STATUS.ERROR && $.uploader.uploadNextChunk() + } else { + $._event(STATUS.RETRY, res) + $.pendingRetry = true + $.abort() + $.retries++ + var retryInterval = $.uploader.opts.chunkRetryInterval + if (retryInterval !== null) { + setTimeout(function () { + $.send() + }, retryInterval) + } else { + $.send() + } + } + }, $.file, $) + } + }, + + abort: function () { + var xhr = this.xhr + this.xhr = null + this.processingResponse = false + this.processedState = null + if (xhr) { + xhr.abort() + } + }, + + status: function (isTest) { + if (this.readState === 1) { + return STATUS.READING + } else if (this.pendingRetry || this.preprocessState === 1) { + // if pending retry then that's effectively the same as actively uploading, + // there might just be a slight delay before the retry starts + return STATUS.UPLOADING + } else if (!this.xhr) { + return STATUS.PENDING + } else if (this.xhr.readyState < 4 || this.processingResponse) { + // Status is really 'OPENED', 'HEADERS_RECEIVED' + // or 'LOADING' - meaning that stuff is happening + return STATUS.UPLOADING + } else { + var _status + if (this.uploader.opts.successStatuses.indexOf(this.xhr.status) > -1) { + // HTTP 200, perfect + // HTTP 202 Accepted - The request has been accepted for processing, but the processing has not been completed. + _status = STATUS.SUCCESS + } else if (this.uploader.opts.permanentErrors.indexOf(this.xhr.status) > -1 || + !isTest && this.retries >= this.uploader.opts.maxChunkRetries) { + // HTTP 415/500/501, permanent error + _status = STATUS.ERROR + } else { + // this should never happen, but we'll reset and queue a retry + // a likely case for this would be 503 service unavailable + this.abort() + _status = STATUS.PENDING + } + var processedState = this.processedState + if (processedState && processedState.err) { + _status = STATUS.ERROR + } + return _status + } + }, + + message: function () { + return this.xhr ? this.xhr.responseText : '' + }, + + progress: function () { + if (this.pendingRetry) { + return 0 + } + var s = this.status() + if (s === STATUS.SUCCESS || s === STATUS.ERROR) { + return 1 + } else if (s === STATUS.PENDING) { + return 0 + } else { + return this.total > 0 ? this.loaded / this.total : 0 + } + }, + + sizeUploaded: function () { + var size = this.endByte - this.startByte + // can't return only chunk.loaded value, because it is bigger than chunk size + if (this.status() !== STATUS.SUCCESS) { + size = this.progress() * size + } + return size + }, + + prepareXhrRequest: function (method, isTest, paramsMethod, blob) { + // Add data from the query options + var query = utils.evalOpts(this.uploader.opts.query, this.file, this, isTest) + query = utils.extend(this.getParams(), query) + + // processParams + query = this.uploader.opts.processParams(query, this.file, this, isTest) + + var target = utils.evalOpts(this.uploader.opts.target, this.file, this, isTest) + var data = null + if (method === 'GET' || paramsMethod === 'octet') { + // Add data from the query options + var params = [] + utils.each(query, function (v, k) { + params.push([encodeURIComponent(k), encodeURIComponent(v)].join('=')) + }) + target = this.getTarget(target, params) + data = blob || null + } else { + // Add data from the query options + data = new FormData() + utils.each(query, function (v, k) { + data.append(k, v) + }) + if (typeof blob !== 'undefined') { + data.append(this.uploader.opts.fileParameterName, blob, this.file.name) + } + } + + this.xhr.open(method, target, true) + this.xhr.withCredentials = this.uploader.opts.withCredentials + + // Add data from header options + utils.each(utils.evalOpts(this.uploader.opts.headers, this.file, this, isTest), function (v, k) { + this.xhr.setRequestHeader(k, v) + }, this) + + return data + } + + }) + + module.exports = Chunk + + },{"./utils":5}],2:[function(_dereq_,module,exports){ + var each = _dereq_('./utils').each + + var event = { + + _eventData: null, + + on: function (name, func) { + if (!this._eventData) this._eventData = {} + if (!this._eventData[name]) this._eventData[name] = [] + var listened = false + each(this._eventData[name], function (fuc) { + if (fuc === func) { + listened = true + return false + } + }) + if (!listened) { + this._eventData[name].push(func) + } + }, + + off: function (name, func) { + if (!this._eventData) this._eventData = {} + if (!this._eventData[name] || !this._eventData[name].length) return + if (func) { + each(this._eventData[name], function (fuc, i) { + if (fuc === func) { + this._eventData[name].splice(i, 1) + return false + } + }, this) + } else { + this._eventData[name] = [] + } + }, + + trigger: function (name) { + if (!this._eventData) this._eventData = {} + if (!this._eventData[name]) return true + var args = this._eventData[name].slice.call(arguments, 1) + var preventDefault = false + each(this._eventData[name], function (fuc) { + preventDefault = fuc.apply(this, args) === false || preventDefault + }, this) + return !preventDefault + } + } + + module.exports = event + + },{"./utils":5}],3:[function(_dereq_,module,exports){ + var utils = _dereq_('./utils') + var event = _dereq_('./event') + var File = _dereq_('./file') + var Chunk = _dereq_('./chunk') + + var version = '0.5.4' + + var isServer = typeof window === 'undefined' + + // ie10+ + var ie10plus = isServer ? false : window.navigator.msPointerEnabled + var support = (function () { + if (isServer) { + return false + } + var sliceName = 'slice' + var _support = utils.isDefined(window.File) && utils.isDefined(window.Blob) && + utils.isDefined(window.FileList) + var bproto = null + if (_support) { + bproto = window.Blob.prototype + utils.each(['slice', 'webkitSlice', 'mozSlice'], function (n) { + if (bproto[n]) { + sliceName = n + return false + } + }) + _support = !!bproto[sliceName] + } + if (_support) Uploader.sliceName = sliceName + bproto = null + return _support + })() + + var supportDirectory = (function () { + if (isServer) { + return false + } + var input = window.document.createElement('input') + input.type = 'file' + var sd = 'webkitdirectory' in input || 'directory' in input + input = null + return sd + })() + + function Uploader (opts) { + this.support = support + /* istanbul ignore if */ + if (!this.support) { + return + } + this.supportDirectory = supportDirectory + utils.defineNonEnumerable(this, 'filePaths', {}) + this.opts = utils.extend({}, Uploader.defaults, opts || {}) + + this.preventEvent = utils.bind(this._preventEvent, this) + + File.call(this, this) + } + + /** + * Default read function using the webAPI + * + * @function webAPIFileRead(fileObj, fileType, startByte, endByte, chunk) + * + */ + var webAPIFileRead = function (fileObj, fileType, startByte, endByte, chunk) { + chunk.readFinished(fileObj.file[Uploader.sliceName](startByte, endByte, fileType)) + } + + Uploader.version = version + + Uploader.defaults = { + chunkSize: 1024 * 1024, + forceChunkSize: false, + simultaneousUploads: 3, + singleFile: false, + fileParameterName: 'file', + progressCallbacksInterval: 500, + speedSmoothingFactor: 0.1, + query: {}, + headers: {}, + withCredentials: false, + preprocess: null, + method: 'multipart', + testMethod: 'GET', + uploadMethod: 'POST', + prioritizeFirstAndLastChunk: false, + allowDuplicateUploads: false, + target: '/', + testChunks: true, + generateUniqueIdentifier: null, + maxChunkRetries: 0, + chunkRetryInterval: null, + permanentErrors: [404, 415, 500, 501], + successStatuses: [200, 201, 202], + onDropStopPropagation: false, + initFileFn: null, + readFileFn: webAPIFileRead, + checkChunkUploadedByResponse: null, + initialPaused: false, + processResponse: function (response, cb) { + cb(null, response) + }, + processParams: function (params) { + return params + } + } + + Uploader.utils = utils + Uploader.event = event + Uploader.File = File + Uploader.Chunk = Chunk + + // inherit file + Uploader.prototype = utils.extend({}, File.prototype) + // inherit event + utils.extend(Uploader.prototype, event) + utils.extend(Uploader.prototype, { + + constructor: Uploader, + + _trigger: function (name) { + var args = utils.toArray(arguments) + var preventDefault = !this.trigger.apply(this, arguments) + if (name !== 'catchAll') { + args.unshift('catchAll') + preventDefault = !this.trigger.apply(this, args) || preventDefault + } + return !preventDefault + }, + + _triggerAsync: function () { + var args = arguments + utils.nextTick(function () { + this._trigger.apply(this, args) + }, this) + }, + + addFiles: function (files, evt) { + var _files = [] + var oldFileListLen = this.fileList.length + utils.each(files, function (file) { + // Uploading empty file IE10/IE11 hangs indefinitely + // Directories have size `0` and name `.` + // Ignore already added files if opts.allowDuplicateUploads is set to false + if ((!ie10plus || ie10plus && file.size > 0) && !(file.size % 4096 === 0 && (file.name === '.' || file.fileName === '.'))) { + var uniqueIdentifier = this.generateUniqueIdentifier(file) + if (this.opts.allowDuplicateUploads || !this.getFromUniqueIdentifier(uniqueIdentifier)) { + var _file = new File(this, file, this) + _file.uniqueIdentifier = uniqueIdentifier + if (this._trigger('fileAdded', _file, evt)) { + _files.push(_file) + } else { + File.prototype.removeFile.call(this, _file) + } + } + } + }, this) + // get new fileList + var newFileList = this.fileList.slice(oldFileListLen) + if (this._trigger('filesAdded', _files, newFileList, evt)) { + utils.each(_files, function (file) { + if (this.opts.singleFile && this.files.length > 0) { + this.removeFile(this.files[0]) + } + this.files.push(file) + }, this) + this._trigger('filesSubmitted', _files, newFileList, evt) + } else { + utils.each(newFileList, function (file) { + File.prototype.removeFile.call(this, file) + }, this) + } + }, + + addFile: function (file, evt) { + this.addFiles([file], evt) + }, + + cancel: function () { + for (var i = this.fileList.length - 1; i >= 0; i--) { + this.fileList[i].cancel() + } + }, + + removeFile: function (file) { + File.prototype.removeFile.call(this, file) + this._trigger('fileRemoved', file) + }, + + generateUniqueIdentifier: function (file) { + var custom = this.opts.generateUniqueIdentifier + if (utils.isFunction(custom)) { + return custom(file) + } + /* istanbul ignore next */ + // Some confusion in different versions of Firefox + var relativePath = file.relativePath || file.webkitRelativePath || file.fileName || file.name + /* istanbul ignore next */ + return file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, '') + }, + + getFromUniqueIdentifier: function (uniqueIdentifier) { + var ret = false + utils.each(this.files, function (file) { + if (file.uniqueIdentifier === uniqueIdentifier) { + ret = file + return false + } + }) + return ret + }, + + uploadNextChunk: function (preventEvents) { + var found = false + var pendingStatus = Chunk.STATUS.PENDING + var checkChunkUploaded = this.uploader.opts.checkChunkUploadedByResponse + if (this.opts.prioritizeFirstAndLastChunk) { + utils.each(this.files, function (file) { + if (file.paused) { + return + } + if (checkChunkUploaded && !file._firstResponse && file.isUploading()) { + // waiting for current file's first chunk response + return + } + if (file.chunks.length && file.chunks[0].status() === pendingStatus) { + file.chunks[0].send() + found = true + return false + } + if (file.chunks.length > 1 && file.chunks[file.chunks.length - 1].status() === pendingStatus) { + file.chunks[file.chunks.length - 1].send() + found = true + return false + } + }) + if (found) { + return found + } + } + + // Now, simply look for the next, best thing to upload + utils.each(this.files, function (file) { + if (!file.paused) { + if (checkChunkUploaded && !file._firstResponse && file.isUploading()) { + // waiting for current file's first chunk response + return + } + utils.each(file.chunks, function (chunk) { + if (chunk.status() === pendingStatus) { + chunk.send() + found = true + return false + } + }) + } + if (found) { + return false + } + }) + if (found) { + return true + } + + // The are no more outstanding chunks to upload, check is everything is done + var outstanding = false + utils.each(this.files, function (file) { + if (!file.isComplete()) { + outstanding = true + return false + } + }) + // should check files now + // if now files in list + // should not trigger complete event + if (!outstanding && !preventEvents && this.files.length) { + // All chunks have been uploaded, complete + this._triggerAsync('complete') + } + return outstanding + }, + + upload: function (preventEvents) { + // Make sure we don't start too many uploads at once + var ret = this._shouldUploadNext() + if (ret === false) { + return + } + !preventEvents && this._trigger('uploadStart') + var started = false + for (var num = 1; num <= this.opts.simultaneousUploads - ret; num++) { + started = this.uploadNextChunk(!preventEvents) || started + if (!started && preventEvents) { + // completed + break + } + } + if (!started && !preventEvents) { + this._triggerAsync('complete') + } + }, + + /** + * should upload next chunk + * @function + * @returns {Boolean|Number} + */ + _shouldUploadNext: function () { + var num = 0 + var should = true + var simultaneousUploads = this.opts.simultaneousUploads + var uploadingStatus = Chunk.STATUS.UPLOADING + utils.each(this.files, function (file) { + utils.each(file.chunks, function (chunk) { + if (chunk.status() === uploadingStatus) { + num++ + if (num >= simultaneousUploads) { + should = false + return false + } + } + }) + return should + }) + // if should is true then return uploading chunks's length + return should && num + }, + + /** + * Assign a browse action to one or more DOM nodes. + * @function + * @param {Element|Array.<Element>} domNodes + * @param {boolean} isDirectory Pass in true to allow directories to + * @param {boolean} singleFile prevent multi file upload + * @param {Object} attributes set custom attributes: + * http://www.w3.org/TR/html-markup/input.file.html#input.file-attributes + * eg: accept: 'image/*' + * be selected (Chrome only). + */ + assignBrowse: function (domNodes, isDirectory, singleFile, attributes) { + if (typeof domNodes.length === 'undefined') { + domNodes = [domNodes] + } + + utils.each(domNodes, function (domNode) { + var input + if (domNode.tagName === 'INPUT' && domNode.type === 'file') { + input = domNode + } else { + input = document.createElement('input') + input.setAttribute('type', 'file') + // display:none - not working in opera 12 + utils.extend(input.style, { + visibility: 'hidden', + position: 'absolute', + width: '1px', + height: '1px' + }) + // for opera 12 browser, input must be assigned to a document + Array.from(domNode.children).forEach(function(child){ + if(child.type=='file'){ + console.log(child) + domNode.removeChild(child) + } + }) + domNode.appendChild(input) + // https://developer.mozilla.org/en/using_files_from_web_applications) + // event listener is executed two times + // first one - original mouse click event + // second - input.click(), input is inside domNode + domNode.addEventListener('click', function (e) { + if (domNode.tagName.toLowerCase() === 'label') { + return + } + input.click() + }, false) + } + if (!this.opts.singleFile && !singleFile) { + input.setAttribute('multiple', 'multiple') + } + if (isDirectory) { + input.setAttribute('webkitdirectory', 'webkitdirectory') + } + attributes && utils.each(attributes, function (value, key) { + input.setAttribute(key, value) + }) + // When new files are added, simply append them to the overall list + var that = this + input.addEventListener('change', function (e) { + that._trigger(e.type, e) + if (e.target.value) { + that.addFiles(e.target.files, e) + e.target.value = '' + } + }, false) + }, this) + }, + + onDrop: function (evt) { + this._trigger(evt.type, evt) + if (this.opts.onDropStopPropagation) { + evt.stopPropagation() + } + evt.preventDefault() + this._parseDataTransfer(evt.dataTransfer, evt) + }, + + _parseDataTransfer: function (dataTransfer, evt) { + if (dataTransfer.items && dataTransfer.items[0] && + dataTransfer.items[0].webkitGetAsEntry) { + this.webkitReadDataTransfer(dataTransfer, evt) + } else { + this.addFiles(dataTransfer.files, evt) + } + }, + + webkitReadDataTransfer: function (dataTransfer, evt) { + var self = this + var queue = dataTransfer.items.length + var files = [] + utils.each(dataTransfer.items, function (item) { + var entry = item.webkitGetAsEntry() + if (!entry) { + decrement() + return + } + if (entry.isFile) { + // due to a bug in Chrome's File System API impl - #149735 + fileReadSuccess(item.getAsFile(), entry.fullPath) + } else { + readDirectory(entry.createReader()) + } + }) + function readDirectory (reader) { + reader.readEntries(function (entries) { + if (entries.length) { + queue += entries.length + utils.each(entries, function (entry) { + if (entry.isFile) { + var fullPath = entry.fullPath + entry.file(function (file) { + fileReadSuccess(file, fullPath) + }, readError) + } else if (entry.isDirectory) { + readDirectory(entry.createReader()) + } + }) + readDirectory(reader) + } else { + decrement() + } + }, readError) + } + function fileReadSuccess (file, fullPath) { + // relative path should not start with "/" + file.relativePath = fullPath.substring(1) + files.push(file) + decrement() + } + function readError (fileError) { + throw fileError + } + function decrement () { + if (--queue === 0) { + self.addFiles(files, evt) + } + } + }, + + _assignHelper: function (domNodes, handles, remove) { + if (typeof domNodes.length === 'undefined') { + domNodes = [domNodes] + } + var evtMethod = remove ? 'removeEventListener' : 'addEventListener' + utils.each(domNodes, function (domNode) { + utils.each(handles, function (handler, name) { + domNode[evtMethod](name, handler, false) + }, this) + }, this) + }, + + _preventEvent: function (e) { + utils.preventEvent(e) + this._trigger(e.type, e) + }, + + /** + * Assign one or more DOM nodes as a drop target. + * @function + * @param {Element|Array.<Element>} domNodes + */ + assignDrop: function (domNodes) { + this._onDrop = utils.bind(this.onDrop, this) + this._assignHelper(domNodes, { + dragover: this.preventEvent, + dragenter: this.preventEvent, + dragleave: this.preventEvent, + drop: this._onDrop + }) + }, + + /** + * Un-assign drop event from DOM nodes + * @function + * @param domNodes + */ + unAssignDrop: function (domNodes) { + this._assignHelper(domNodes, { + dragover: this.preventEvent, + dragenter: this.preventEvent, + dragleave: this.preventEvent, + drop: this._onDrop + }, true) + this._onDrop = null + } + }) + + module.exports = Uploader + + },{"./chunk":1,"./event":2,"./file":4,"./utils":5}],4:[function(_dereq_,module,exports){ + var utils = _dereq_('./utils') + var Chunk = _dereq_('./chunk') + + function File (uploader, file, parent) { + utils.defineNonEnumerable(this, 'uploader', uploader) + this.isRoot = this.isFolder = uploader === this + utils.defineNonEnumerable(this, 'parent', parent || null) + utils.defineNonEnumerable(this, 'files', []) + utils.defineNonEnumerable(this, 'fileList', []) + utils.defineNonEnumerable(this, 'chunks', []) + utils.defineNonEnumerable(this, '_errorFiles', []) + utils.defineNonEnumerable(this, 'file', null) + this.id = utils.uid() + + if (this.isRoot || !file) { + this.file = null + } else { + if (utils.isString(file)) { + // folder + this.isFolder = true + this.file = null + this.path = file + if (this.parent.path) { + file = file.substr(this.parent.path.length) + } + this.name = file.charAt(file.length - 1) === '/' ? file.substr(0, file.length - 1) : file + } else { + this.file = file + this.fileType = this.file.type + this.name = file.fileName || file.name + this.size = file.size + this.relativePath = file.relativePath || file.webkitRelativePath || this.name + this._parseFile() + } + } + + this.paused = uploader.opts.initialPaused + this.error = false + this.allError = false + this.aborted = false + this.completed = false + this.averageSpeed = 0 + this.currentSpeed = 0 + this._lastProgressCallback = Date.now() + this._prevUploadedSize = 0 + this._prevProgress = 0 + + this.bootstrap() + } + + utils.extend(File.prototype, { + + _parseFile: function () { + var ppaths = parsePaths(this.relativePath) + if (ppaths.length) { + var filePaths = this.uploader.filePaths + utils.each(ppaths, function (path, i) { + var folderFile = filePaths[path] + if (!folderFile) { + folderFile = new File(this.uploader, path, this.parent) + filePaths[path] = folderFile + this._updateParentFileList(folderFile) + } + this.parent = folderFile + folderFile.files.push(this) + if (!ppaths[i + 1]) { + folderFile.fileList.push(this) + } + }, this) + } else { + this._updateParentFileList() + } + }, + + _updateParentFileList: function (file) { + if (!file) { + file = this + } + var p = this.parent + if (p) { + p.fileList.push(file) + } + }, + + _eachAccess: function (eachFn, fileFn) { + if (this.isFolder) { + utils.each(this.files, function (f, i) { + return eachFn.call(this, f, i) + }, this) + return + } + fileFn.call(this, this) + }, + + bootstrap: function () { + if (this.isFolder) return + var opts = this.uploader.opts + if (utils.isFunction(opts.initFileFn)) { + opts.initFileFn.call(this, this) + } + + this.abort(true) + this._resetError() + // Rebuild stack of chunks from file + this._prevProgress = 0 + var round = opts.forceChunkSize ? Math.ceil : Math.floor + var chunks = Math.max(round(this.size / opts.chunkSize), 1) + for (var offset = 0; offset < chunks; offset++) { + this.chunks.push(new Chunk(this.uploader, this, offset)) + } + }, + + _measureSpeed: function () { + var smoothingFactor = this.uploader.opts.speedSmoothingFactor + var timeSpan = Date.now() - this._lastProgressCallback + if (!timeSpan) { + return + } + var uploaded = this.sizeUploaded() + // Prevent negative upload speed after file upload resume + this.currentSpeed = Math.max((uploaded - this._prevUploadedSize) / timeSpan * 1000, 0) + this.averageSpeed = smoothingFactor * this.currentSpeed + (1 - smoothingFactor) * this.averageSpeed + this._prevUploadedSize = uploaded + if (this.parent && this.parent._checkProgress()) { + this.parent._measureSpeed() + } + }, + + _checkProgress: function (file) { + return Date.now() - this._lastProgressCallback >= this.uploader.opts.progressCallbacksInterval + }, + + _chunkEvent: function (chunk, evt, message) { + var uploader = this.uploader + var STATUS = Chunk.STATUS + var that = this + var rootFile = this.getRoot() + var triggerProgress = function () { + that._measureSpeed() + uploader._trigger('fileProgress', rootFile, that, chunk) + that._lastProgressCallback = Date.now() + } + switch (evt) { + case STATUS.PROGRESS: + if (this._checkProgress()) { + triggerProgress() + } + break + case STATUS.ERROR: + this._error() + this.abort(true) + uploader._trigger('fileError', rootFile, this, message, chunk) + break + case STATUS.SUCCESS: + this._updateUploadedChunks(message, chunk) + if (this.error) { + return + } + clearTimeout(this._progeressId) + this._progeressId = 0 + var timeDiff = Date.now() - this._lastProgressCallback + if (timeDiff < uploader.opts.progressCallbacksInterval) { + this._progeressId = setTimeout(triggerProgress, uploader.opts.progressCallbacksInterval - timeDiff) + } + if (this.isComplete()) { + clearTimeout(this._progeressId) + triggerProgress() + this.currentSpeed = 0 + this.averageSpeed = 0 + uploader._trigger('fileSuccess', rootFile, this, message, chunk) + if (rootFile.isComplete()) { + uploader._trigger('fileComplete', rootFile, this) + } + } else if (!this._progeressId) { + triggerProgress() + } + break + case STATUS.RETRY: + uploader._trigger('fileRetry', rootFile, this, chunk) + break + } + }, + + _updateUploadedChunks: function (message, chunk) { + var checkChunkUploaded = this.uploader.opts.checkChunkUploadedByResponse + if (checkChunkUploaded) { + var xhr = chunk.xhr + utils.each(this.chunks, function (_chunk) { + if (!_chunk.tested) { + var uploaded = checkChunkUploaded.call(this, _chunk, message) + if (_chunk === chunk && !uploaded) { + // fix the first chunk xhr status + // treated as success but checkChunkUploaded is false + // so the current chunk should be uploaded again + _chunk.xhr = null + } + if (uploaded) { + // first success and other chunks are uploaded + // then set xhr, so the uploaded chunks + // will be treated as success too + _chunk.xhr = xhr + } + _chunk.tested = true + } + }, this) + if (!this._firstResponse) { + this._firstResponse = true + this.uploader.upload(true) + } else { + this.uploader.uploadNextChunk() + } + } else { + this.uploader.uploadNextChunk() + } + }, + + _error: function () { + this.error = this.allError = true + var parent = this.parent + while (parent && parent !== this.uploader) { + parent._errorFiles.push(this) + parent.error = true + if (parent._errorFiles.length === parent.files.length) { + parent.allError = true + } + parent = parent.parent + } + }, + + _resetError: function () { + this.error = this.allError = false + var parent = this.parent + var index = -1 + while (parent && parent !== this.uploader) { + index = parent._errorFiles.indexOf(this) + parent._errorFiles.splice(index, 1) + parent.allError = false + if (!parent._errorFiles.length) { + parent.error = false + } + parent = parent.parent + } + }, + + isComplete: function () { + if (!this.completed) { + var outstanding = false + this._eachAccess(function (file) { + if (!file.isComplete()) { + outstanding = true + return false + } + }, function () { + var STATUS = Chunk.STATUS + utils.each(this.chunks, function (chunk) { + var status = chunk.status() + if (status === STATUS.PENDING || status === STATUS.UPLOADING || status === STATUS.READING || chunk.preprocessState === 1 || chunk.readState === 1) { + outstanding = true + return false + } + }) + }) + this.completed = !outstanding + } + return this.completed + }, + + isUploading: function () { + var uploading = false + this._eachAccess(function (file) { + if (file.isUploading()) { + uploading = true + return false + } + }, function () { + var uploadingStatus = Chunk.STATUS.UPLOADING + utils.each(this.chunks, function (chunk) { + if (chunk.status() === uploadingStatus) { + uploading = true + return false + } + }) + }) + return uploading + }, + + resume: function () { + this._eachAccess(function (f) { + f.resume() + }, function () { + this.paused = false + this.aborted = false + this.uploader.upload() + }) + this.paused = false + this.aborted = false + }, + + pause: function () { + this._eachAccess(function (f) { + f.pause() + }, function () { + this.paused = true + this.abort() + }) + this.paused = true + }, + + cancel: function () { + this.uploader.removeFile(this) + }, + + retry: function (file) { + var fileRetry = function (file) { + if (file.error) { + file.bootstrap() + } + } + if (file) { + file.bootstrap() + } else { + this._eachAccess(fileRetry, function () { + this.bootstrap() + }) + } + this.uploader.upload() + }, + + abort: function (reset) { + if (this.aborted) { + return + } + this.currentSpeed = 0 + this.averageSpeed = 0 + this.aborted = !reset + var chunks = this.chunks + if (reset) { + this.chunks = [] + } + var uploadingStatus = Chunk.STATUS.UPLOADING + utils.each(chunks, function (c) { + if (c.status() === uploadingStatus) { + c.abort() + this.uploader.uploadNextChunk() + } + }, this) + }, + + progress: function () { + var totalDone = 0 + var totalSize = 0 + var ret = 0 + this._eachAccess(function (file, index) { + totalDone += file.progress() * file.size + totalSize += file.size + if (index === this.files.length - 1) { + ret = totalSize > 0 ? totalDone / totalSize : this.isComplete() ? 1 : 0 + } + }, function () { + if (this.error) { + ret = 1 + return + } + if (this.chunks.length === 1) { + this._prevProgress = Math.max(this._prevProgress, this.chunks[0].progress()) + ret = this._prevProgress + return + } + // Sum up progress across everything + var bytesLoaded = 0 + utils.each(this.chunks, function (c) { + // get chunk progress relative to entire file + bytesLoaded += c.progress() * (c.endByte - c.startByte) + }) + var percent = bytesLoaded / this.size + // We don't want to lose percentages when an upload is paused + this._prevProgress = Math.max(this._prevProgress, percent > 0.9999 ? 1 : percent) + ret = this._prevProgress + }) + return ret + }, + + getSize: function () { + var size = 0 + this._eachAccess(function (file) { + size += file.size + }, function () { + size += this.size + }) + return size + }, + + getFormatSize: function () { + var size = this.getSize() + return utils.formatSize(size) + }, + + getRoot: function () { + if (this.isRoot) { + return this + } + var parent = this.parent + while (parent) { + if (parent.parent === this.uploader) { + // find it + return parent + } + parent = parent.parent + } + return this + }, + + sizeUploaded: function () { + var size = 0 + this._eachAccess(function (file) { + size += file.sizeUploaded() + }, function () { + utils.each(this.chunks, function (chunk) { + size += chunk.sizeUploaded() + }) + }) + return size + }, + + timeRemaining: function () { + var ret = 0 + var sizeDelta = 0 + var averageSpeed = 0 + this._eachAccess(function (file, i) { + if (!file.paused && !file.error) { + sizeDelta += file.size - file.sizeUploaded() + averageSpeed += file.averageSpeed + } + if (i === this.files.length - 1) { + ret = calRet(sizeDelta, averageSpeed) + } + }, function () { + if (this.paused || this.error) { + ret = 0 + return + } + var delta = this.size - this.sizeUploaded() + ret = calRet(delta, this.averageSpeed) + }) + return ret + function calRet (delta, averageSpeed) { + if (delta && !averageSpeed) { + return Number.POSITIVE_INFINITY + } + if (!delta && !averageSpeed) { + return 0 + } + return Math.floor(delta / averageSpeed) + } + }, + + removeFile: function (file) { + if (file.isFolder) { + while (file.files.length) { + var f = file.files[file.files.length - 1] + this._removeFile(f) + } + } + this._removeFile(file) + }, + + _delFilePath: function (file) { + if (file.path && this.filePaths) { + delete this.filePaths[file.path] + } + utils.each(file.fileList, function (file) { + this._delFilePath(file) + }, this) + }, + + _removeFile: function (file) { + if (!file.isFolder) { + utils.each(this.files, function (f, i) { + if (f === file) { + this.files.splice(i, 1) + return false + } + }, this) + file.abort() + var parent = file.parent + var newParent + while (parent && parent !== this) { + newParent = parent.parent + parent._removeFile(file) + parent = newParent + } + } + file.parent === this && utils.each(this.fileList, function (f, i) { + if (f === file) { + this.fileList.splice(i, 1) + return false + } + }, this) + if (!this.isRoot && this.isFolder && !this.files.length) { + this.parent._removeFile(this) + this.uploader._delFilePath(this) + } + file.parent = null + }, + + getType: function () { + if (this.isFolder) { + return 'folder' + } + return this.file.type && this.file.type.split('/')[1] + }, + + getExtension: function () { + if (this.isFolder) { + return '' + } + return this.name.substr((~-this.name.lastIndexOf('.') >>> 0) + 2).toLowerCase() + } + + }) + + module.exports = File + + function parsePaths (path) { + var ret = [] + var paths = path.split('/') + var len = paths.length + var i = 1 + paths.splice(len - 1, 1) + len-- + if (paths.length) { + while (i <= len) { + ret.push(paths.slice(0, i++).join('/') + '/') + } + } + return ret + } + + },{"./chunk":1,"./utils":5}],5:[function(_dereq_,module,exports){ + var oproto = Object.prototype + var aproto = Array.prototype + var serialize = oproto.toString + + var isFunction = function (fn) { + return serialize.call(fn) === '[object Function]' + } + + var isArray = Array.isArray || /* istanbul ignore next */ function (ary) { + return serialize.call(ary) === '[object Array]' + } + + var isPlainObject = function (obj) { + return serialize.call(obj) === '[object Object]' && Object.getPrototypeOf(obj) === oproto + } + + var i = 0 + var utils = { + uid: function () { + return ++i + }, + noop: function () {}, + bind: function (fn, context) { + return function () { + return fn.apply(context, arguments) + } + }, + preventEvent: function (evt) { + evt.preventDefault() + }, + stop: function (evt) { + evt.preventDefault() + evt.stopPropagation() + }, + nextTick: function (fn, context) { + setTimeout(utils.bind(fn, context), 0) + }, + toArray: function (ary, start, end) { + if (start === undefined) start = 0 + if (end === undefined) end = ary.length + return aproto.slice.call(ary, start, end) + }, + + isPlainObject: isPlainObject, + isFunction: isFunction, + isArray: isArray, + isObject: function (obj) { + return Object(obj) === obj + }, + isString: function (s) { + return typeof s === 'string' + }, + isUndefined: function (a) { + return typeof a === 'undefined' + }, + isDefined: function (a) { + return typeof a !== 'undefined' + }, + + each: function (ary, func, context) { + if (utils.isDefined(ary.length)) { + for (var i = 0, len = ary.length; i < len; i++) { + if (func.call(context, ary[i], i, ary) === false) { + break + } + } + } else { + for (var k in ary) { + if (func.call(context, ary[k], k, ary) === false) { + break + } + } + } + }, + + /** + * If option is a function, evaluate it with given params + * @param {*} data + * @param {...} args arguments of a callback + * @returns {*} + */ + evalOpts: function (data, args) { + if (utils.isFunction(data)) { + // `arguments` is an object, not array, in FF, so: + args = utils.toArray(arguments) + data = data.apply(null, args.slice(1)) + } + return data + }, + + extend: function () { + var options + var name + var src + var copy + var copyIsArray + var clone + var target = arguments[0] || {} + var i = 1 + var length = arguments.length + var force = false + + // 濡傛灉绗竴涓弬鏁颁负甯冨皵,鍒ゅ畾鏄惁娣辨嫹璐� + if (typeof target === 'boolean') { + force = target + target = arguments[1] || {} + i++ + } + + // 纭繚鎺ュ彈鏂逛负涓�涓鏉傜殑鏁版嵁绫诲瀷 + if (typeof target !== 'object' && !isFunction(target)) { + target = {} + } + + // 濡傛灉鍙湁涓�涓弬鏁帮紝閭d箞鏂版垚鍛樻坊鍔犱簬 extend 鎵�鍦ㄧ殑瀵硅薄涓� + if (i === length) { + target = this + i-- + } + + for (; i < length; i++) { + // 鍙鐞嗛潪绌哄弬鏁� + if ((options = arguments[i]) != null) { + for (name in options) { + src = target[name] + copy = options[name] + + // 闃叉鐜紩鐢� + if (target === copy) { + continue + } + if (force && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false + clone = src && isArray(src) ? src : [] + } else { + clone = src && isPlainObject(src) ? src : {} + } + target[name] = utils.extend(force, clone, copy) + } else if (copy !== undefined) { + target[name] = copy + } + } + } + } + return target + }, + + formatSize: function (size) { + if (size < 1024) { + return size.toFixed(0) + ' bytes' + } else if (size < 1024 * 1024) { + return (size / 1024.0).toFixed(0) + ' KB' + } else if (size < 1024 * 1024 * 1024) { + return (size / 1024.0 / 1024.0).toFixed(1) + ' MB' + } else { + return (size / 1024.0 / 1024.0 / 1024.0).toFixed(1) + ' GB' + } + }, + + defineNonEnumerable: function (target, key, value) { + Object.defineProperty(target, key, { + enumerable: false, + configurable: true, + writable: true, + value: value + }) + } + } + + module.exports = utils + + },{}]},{},[3]) + (3) + }); \ No newline at end of file diff --git a/src/pages/ai/FileUpload/common/utils.js b/src/pages/ai/FileUpload/common/utils.js new file mode 100644 index 0000000..92c775a --- /dev/null +++ b/src/pages/ai/FileUpload/common/utils.js @@ -0,0 +1,28 @@ +export function secondsToStr(temp) { + const years = Math.floor(temp / 31536000) + if (years) { + return years + ' 骞�' + numberEnding(years) + } + const days = Math.floor((temp %= 31536000) / 86400) + if (days) { + return days + ' 澶�' + numberEnding(days) + } + const hours = Math.floor((temp %= 86400) / 3600) + if (hours) { + return hours + ' 灏忔椂' + numberEnding(hours) + } + const minutes = Math.floor((temp %= 3600) / 60) + if (minutes) { + return minutes + ' 鍒�' + numberEnding(minutes) + } + const seconds = temp % 60 + return seconds + ' 绉�' + numberEnding(seconds) + function numberEnding(number) { + // return (number > 1) ? 's' : '' + return '' + } +} + +export function kebabCase(s) { + return s.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`) +} diff --git a/src/pages/ai/FileUpload/drop.vue b/src/pages/ai/FileUpload/drop.vue new file mode 100644 index 0000000..9c88666 --- /dev/null +++ b/src/pages/ai/FileUpload/drop.vue @@ -0,0 +1,64 @@ +<template> + <div class="uploader-drop" :class="dropClass" ref="drop" v-show="support"> + <slot></slot> + </div> +</template> + +<script> +import { uploaderMixin, supportMixin } from './common/mixins' + +const COMPONENT_NAME = 'uploader-drop' + +export default { + name: COMPONENT_NAME, + mixins: [uploaderMixin, supportMixin], + data() { + return { + dropClass: '' + } + }, + methods: { + onDragEnter() { + this.dropClass = 'uploader-dragover' + }, + onDragLeave() { + this.dropClass = '' + }, + onDrop() { + this.dropClass = 'uploader-droped' + } + }, + mounted() { + this.$nextTick(() => { + const dropEle = this.$refs.drop + const uploader = this.uploader.uploader + uploader.assignDrop(dropEle) + uploader.on('dragenter', this.onDragEnter) + uploader.on('dragleave', this.onDragLeave) + uploader.on('drop', this.onDrop) + }) + }, + beforeDestroy() { + const dropEle = this.$refs.drop + const uploader = this.uploader.uploader + uploader.off('dragenter', this.onDragEnter) + uploader.off('dragleave', this.onDragLeave) + uploader.off('drop', this.onDrop) + uploader.unAssignDrop(dropEle) + } +} +</script> + +<style> +.uploader-drop { + position: relative; + padding: 10px; + overflow: hidden; + border: 1px dashed #ccc; + background-color: #f5f5f5; +} +.uploader-dragover { + border-color: #999; + background-color: #f7f7f7; +} +</style> diff --git a/src/pages/ai/FileUpload/file.vue b/src/pages/ai/FileUpload/file.vue new file mode 100644 index 0000000..ddd30c8 --- /dev/null +++ b/src/pages/ai/FileUpload/file.vue @@ -0,0 +1,469 @@ +<template> + <div class="uploader-file" :status="status"> + <slot + :file="file" + :list="list" + :status="status" + :paused="paused" + :error="error" + :response="response" + :average-speed="averageSpeed" + :formated-average-speed="formatedAverageSpeed" + :current-speed="currentSpeed" + :is-complete="isComplete" + :is-uploading="isUploading" + :size="size" + :formated-size="formatedSize" + :uploaded-size="uploadedSize" + :progress="progress" + :progress-style="progressStyle" + :progressing-class="progressingClass" + :time-remaining="timeRemaining" + :formated-time-remaining="formatedTimeRemaining" + :type="type" + :extension="extension" + :file-category="fileCategory" + > + <div + class="uploader-file-progress" + :class="progressingClass" + :style="progressStyle" + ></div> + <div class="uploader-file-info"> + <div class="uploader-file-name"> + <i class="uploader-file-icon" :icon="fileCategory"></i> + {{ file.name }} + </div> + <div class="uploader-file-size">{{ formatedSize }}</div> + <div class="uploader-file-meta"></div> + <div class="uploader-file-status"> + <span v-show="status !== 'uploading'">{{ statusText }}</span> + <span v-show="status === 'uploading'"> + <span>{{ progressStyle.progress }}</span> + <em>{{ formatedAverageSpeed }}</em> + + <i> {{ formatedTimeRemaining }}</i> + </span> + </div> + <div class="uploader-file-actions"> + <span class="uploader-file-pause" @click="pause"></span> + <span class="uploader-file-resume" @click="resume">锔�</span> + <span class="uploader-file-retry" @click="retry"></span> + <span class="uploader-file-remove" @click="remove"></span> + </div> + </div> + </slot> + </div> +</template> + +<script> +import Uploader from "simple-uploader.js"; +import events from "./common/file-events"; +import { secondsToStr } from "./common/utils"; + +const COMPONENT_NAME = "uploader-file"; + +export default { + name: COMPONENT_NAME, + props: { + file: { + type: Object, + default() { + return {}; + }, + }, + list: { + type: Boolean, + default: false, + }, + }, + data() { + return { + response: null, + paused: false, + error: false, + averageSpeed: 0, + currentSpeed: 0, + isComplete: false, + isUploading: false, + size: 0, + formatedSize: "", + uploadedSize: 0, + progress: 0, + timeRemaining: 0, + type: "", + extension: "", + progressingClass: "", + }; + }, + computed: { + fileCategory() { + const extension = this.extension; + const isFolder = this.file.isFolder; + let type = isFolder ? "folder" : "unknown"; + const categoryMap = this.file.uploader.opts.categoryMap; + const typeMap = categoryMap || { + image: ["gif", "jpg", "jpeg", "png", "bmp", "webp"], + video: ["mp4", "m3u8", "rmvb", "avi", "swf", "3gp", "mkv", "flv"], + audio: ["mp3", "wav", "wma", "ogg", "aac", "flac"], + document: [ + "doc", + "txt", + "docx", + "pages", + "epub", + "pdf", + "numbers", + "csv", + "xls", + "xlsx", + "keynote", + "ppt", + "pptx", + ], + }; + Object.keys(typeMap).forEach((_type) => { + const extensions = typeMap[_type]; + if (extensions.indexOf(extension) > -1) { + type = _type; + } + }); + return type; + }, + progressStyle() { + const progress = Math.floor(this.progress * 100); + const style = `translateX(${Math.floor(progress - 100)}%)`; + return { + progress: `${progress}%`, + webkitTransform: style, + mozTransform: style, + msTransform: style, + transform: style, + }; + }, + formatedAverageSpeed() { + return `${Uploader.utils.formatSize(this.averageSpeed)} / s`; + }, + status() { + const isUploading = this.isUploading; + const isComplete = this.isComplete; + const isError = this.error; + const paused = this.paused; + if (isComplete) { + return "success"; + } else if (isError) { + return "error"; + } else if (isUploading) { + return "uploading"; + } else if (paused) { + return "paused"; + } else { + return "waiting"; + } + }, + statusText() { + const status = this.status; + const fileStatusText = this.file.uploader.fileStatusText; + let txt = status; + if (typeof fileStatusText === "function") { + txt = fileStatusText(status, this.response); + } else { + txt = fileStatusText[status]; + } + return txt || status; + }, + formatedTimeRemaining() { + const timeRemaining = this.timeRemaining; + const file = this.file; + if (timeRemaining === Number.POSITIVE_INFINITY || timeRemaining === 0) { + return ""; + } + let parsedTimeRemaining = secondsToStr(timeRemaining); + const parseTimeRemaining = file.uploader.opts.parseTimeRemaining; + if (parseTimeRemaining) { + parsedTimeRemaining = parseTimeRemaining( + timeRemaining, + parsedTimeRemaining + ); + } + return parsedTimeRemaining; + }, + }, + watch: { + status(newStatus, oldStatus) { + if (oldStatus && newStatus === "uploading" && oldStatus !== "uploading") { + this.tid = setTimeout(() => { + this.progressingClass = "uploader-file-progressing"; + }, 200); + } else { + clearTimeout(this.tid); + this.progressingClass = ""; + } + }, + }, + methods: { + _actionCheck() { + this.paused = this.file.paused; + this.error = this.file.error; + this.isUploading = this.file.isUploading(); + }, + pause() { + this.file.pause(); + this._actionCheck(); + this._fileProgress(); + }, + resume() { + this.file.resume(); + this._actionCheck(); + }, + remove() { + this.file.cancel(); + }, + retry() { + this.file.retry(); + this._actionCheck(); + }, + processResponse(message) { + let res = message; + try { + res = JSON.parse(message); + } catch (e) {} + this.response = res; + }, + fileEventsHandler(event, args) { + const rootFile = args[0]; + const file = args[1]; + const target = this.list ? rootFile : file; + if (this.file === target) { + if (this.list && event === "fileSuccess") { + this.processResponse(args[2]); + return; + } + this[`_${event}`].apply(this, args); + } + }, + _fileProgress() { + this.progress = this.file.progress(); + this.averageSpeed = this.file.averageSpeed; + this.currentSpeed = this.file.currentSpeed; + this.timeRemaining = this.file.timeRemaining(); + this.uploadedSize = this.file.sizeUploaded(); + this._actionCheck(); + }, + _fileSuccess(rootFile, file, message) { + if (rootFile) { + this.processResponse(message); + } + this._fileProgress(); + this.error = false; + this.isComplete = true; + this.isUploading = false; + }, + _fileComplete() { + this._fileSuccess(); + }, + _fileError(rootFile, file, message) { + this._fileProgress(); + this.processResponse(message); + this.error = true; + this.isComplete = false; + this.isUploading = false; + }, + }, + mounted() { + const staticProps = ["paused", "error", "averageSpeed", "currentSpeed"]; + const fnProps = [ + "isComplete", + "isUploading", + { + key: "size", + fn: "getSize", + }, + { + key: "formatedSize", + fn: "getFormatSize", + }, + { + key: "uploadedSize", + fn: "sizeUploaded", + }, + "progress", + "timeRemaining", + { + key: "type", + fn: "getType", + }, + { + key: "extension", + fn: "getExtension", + }, + ]; + staticProps.forEach((prop) => { + this[prop] = this.file[prop]; + }); + fnProps.forEach((fnProp) => { + if (typeof fnProp === "string") { + this[fnProp] = this.file[fnProp](); + } else { + this[fnProp.key] = this.file[fnProp.fn](); + } + }); + + const handlers = (this._handlers = {}); + const eventHandler = (event) => { + handlers[event] = (...args) => { + this.fileEventsHandler(event, args); + }; + return handlers[event]; + }; + events.forEach((event) => { + this.file.uploader.on(event, eventHandler(event)); + }); + }, + destroyed() { + events.forEach((event) => { + this.file.uploader.off(event, this._handlers[event]); + }); + this._handlers = null; + }, +}; +</script> + +<style> +.uploader-file { + position: relative; + height: 49px; + line-height: 49px; + overflow: hidden; +} +.uploader-file[status="waiting"] .uploader-file-pause, +.uploader-file[status="uploading"] .uploader-file-pause { + display: block; +} +.uploader-file[status="paused"] .uploader-file-resume { + display: block; +} +.uploader-file[status="error"] .uploader-file-retry { + display: block; +} +.uploader-file[status="success"] .uploader-file-remove { + display: none; +} +.uploader-file[status="error"] .uploader-file-progress { + background: #ffe0e0; +} +.uploader-file-progress { + position: absolute; + width: 100%; + height: 4px; + border-radius: 4px; + background: #1dd4ec; + transform: translateX(-100%); +} +.uploader-file-progressing { + transition: all 0.4s linear; +} +.uploader-file-info { + position: relative; + z-index: 1; + height: 100%; + overflow: hidden; + font-size: 13px; +} +.uploader-file-info:hover { + background-color: rgba(240, 240, 240, 0.2); +} +.uploader-file-info i, +.uploader-file-info em { + font-style: normal; +} +.uploader-file-name, +.uploader-file-size, +.uploader-file-meta, +.uploader-file-status, +.uploader-file-actions { + float: left; + position: relative; + height: 100%; +} +.uploader-file-name { + width: 50%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + text-indent: 14px; + text-align: left; +} +.uploader-file-icon { + width: 24px; + height: 24px; + display: inline-block; + vertical-align: top; + margin-top: 13px; + margin-right: 8px; +} +.uploader-file-icon::before { + content: "馃搵"; + display: block; + /* height: 49px; */ + font-size: 18px; + line-height: 26px; + text-indent: 0; +} +.uploader-file-icon[icon="folder"]::before { + content: "馃搨"; +} +.uploader-file-icon[icon="image"]::before { + content: "馃寙"; +} +.uploader-file-icon[icon="video"]::before { + content: "馃幀"; +} +.uploader-file-icon[icon="audio"]::before { + content: "馃幍"; +} +.uploader-file-icon[icon="document"]::before { + content: "馃搵"; +} +.uploader-file-size { + width: 11%; + text-indent: 10px; +} +.uploader-file-meta { + width: 8%; +} +.uploader-file-status { + width: 24%; + text-indent: 20px; +} +.uploader-file-actions { + width: 6%; +} +.uploader-file-actions > span { + display: none; + float: left; + width: 16px; + height: 16px; + margin-top: 16px; + margin-right: 10px; + cursor: pointer; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAACxMAAAsTAQCanBgAAARkSURBVGje7ZnfS1NRHMAH4ptPkvQSuAdBkCxD8FUQJMEULUgzy1KyyPVQ4JMiiP4Bvg6EwUQQfMmwhwRDshwaKUjDVCgoSdDNHkzTJZ6+Z37Purve8+PeTb2TM/ggu+ew89l33x8H9BBCPG7GowXTJej3+wnDvEm0JuLC04+EYWftVAUv+fiCvDUdQR1BHUEdQR3BTIygvixoQS14XgTtthLVdpNWwXRLqvQ724LplFRtyrYF0yVpFLQrKRVMh6RZ0I6kkmCqklaCqpKZH0FX56Crq9jVfdDVk0RfFrSgFsxkQVmLcdKCVrKySCrryhPEyYShhzOcrFtG0EoilfHHk1CRU5rF6ZjNZhlVOW6RnMSVyyilKies4pO41diVy8wIujoHXV3FGdMHXTtJKLFYTLhZtq4vC1rwXApCZTIqgR6g1PBMCO9DL3bMMSqBHqDU8EyISDAHiGKvWwcCQG2KgjlAFCDAOhAAap0K5gKLphk8mqJgLrCIgoxRJ4J5wKpJ7gAoMkn5EBXBPGDVJHcAFJmkfIhQcAql1oBpTvTol9gG9pm4RHAKpdaAaU706JfYBvaZuJVgPQrt4sFlnOh5MC/p3lmJYD0K7eLBZZzoeTAv6d5ZnuAYHjpgEOnk5F0ufhG6v1ggOIaHDhhEOjl5l4tfhO4vthLcwAMrFNvLJO5vEwhu4IEViu1lEve3WQmyoihQFBzG/V0CQVYUBYqCw7i/SxTBcpsRbFeIYLnNCLZbCY5b5KAnxRwct8hBj9McZFVMW0ihRNBuFdMWUigRlFaxuQ9WWYjRMTiIe5z0wSoLMToGB3GPsA9aTZIJoB+nRgBnM1tzOkkmgH6cGgGczWzNpzqLx3n/aULJJgezeNw07oxQySbVywKjBOgFRnDs+VEsx8FlgVEC9AIjOPb8KJYjvSzoG7UW1IJaUAtqQS14toLNM5fN5APdwBJA8G83Pk/aK/rgzVvXzeQD3cASQPBvNz5P2ssTzAaGUIrHEO6zI5gNDKEUjyHcxxWkh4Ylcowwk1QQpIeGJXKMMJO0EgwqyjGCioJBJvDrxRMSuVOTJEXfbz1/bHwWtBL0yoQehK6RucgE+bGzanzulQh6E3IgQV+xpc8kcrfuSO7eTfJ3ZYmQw0Oy9azVKOk1C/bJ5D5F38YPeLfx0rjWJxHsS0SqsSYuxySjj5qO5Oj7xQWy2VBtFOwzCy6ryH3YfE3uh64Y1xckgstJPydEjkkeHv07Iy4Xaao15+KCWTBx6M/db+T9xivSErqaJDdzXI6yLRE8Vgg0coex/SPJvT0SbWu0KpZtbgSpCH3NRt7I5OxHkObc6heU+/M/J5vrpBFM5GBLqCQux14COXs5CNXK5OjPGm1tSMrJSOMNYQ4mVTGV/L6zTL7+DovkbFUxbSW0Wo05l8hJWsU+cRWfSh+Mt5Lb1ck/J1TvVsdDaR/MiEni+llsdZuZp62EViu+96bpNjNPWwmtVnzvFd5m9IVVC54x/wA7gNvqFG9vXQAAAABJRU5ErkJggg==") + no-repeat 0 0; +} +.uploader-file-actions > span:hover { + background-position-x: -21px; +} +.uploader-file-actions .uploader-file-pause { + background-position-y: 0; +} +.uploader-file-actions .uploader-file-resume { + background-position-y: -17px; +} +.uploader-file-actions .uploader-file-retry { + background-position-y: -53px; +} +.uploader-file-actions .uploader-file-remove { + display: block; + background-position-y: -34px; +} +</style> diff --git a/src/pages/ai/FileUpload/files.vue b/src/pages/ai/FileUpload/files.vue new file mode 100644 index 0000000..1380ba9 --- /dev/null +++ b/src/pages/ai/FileUpload/files.vue @@ -0,0 +1,42 @@ +<template> + <div class="uploader-files"> + <slot :files="files"> + <ul> + <li v-for="file in files" :key="file.id"> + <uploader-file :file="file"></uploader-file> + </li> + </ul> + </slot> + </div> +</template> + +<script> +import { uploaderMixin } from './common/mixins' +import UploaderFile from './file.vue' + +const COMPONENT_NAME = 'uploader-files' + +export default { + name: COMPONENT_NAME, + mixins: [uploaderMixin], + computed: { + files() { + return this.uploader.files + } + }, + components: { + UploaderFile + } +} +</script> + +<style> +.uploader-files { + position: relative; +} +.uploader-files > ul { + list-style: none; + margin: 0; + padding: 0; +} +</style> diff --git a/src/pages/ai/FileUpload/index.vue b/src/pages/ai/FileUpload/index.vue new file mode 100644 index 0000000..a7b8311 --- /dev/null +++ b/src/pages/ai/FileUpload/index.vue @@ -0,0 +1,306 @@ +<template> + <div class="file-uploader"> + <uploader + v-if="single" + ref="uploader" + :options="options" + :file-status-text="statusText" + class="uploader-single" + :sourceType="sourceType" + @file-added="onFileAdded" + @complete="onComplete" + > + <div class="up-bar" v-if="isDrag == true"> + <div class="name">{{ fileName || uploadPlaceholder }}</div> + <uploader-btn slot="suffix" :attrs="attrs"> + <el-tooltip :content="tipWords" placement="top" v-if="tip"> + <div class="open-file-btn"> + <span class="icon iconfont"></span> + </div> + </el-tooltip> + </uploader-btn> + </div> + <el-input + :placeholder="uploadPlaceholder" + v-if="isDrag == false" + size="small" + :readonly="true" + v-model="fileName" + > + <uploader-btn slot="suffix" :attrs="attrs"> + <el-tooltip :content="tipWords" placement="top" v-if="tip"> + <i + class="el-icon-upload2" + style="font-size: 18px; color: #0088ff" + ></i> + </el-tooltip> + <i + v-else + class="el-icon-upload2" + style="font-size: 18px; color: #0088ff" + ></i> + </uploader-btn> + </el-input> + <uploader-list /> + </uploader> + + <uploader + v-else + ref="uploader" + :options="options" + :file-status-text="statusText" + class="uploader-example" + @file-added="onFileAdded" + @file-complete="fileComplete" + @complete="onComplete" + @close="closeHandle" + > + <uploader-btn ref="button" :sourceType="sourceType"> + <i class="el-icon-upload2" style="font-size: 18px; color: #0088ff"></i> + 涓婁紶 + </uploader-btn> + <uploader-list /> + </uploader> + </div> +</template> + +<script> +import uploader from "./uploader"; +import SparkMD5 from "spark-md5"; +import UploaderBtn from "./btn"; +import UploaderList from "./list"; +import UploaderDrop from "./drop"; + +export default { + components: { + uploader, + UploaderBtn, + UploaderList, + UploaderDrop, + }, + props: { + sourceType: { + type: Number, + }, + tip: { + type: Boolean, + default: false, + }, + tipWords: { + type: String, + default: "", + }, + single: { + type: Boolean, + default: false, + }, + uploadPlaceholder: { + type: String, + default: "", + }, + isDrag: { + type: Boolean, + default: false, + }, + url: { + type: String, + default: "/data/api-f/file/upload", + }, + attrs: { + type: Object, + default() { + return {}; + }, + }, + }, + data() { + return { + fileName: "",shouldStop:false, + fileMd5: "", + statusText: { + success: "涓婁紶鎴愬姛", + error: "涓婁紶澶辫触", + uploading: "涓婁紶涓�", + paused: "鏆傚仠涓�", + waiting: "绛夊緟涓�", + }, + }; + }, + computed: { + uploader() { + return this.$refs.uploader.uploader; + }, + options() { + return { + target: this.url, + testChunks: true, + headers: { + Authorization: + sessionStorage.getItem("loginedInfo") && + JSON.parse(sessionStorage.getItem("loginedInfo")).access_token, + }, + }; + }, + }, + methods: { + onFileAdded(file) { + // if (this.sourceType == 3) { + // if ( + // !file.name.endsWith(".tar") || + // !file.name.endsWith(".gz") || + // !file.name.endsWith(".tar.gz") + // ) { + // this.shouldStop = true + // this.$notify.warning("浠呮敮鎸�.tar/.gz/.tar.gz涓夌鏍煎紡鏂囦欢"); + // return + // } + // } + if (this.single) { + this.uploader.fileList = this.uploader.fileList.slice([-1]); + this.$emit("file-added"); + } + this.computeMD5(file); + }, + computeMD5(file) { + let fileReader = new FileReader(); + let time = new Date().getTime(); + let blobSlice = + File.prototype.slice || + File.prototype.mozSlice || + File.prototype.webkitSlice; + let currentChunk = 0; + const chunkSize = 10 * 1024 * 1000; + let chunks = Math.ceil(file.size / chunkSize); + let spark = new SparkMD5.ArrayBuffer(); + // 鏂囦欢鐘舵�佽涓�"璁$畻MD5" + this.statusText.paused = "鍑嗗涓婁紶,姝e湪妫�鏌ユ枃浠�"; + file.pause(); + loadNext(); + fileReader.onload = (e) => { + spark.append(e.target.result); + if (currentChunk < chunks) { + currentChunk++; + loadNext(); + } else { + let md5 = spark.end(); + this.computeMD5Success(md5, file); + this.fileName = file.name; + this.fileMd5 = md5; + } + }; + fileReader.onerror = function () { + this.error(`鏂囦欢${file.name}璇诲彇鍑洪敊锛岃妫�鏌ヨ鏂囦欢`); + file.cancel(); + }; + function loadNext() { + let start = currentChunk * chunkSize; + let end = + start + chunkSize >= file.size ? file.size : start + chunkSize; + fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); + } + }, + computeMD5Success(md5, file) { + //灏嗚嚜瀹氫箟鍙傛暟鐩存帴鍔犺浇uploader瀹炰緥鐨刼pts涓� + if (location.href.indexOf("dataStack") >= 0) { + Object.assign(this.uploader.opts, { + query: { + stackId: this.DataStackPool.selectedDir.id, + // ...this.params, + }, + }); + } + file.uniqueIdentifier = md5; + file.resume(); + this.statusText.paused = "鏆傚仠涓�"; + }, + onComplete() { + if (this.shouldStop) { + return + } + this.$emit("complete", { + filename: this.fileName, + identifier: this.fileMd5, + }); + }, + fileComplete() {}, + closeHandle() { + this.$emit("close"); + }, + }, + mounted() { + this.isDrag; + this.$nextTick(() => { + window.uploader = this.$refs.uploader.uploader; + }); + }, +}; +</script> + +<style lang="scss"> +.file-uploader { + .el-input__suffix, + .el-input__suffix-inner { + outline: none !important; + } + .el-tooltip.focusing { + outline: none; + } + .uploader-example { + width: 99%; + // padding: 15px; + // margin: 40px auto 0; + font-size: 12px; + // box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + background-color: #fff; + } + .uploader-example .uploader-btn { + position: relative; + display: none; + // float: right; + // top: -45px; + } + .uploader-example .uploader-list { + max-height: 440px; + overflow: auto; + overflow-x: hidden; + overflow-y: auto; + } + .uploader-single { + position: unset; + .close { + display: none; + } + .uploader-btn { + border: 0px; + } + .uploader-file { + // height: 2px; + .uploader-file-progress { + // background: #3d68e1; + } + .uploader-file-info { + // display: none; + } + } + + .up-bar { + height: 30px; + background: #f2f2f7; + border-radius: 2px; + display: flex; + align-items: center; + justify-content: space-between; + box-sizing: border-box; + padding: 0 20px; + .iconfont { + font-size: 16px; + color: #333; + } + .name { + color: #bdbdbd; + font-size: 14px; + } + } + } +} +</style>> diff --git a/src/pages/ai/FileUpload/list.vue b/src/pages/ai/FileUpload/list.vue new file mode 100644 index 0000000..9951595 --- /dev/null +++ b/src/pages/ai/FileUpload/list.vue @@ -0,0 +1,43 @@ +<template> + <div class="uploader-list"> + <slot :file-list="fileList"> + <ul> + <li v-for="file in fileList" :key="file.id"> + <uploader-file :file="file" :list="true"></uploader-file> + </li> + </ul> + </slot> + </div> +</template> + +<script> +import { uploaderMixin } from './common/mixins' +import UploaderFile from './file.vue' + +const COMPONENT_NAME = 'uploader-list' + +export default { + name: COMPONENT_NAME, + mixins: [uploaderMixin], + computed: { + fileList() { + return this.uploader.fileList + } + }, + components: { + UploaderFile + } +} +</script> + +<style> +.uploader-list { + position: relative; margin-top: 12px; + +} +.uploader-list > ul { + list-style: none; + margin: 0; + padding: 0; +} +</style> diff --git a/src/pages/ai/FileUpload/unsupport.vue b/src/pages/ai/FileUpload/unsupport.vue new file mode 100644 index 0000000..59626ee --- /dev/null +++ b/src/pages/ai/FileUpload/unsupport.vue @@ -0,0 +1,30 @@ +<template> + <div class="uploader-unsupport" v-show="!support"> + <slot> + <p> + Your browser, unfortunately, is not supported by Uploader.js. The library requires support for + <a href="http://www.w3.org/TR/FileAPI/">the HTML5 File API</a> along with + <a href="http://www.w3.org/TR/FileAPI/#normalization-of-params">file slicing</a>. + </p> + </slot> + </div> +</template> + +<script> +import { uploaderMixin, supportMixin } from './common/mixins' + +const COMPONENT_NAME = 'uploader-unsupport' + +export default { + name: COMPONENT_NAME, + mixins: [uploaderMixin, supportMixin] +} +</script> + +<style> +.uploader-unsupport { + position: relative; + z-index: 10; + overflow: hidden; +} +</style> diff --git a/src/pages/ai/FileUpload/uploader.vue b/src/pages/ai/FileUpload/uploader.vue new file mode 100644 index 0000000..69705de --- /dev/null +++ b/src/pages/ai/FileUpload/uploader.vue @@ -0,0 +1,189 @@ +<template> + <div class="uploader"> + <!-- <div class="close" @click="closeHandle">x</div> --> + <slot :files="files" :file-list="fileList" :started="started"> + <uploader-unsupport></uploader-unsupport> + <UploaderDrop> + <p>鎷栧姩鏂囦欢鍒拌鍖哄煙涓婁紶</p> + + <uploader-btn >閫夋嫨鏂囦欢</uploader-btn> + <uploader-btn :directory="true" >閫夋嫨鏂囦欢澶�</uploader-btn> + </UploaderDrop> + <uploader-list></uploader-list> + </slot> + </div> +</template> + +<script> +import Uploader from 'simple-uploader.js' +import { kebabCase } from './common/utils' +import UploaderBtn from './btn.vue' +import UploaderDrop from './drop.vue' +import UploaderUnsupport from './unsupport.vue' +import UploaderList from './list.vue' + +const COMPONENT_NAME = 'uploader' +const FILE_ADDED_EVENT = 'fileAdded' +const FILES_ADDED_EVENT = 'filesAdded' +const UPLOAD_START_EVENT = 'uploadStart' + +export default { + name: COMPONENT_NAME, + provide() { + return { + uploader: this + } + }, + props: { + attrs: { + type: Object, + default() { + return {} + } + }, + sourceType: { + type: Number, + }, + options: { + type: Object, + default() { + return {} + } + }, + autoStart: { + type: Boolean, + default: true + }, + fileStatusText: { + type: [Object, Function], + default() { + return { + success: 'success', + error: 'error', + uploading: 'uploading', + paused: 'paused', + waiting: 'waiting' + } + } + } + }, + data() { + return { + started: false, + files: [], + fileList: [] + } + }, + methods: { + uploadStart() { + this.started = true + }, + fileAdded(file) { + this.$emit(kebabCase(FILE_ADDED_EVENT), file) + if (file.ignored) { + // is ignored, filter it + return false + } + }, + filesAdded(files, fileList) { + if (this.sourceType == 3 && files[0]) { + if ( + !files[0].name.endsWith(".tar") || + !files[0].name.endsWith(".gz") || + !files[0].name.endsWith(".tar.gz") + ) { + this.shouldStop = true + return + } + } + this.$emit(kebabCase(FILES_ADDED_EVENT), files, fileList) + if (files.ignored || fileList.ignored) { + // is ignored, filter it + return false + } + }, + fileRemoved(file) { + this.files = this.uploader.files + this.fileList = this.uploader.fileList + }, + filesSubmitted(files, fileList) { + if (this.sourceType == 3&& files[0]) { + if ( + !files[0].name.endsWith(".tar") || + !files[0].name.endsWith(".gz") || + !files[0].name.endsWith(".tar.gz") + ) { + this.shouldStop = true + return + } + } + this.files = this.uploader.files + this.fileList = this.uploader.fileList + if (this.autoStart) { + this.uploader.upload() + } + }, + allEvent(...args) { + const name = args[0] + const EVENTSMAP = { + [FILE_ADDED_EVENT]: true, + [FILES_ADDED_EVENT]: true, + [UPLOAD_START_EVENT]: 'uploadStart' + } + const handler = EVENTSMAP[name] + if (handler) { + if (handler === true) { + return + } + this[handler].apply(this, args.slice(1)) + } + args[0] = kebabCase(name) + this.$emit.apply(this, args) + }, + closeHandle() { + this.$emit("close") + } + }, + created() { + // this.bindUploader(); + this.options.initialPaused = !this.autoStart + const uploader = new Uploader(this.options) + this.uploader = uploader + this.uploader.fileStatusText = this.fileStatusText + uploader.on('catchAll', this.allEvent) + uploader.on(FILE_ADDED_EVENT, this.fileAdded) + uploader.on(FILES_ADDED_EVENT, this.filesAdded) + uploader.on('fileRemoved', this.fileRemoved) + uploader.on('filesSubmitted', this.filesSubmitted) + }, + mounted() { + }, + destroyed() { + const uploader = this.uploader + uploader.off('catchAll', this.allEvent) + uploader.off(FILE_ADDED_EVENT, this.fileAdded) + uploader.off(FILES_ADDED_EVENT, this.filesAdded) + uploader.off('fileRemoved', this.fileRemoved) + uploader.off('filesSubmitted', this.filesSubmitted) + this.uploader = null + }, + components: { + UploaderBtn, + UploaderDrop, + UploaderUnsupport, + UploaderList + } +} +</script> + +<style lang="scss"> +.uploader { + .close { + position: absolute; + right: 5px; + top: 3px; + cursor: pointer; + } +} + +</style> diff --git a/src/pages/ai/index/App.vue b/src/pages/ai/index/App.vue index 13549e1..68b8825 100644 --- a/src/pages/ai/index/App.vue +++ b/src/pages/ai/index/App.vue @@ -7,568 +7,390 @@ <div class="inner-bar"></div> </div> </div> - <!-- 瓒呯骇绠$悊鍛樺彲瑙� --> <div class="super"> - <div class="left-box"> - <!-- <div class="title"> - <label>绠楁硶搴�</label> - </div>--> - <el-tabs - v-model="activeName" - type="border-card" - @tab-click="handleTabClick" - style="height: calc(100% - 20px)" - > - <el-tab-pane label="宸叉縺娲�" name="myAlgorithm"> - <div class="width-new-line task-list" v-show="activeName === 'myAlgorithm'"> - <p class="src-title">绠楁硶杞欢</p> - <div class="flex-list"> - <div class="wrap-box" v-for="item in installedList" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div - class="svg-wrap" - :class="{ willUpGrade: item.isUpgrade }" - v-loading="item.upgradeLoading" - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <!-- <i class="iconfont iconupdate" v-if="item.isUpgrade"></i> --> - <img class="update-icon" v-if="item.isUpgrade" src="../../../assets/img/鏇存柊鎻愮ず.png" alt=""> - <div class="mask" v-if="!item.isDefault || item.isUpgrade"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div class="info-onmask" @click="checkDetail(item, 'active')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - @click="unLoadSdk(item)" - type="primary" - size="small" - class="bot-btn" - >鍗歌浇</el-button> - <el-button - v-if="item.isUpgrade" - @click="donwload(item, 0)" - type="warning" - size="small" - class="bot-btn" - >鍗囩骇</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit"> - {{ - item.sdk_name - }} - </span> - - <el-input - size="small" - v-model="item.sdk_name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> - </div> - <div class="wrap-box" v-for="item in notInstalledList" :key="item.id"> - <div - class="list-choose-item-left list-choose-item-left-uninstal" - v-loading="downloading && downloadItem == item.id" - > - <div class="mask"> - <div class="left-top"> - <div v-if="item.installed">褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div - class="info-onmask" - @click="checkDetail(item, 'activeNotInstall')" - >鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button @click="donwload(item,1)" type="primary" class="bot-btn">瀹夎</el-button> - </div> - </div> - <div class="click-download" title="涓嬭浇"> - <span class="iconfont iconxiazai1"></span> - </div> - <div class="list-complete-item-handle"> - <div - class="svg-wrap" - v-loading=" - item.installLoading || item.upgradeLoading - " - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span class="list-choose-item-left-uninstal"> - {{ - item.sdk_name - }} - </span> - </div> - </div> - </div> - </div> - </div> - </div> - <p class="src-title">搴旂敤杞欢</p> - <div class="flex-list"> - <div class="wrap-box" v-for="item in installedApps" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div - class="svg-wrap" - :class="{ willUpGrade: item.isUpgrade }" - v-loading=" - item.unloadLoading || item.upgradeLoading - " - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <!-- <i class="iconfont iconupdate" v-if="item.isUpgrade"></i> --> - <img class="update-icon" v-if="item.isUpgrade" src="../../../assets/img/鏇存柊鎻愮ず.png" alt=""> - - <div class="mask"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <!-- v-if="!item.isDefault" --> - <div class="info-onmask" @click="checkDetail(item,'active')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - v-show="!item.isDefault" - @click="unLoad(item)" - type="primary" - size="small" - class="bot-btn" - >鍗歌浇</el-button> - <el-button - v-if="item.isUpgrade" - @click="downloadApp(item, 'upgrade')" - type="warning" - size="small" - class="bot-btn" - >鍗囩骇</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name" style="color:grey;"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit">{{ item.name }}</span> - <el-input - size="small" - v-model="item.sdk_name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> - </div> - <div class="wrap-box" v-for="item in storeApps" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle uninstall"> - <div - class="svg-wrap" - v-loading=" - item.installLoading || item.upgradeLoading - " - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <div class="mask"> - <div class="left-top"> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <!-- v-if="!item.isDefault" --> - <div class="info-onmask" @click="checkDetail(item,'activeNotInstall')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - @click="downloadApp(item)" - type="primary" - size="small" - class="bot-btn" - >瀹夎</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit">{{ item.name }}</span> - <el-input - size="small" - v-model="item.name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> - </div> - </div> + <div class="left-box" v-if="!inDetail"> + <div class="nav-box"> + <div class="nav-box-menu"> + <div + v-for="(name, index) in menuArr" + :key="index" + class="menu-item" + :class="activeName == name ? 'menu-item-actiove' : ''" + @click="pickMenu(name)" + > + {{ name }} + <sup v-if="index == 3 && updateNum != 0">{{ updateNum }}</sup> </div> - </el-tab-pane> + </div> + <div class="nav-box-search"> + <span class="icon iconfont all-scene"></span> + <el-input + placeholder="鎼滅储" + v-model="inputText" + @change="searchAll" + class="input-with-select" + > + <i class="el-icon-search" slot="prepend"></i> + <el-select + v-model="select" + slot="append" + placeholder="閫夋嫨鍦烘櫙" + :popper-append-to-body="false" + > + <el-option label="閾佽矾鍦烘櫙" value="1"> + <span class="icon iconfont"></span> + <span>閾佽矾鍦烘櫙</span> + </el-option> + <el-option label="瀹夊叏鍦烘櫙" value="2"> + <span class="icon iconfont"></span> + <span>瀹夊叏鍦烘櫙</span> + </el-option> + <el-option label="閫氱敤鍦烘櫙" value="3"> + <span class="icon iconfont"></span> + <span>閫氱敤鍦烘櫙</span> + </el-option> + <el-option label="鏍″洯鍥尯" value="4"> + <span class="icon iconfont"></span> + <span>鏍″洯鍥尯</span> + </el-option> + </el-select> + </el-input> + </div> - <el-tab-pane - label="绂荤嚎鍗囩骇/瀹夎" - name="upgradeOrInstallation" - v-if="isShow('algorithmManage:insOffLine')" - > - <div class="tab-content"> - <div class="action-bar"> - <file-uploader - single - tip - tipWords="涓婁紶绠楁硶" - uploadPlaceholder="涓婁紶瀹夎杞欢" - url="/data/api-v/sdk/upload" - @complete="onFileUpload" - @file-added="onFileAdded" + <div class="bg-img-wrap"> + <img src="/images/appCenter/Group-112.png" alt="" /> + </div> + </div> + <div class="quick-path" v-if="showQuickPath"> + <div class="left-items"> + <div + class="quick-item" + v-for="(item, index) in recomandUpdateList" + :key="index" + @click="checkDetail(item, 'inactive', item.sdk_name)" + > + <div class="icon-img"> + <span class="icon iconfont" v-if="item.isUpgrade" + ></span + > + <img + v-if="item.iconBlob" + :src=" + item.iconBlob.indexOf(',') > 0 + ? item.iconBlob + : `data:image/png;base64,${item.iconBlob}` + " + alt /> + <img v-else :src="item.icon" alt /> + </div> + <div class="desc"> + <el-tooltip + :content="item.sdk_name || item.name" + effect="light" + > + <div class="desc-1">{{ item.sdk_name || item.name }}</div> + </el-tooltip> + <div class="desc-2">鐗堟湰 {{ item.version }}</div> + </div> + <div class="right-icon"> + <el-tooltip effect="dark" content="涓嬭浇" placement="bottom"> + <span class="icon iconfont"></span> + </el-tooltip> </div> </div> - </el-tab-pane> - <el-tab-pane label="搴旂敤涓績" name="algorithmMall" v-if="isShow('algorithmManage:buy')"> - <div class="tab-content"> - <div class="flex-title"> - <p class="src-title">绠楁硶杞欢</p> - </div> - <div class="store-list flex-list"> - <div class="wrap-box" v-for="item in unActivedSDKList" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div class="alg-icon svg-wrap"> - <!-- <div class="mask" @click="actSdkOrApp(item.id)"> - <span - class="iconfont iconyunxiazai" - style=" - color: #ff6a00; - font-size: 20px; - position: absolute; - top: 45%; - left: 45%; - " - ></span> - </div>--> - <div class="mask" v-if="!item.isDefault || item.isUpgrade"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div class="info-onmask" @click="actSdkOrApp(item)">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - @click="actSdkOrApp(item)" - type="primary" - size="small" - class="bot-btn" - >婵�娲�</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit"> - {{ - item.sdk_name - }} - </span> - <el-input - size="small" - v-model="item.sdk_name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> - </div> - </div> - <p class="src-title">搴旂敤杞欢</p> - <div class="app-list flex-list"> - <div v-if="!unActivedAppList.length" class="empty-tip">鏆傛棤鏁版嵁</div> - <div class="wrap-box" v-for="item in unActivedAppList" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div class="alg-icon svg-wrap"> - <div class="mask" v-if="!item.isDefault || item.isUpgrade"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div class="info-onmask" @click="actSdkOrApp(item,'app')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - @click="actSdkOrApp(item, 'app')" - type="primary" - size="small" - class="bot-btn" - >婵�娲�</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit">{{ item.name }}</span> - <el-input - size="small" - v-model="item.name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> - </div> - </div> - </div> - <!-- --> - </el-tab-pane> - <el-tab-pane name="update"> - <span slot="label"> - <el-badge class="update-badge" :value="updateNum" :hidden="updateNum==0">鏇存柊</el-badge> - </span> - <div class="task-list"> - <div class="flex-title"> - <p class="src-title">绠楁硶杞欢</p> - <el-button @click="batchUpdate('sdk')" size="mini" type="primary">鏇存柊鍏ㄩ儴</el-button> - </div> - <div class="flex-list"> - <div - v-if="hasNewVersionSdk.length==0" - class="empty-tip" - >{{errMsg?errMsg:"鏆傛棤鏁版嵁"}}</div> - <div class="wrap-box" v-for="item in hasNewVersionSdk" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div - class="svg-wrap" - :class="{ willUpGrade: item.isUpgrade }" - v-loading="item.upgradeLoading" - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <!-- <i class="iconfont iconupdate" v-if="item.isUpgrade"></i> --> - <img class="update-icon" v-if="item.isUpgrade" src="../../../assets/img/鏇存柊鎻愮ず.png" alt=""> + </div> - <div class="mask" v-if="!item.isDefault || item.isUpgrade"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div class="info-onmask" @click="checkDetail(item,'active')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - @click="unLoadSdk(item)" - type="primary" - size="small" - class="bot-btn" - >鍗歌浇</el-button> - <el-button - v-if="item.isUpgrade" - @click="donwload(item, 0)" - type="warning" - size="small" - class="bot-btn" - >鍗囩骇</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit"> - {{ - item.sdk_name - }} - </span> - </div> - </div> - </div> - </div> - </div> - </div> - <div class="flex-title"> - <p class="src-title">搴旂敤杞欢</p> - <el-button @click="batchUpdate('app')" type="primary" size="mini">鏇存柊鍏ㄩ儴</el-button> - </div> - <div class="flex-list"> - <div v-if="!hasNewVersionApp.length" class="empty-tip">鏆傛棤鏁版嵁</div> - <div class="wrap-box" v-for="item in hasNewVersionApp" :key="item.id"> - <div class="list-choose-item-left"> - <div class="list-complete-item-handle"> - <div - class="svg-wrap" - :class="{ willUpGrade: item.isUpgrade }" - v-loading=" - item.unloadLoading || item.upgradeLoading - " - :element-loading-text="item.progressMsg" - element-loading-background="rgba(0,0,0,.8)" - > - <!-- <i class="iconfont iconupdate" v-if="item.isUpgrade"></i> --> - <img class="update-icon" v-if="item.isUpgrade" src="../../../assets/img/鏇存柊鎻愮ず.png" alt=""> + <!-- <div class="down-all-btn"> + <el-button plain size="small" @click="batchUpdate('both')" round + >鍏ㄩ儴鏇存柊</el-button + > + </div> --> + </div> - <div class="mask"> - <div class="left-top"> - <div>褰撳墠鐗堟湰:{{ item.version }}</div> - <div v-if="item.remoteVersion">鏈�鏂扮増鏈�:{{ item.remoteVersion }}</div> - </div> - <div class="info-onmask" @click="checkDetail(item,'active')">鏌ョ湅璇︽儏</div> - <div class="mask-btn"> - <el-button - v-if="!item.isDefault" - @click="unLoad(item)" - type="primary" - size="small" - class="bot-btn" - >鍗歌浇</el-button> - <el-button - v-if="item.isUpgrade" - @click="downloadApp(item, 'upgrade')" - type="warning" - size="small" - class="bot-btn" - >鍗囩骇</el-button> - </div> - </div> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - <img v-else class="baseImg" :src="item.icon" alt /> - </div> - <div class="alg-name"> - <div style="padding: 0px 10px 0px 10px"> - <span v-if="!item.isEdit">{{ item.name }}</span> - <el-input - size="small" - v-model="item.sdk_name" - v-if="item.isEdit" - v-focus - :maxlength="15" - @blur="inputBlur(item)" - ></el-input> - </div> - </div> - </div> - </div> + <div class="main-content"> + <!-- <div class="main-title">搴旂敤涓績</div> --> + <div class="tab-btns" v-if="activeName != '绂荤嚎鍗囩骇/瀹夎'"> + <div class="group-left"> + <div + class="tab" + @click="pickTab('sdk')" + :class="activeTab == 'sdk' ? 'tab-active' : ''" + > + 绠楁硶杞欢 + </div> + <div + class="tab" + @click="pickTab('app')" + :class="activeTab == 'app' ? 'tab-active' : ''" + > + 搴旂敤杞欢 + </div> + </div> + + <div + class="batch-update" + v-if="activeName == '鏇存柊' && tempList.length" + > + <el-button + size="small" + type="primary" + round + @click="batchUpdate" + >鍏ㄩ儴鏇存柊</el-button + > + </div> + </div> + <div + class="front-page-items" + v-if="activeName != '绂荤嚎鍗囩骇/瀹夎'" + > + <div + class="front-page-item" + v-for="(item, index) in tempList" + :key="index" + @click="checkDetail(item, null, item.sdk_name)" + :class="{ + disabled: activeName == '搴旂敤涓績' && !item.canUpOrIns, + }" + > + <div class="icon-img"> + <span class="icon iconfont" v-if="item.isUpgrade" + ></span + > + <img + v-if="item.iconBlob" + :src=" + item.iconBlob.indexOf(',') > 0 + ? item.iconBlob + : `data:image/png;base64,${item.iconBlob}` + " + alt + /> + <img v-else :src="item.icon" alt /> + </div> + <div class="desc"> + <el-tooltip + :content="item.sdk_name || item.name" + effect="light" + > + <div class="desc-1">{{ item.sdk_name || item.name }}</div> + </el-tooltip> + <div class="desc-2">鐗堟湰 {{ item.version }}</div> + </div> + <div class="right-btn"> + <el-button + size="small" + type="primary" + class="other-btn" + round + @click="checkDetail(item, null, item.sdk_name)" + v-if="activeName == '搴旂敤涓績' && item.price > 0" + >婵�娲�</el-button + > + <el-button + size="small" + type="primary" + class="update-btn" + round + @click.stop="actived(item)" + v-if="activeName == '搴旂敤涓績' && item.price == 0" + >瀹夎</el-button + > + <el-button + size="small" + type="primary" + class="check-btn" + round + v-if=" + activeName == '宸叉縺娲�' && + ((activeTab == 'sdk' && !item.isUpgrade) || + (activeTab == 'app' && + !item.isUpgrade && + !item.isDefault)) + " + >鏌ョ湅</el-button + > + <el-button + size="small" + type="primary" + class="check-btn" + round + v-if=" + activeName == '宸叉縺娲�' && + activeTab == 'app' && + item.isDefault && + !item.isUpgrade + " + >鏌ョ湅</el-button + > + <el-button + size="small" + type="primary" + class="other-btn" + round + v-if=" + activeName == '宸叉縺娲�' && + activeTab == 'app' && + item.isDefault && + item.isUpgrade + " + >鍗囩骇</el-button + > + <el-button + size="small" + type="primary" + class="update-btn" + round + @click.stop="donwloadSDK(item)" + v-if=" + (activeName == '鏇存柊' || activeName == '宸叉縺娲�') && + activeTab == 'sdk' && + item.isUpgrade && + !item.upgradeLoading + " + >鏇存柊</el-button + > + <span + class="icon iconfont rocket-icon" + v-if=" + activeName == '鏇存柊' && + item.isUpgrade && + item.upgradeLoading && + rocketIf + " + ></span + > + <span + class="icon iconfont rocket-icon" + v-if=" + activeName == '鏇存柊' && + item.isUpgrade && + item.upgradeLoading && + !rocketIf + " + ></span + > + <el-button + size="small" + type="primary" + class="update-btn" + round + @click.stop="downloadApp(item, 'upgrade')" + v-if=" + (activeName == '鏇存柊' || activeName == '宸叉縺娲�') && + activeTab == 'app' && + item.isUpgrade && + !item.upgradeLoading + " + >鏇存柊</el-button + > + + <div class="status"> + {{ item.progressMsg }} </div> </div> </div> - </el-tab-pane> - </el-tabs> + + <div + class="front-page-item item-dimmed" + v-for="(item, index) in tempDarkList" + :key="index" + @click="checkDetail(item, 'activeNotInstall', item.sdk_name)" + > + <div class="icon-img"> + <img + v-if="item.iconBlob" + :src=" + item.iconBlob.indexOf(',') > 0 + ? item.iconBlob + : `data:image/png;base64,${item.iconBlob}` + " + alt + /> + <img v-else :src="item.icon" alt /> + </div> + <div class="desc"> + <el-tooltip + :content="item.sdk_name || item.name" + effect="light" + > + <div class="desc-1">{{ item.sdk_name || item.name }}</div> + </el-tooltip> + <div class="desc-2">鐗堟湰 {{ item.version }}</div> + </div> + <div class="right-btn"> + <el-button + size="small" + type="primary" + class="other-btn" + round + v-if="activeTab == 'sdk' && !item.upgradeLoading" + @click.stop="donwloadSDK(item)" + >瀹夎</el-button + > + <el-button + size="small" + type="primary" + class="other-btn" + round + v-if="activeTab == 'app' && !item.upgradeLoading" + @click.stop="downloadApp(item)" + >瀹夎</el-button + > + <div class="spin-icon"> + <span + class="icon iconfont anz-font" + v-if="item.upgradeLoading" + ></span + > + </div> + <div class="status"> + {{ item.progressMsg }} + </div> + </div> + </div> + </div> + + <div class="upload-pkg" v-if="activeName == '绂荤嚎鍗囩骇/瀹夎'"> + <div class="upload-head"> + <div class="left"> + <span class="icon iconfont"></span> + <span class="txt">涓婁紶瀹夎杞欢</span> + </div> + </div> + + <FileUploader + class="upload-demo" + single + tip + :sourceType="3" + :isDrag="true" + :attrs="{ accept: '.zip,.tar,.gz,.tar.gz' }" + tipWords="鐐瑰嚮涓婁紶" + uploadPlaceholder="绠楁硶杞欢" + url="/data/api-v/sdk/upload" + @complete="onFileUpload" + @file-added="onFileAdded" + /> + </div> + </div> </div> + + <detailPage + :detailProductID="detailProductID" + :detailType="detailType" + :detailPrice="detailPrice" + :isSdk="isSdk" + v-if="inDetail" + @flushSdk="getAllSdk" + @flushApp="getAllApps" + @goback="goback" + ></detailPage> </div> </div> </div> + <el-dialog title="瀹夎鍖呬俊鎭�" :visible.sync="installDialogVisible" @@ -615,265 +437,6 @@ <el-button type="primary" @click="offlineInstall">瀹� 瑁�</el-button> </div> </el-dialog> - <!-- <div class="dialog-content" v-if="productDetailVisible" > --> - <el-dialog class="product-detail-dialog" :visible="productDetailVisible" @close="closeDial"> - <!-- <el-button-group> --> - <div class="button-group" v-show="!backDisable||!forwardDisable"> - <el-button size="small" @click="backwards" :disabled="backDisable"> - <span><</span> - </el-button> - <!-- <el-button type="primary" size="small" icon="el-icon-arrow-left"></el-button> --> - <el-button size="small" @click="forwards" :disabled="forwardDisable">></el-button> - <!-- <el-button type="primary" size="small"><i class="el-icon-arrow-right el-icon--right"></i></el-button> --> - </div> - <!-- </el-button-group> --> - <div class="dialog-title" slot="title">{{isSDKDialog?"绠楁硶璇︽儏":"搴旂敤璇︽儏"}}</div> - <div class="dialog-content"> - <div class="box-top"> - <div class="top-left"> - <div class="banner"> - <el-carousel - ref="carousel" - :autoplay="false" - indicator-position="none" - :arrow=" - productDetail.pics !== undefined - ? productDetail.pics.length > 1 - ? 'always' - : 'never' - : 'never' - " - @change="changeHandle" - > - <!-- :arrow="productDetail.pics.length > 1 ? 'always' : 'never'" --> - <el-carousel-item v-for="(item, index) in productDetail.pics" :key="index"> - <div class="imgwrap"> - <img - v-if="item.type != 'video'" - :src="item.url" - class="cursor-pointer" - preview - /> - <video v-if="item.type == 'video'" :src="item.url" controls></video> - </div> - </el-carousel-item> - </el-carousel> - </div> - </div> - <div class="top-right"> - <!-- <div class="title">{{curCheckTarget.sdk_name}}</div> --> - <div class="summary"> - <div class="icon"> - <img - v-if="productDetail.iconBlob" - class="baseImg" - :src=" - productDetail.iconBlob.indexOf(',') > 0 - ? productDetail.iconBlob - : `data:image/png;base64,${productDetail.iconBlob}` - " - alt - /> - </div> - <div class="right-desc"> - <div class="name"> - <el-tooltip - class - effect="dark" - :content="productDetail.productName" - placement="right-start" - > - <span>{{ productDetail.productName }}</span> - </el-tooltip> - </div> - <div class="tags"> - <el-tag type="info" size="small" color="#fff" v-if="!isSDKDialog">搴旂敤</el-tag> - <el-tag type="info" size="small" color="#fff" v-if="isSDKDialog">绠楁硶</el-tag> - </div> - <div class="btns"> - <el-button - size="small" - type="warning" - v-if="needToUpgradeInWin||productDetail.isUpgrade" - @click="upgradeSDKinWin" - > - {{ - isUpgrading ? "鍗囩骇涓�.." : "鍗囩骇" - }} - </el-button> - <el-button - size="small" - type="primary" - v-if="isActive&&!isDefaultApp" - @click="unloadSDKinWin" - >鍗歌浇</el-button> - <el-button - size="small" - type="primary" - v-if="!isActive&&!showInstallNotActive" - @click="showInputCode=!showInputCode" - >婵�娲�</el-button> - <el-button - size="small" - type="primary" - v-if="!isActive&&showInstallNotActive" - @click="downloadSdkInSide" - >{{isUpgrading?"瀹夎涓�..":"瀹夎"}}</el-button> - <el-button - size="small" - type="success" - v-if="!isSDKDialog&&isActive" - @click="openApp" - >鎵撳紑</el-button> - </div> - </div> - </div> - <div class="jihuo-input" v-if="showInputCode"> - <el-input - size="small" - v-model="activeCode" - placeholder="00000-00000-00000-00000-00000" - @blur="getCodeDetail" - ></el-input> - <el-button type="primary" size="small" @click="actived">婵�娲�</el-button> - <el-button type="primary" size="small" @click="cancelActivate">鍙栨秷</el-button> - </div> - <div class="product-intruduction"> - <div class="part-title" v-if="!showInputCode">绠�浠�</div> - <div class="text"> - <div class="single-desc"> - <div>鐗堟湰锛�</div> - <div> - {{ - productDetail.productVersion === "" - ? "鏆傛棤" - : productDetail.productVersion - }} - </div> - </div> - <div class="single-desc"> - <div>姒傝堪锛�</div> - <div> - {{ - productDetail.description === "" - ? "鏆傛棤" - : productDetail.description - }} - </div> - </div> - <div class="single-desc"> - <div>璇﹁堪锛�</div> - <div> - {{ - productDetail.summary === "" - ? "鏆傛棤" - : productDetail.summary - }} - </div> - </div> - </div> - </div> - </div> - </div> - <div class="box-bottom"> - <div class="bot-left"> - <div class="part-title">{{ isSDKDialog ? "搴旂敤鍦烘櫙" : "鍔熻兘鐗圭偣" }}</div> - <div class="list-zone"> - <div class="list-item" v-for="(item, index) in productDetail.funcInfo" :key="index"> - <el-tag - type - size="small" - effect="dark" - >{{ item.title === "" ? "鏆傛棤鏁版嵁" : item.title }}</el-tag> - <div class="desc"> - {{ - item.desc === "" - ? "鏆傛棤鏁版嵁" - : item.desc - }} - </div> - </div> - </div> - </div> - <div class="bot-right"> - <div class="part-title">鎺ㄨ崘绠楁硶</div> - <div class="item-zone"> - <div class="item" v-for="(item, index) in otherProducts" :key="index"> - <el-tag type="info" color="inherit" size="small"> - {{ - item.productTypeName === "" - ? "鏆傛棤鏁版嵁" - : item.productTypeName - }} - </el-tag> - <div class="icon"> - <img - v-if="item.iconBlob" - class="baseImg" - :src=" - item.iconBlob.indexOf(',') > 0 - ? item.iconBlob - : `data:image/png;base64,${item.iconBlob}` - " - alt - /> - - <div class="icon-name"> - <el-tooltip - class - effect="dark" - :content="item.name === '' ? '鏆傛棤鏁版嵁':item.name" - placement="top-start" - > - <span>{{ item.name === "" ? "鏆傛棤鏁版嵁" : item.name }}</span> - </el-tooltip> - </div> - </div> - <div class="look-button"> - <el-button type="primary" size="mini" @click="checkInWindow(item)">鏌ョ湅</el-button> - </div> - </div> - </div> - </div> - </div> - </div> - </el-dialog> - <el-dialog - :visible.sync="showActivateSuccess" - title="婵�娲绘垚鍔燂紒" - width="30%" - class="active-Dial" - :before-close="handleClose" - > - <div class="dialog-active"> - <ul class="desc"> - <li> - <label>婵�娲荤爜:</label> - <span>{{ activedSdkOrApp.activateCode }}</span> - </li> - <li> - <label>浜у搧鍚嶇О:</label> - <span>{{ activedSdkOrApp.productName }}</span> - </li> - <li> - <label>閰嶇疆璇︽儏:</label> - <span>{{ activedSdkOrApp.setting }}</span> - </li> - <li> - <label>鏈嶅姟鍒版湡鏃�:</label> - <span>{{ activedSdkOrApp.expireTime }}</span> - </li> - <li> - <label>璁稿彲璇�:</label> - <span>{{ activedSdkOrApp.licence }}</span> - </li> - </ul> - <div class="text-right"> - <el-button type="primary" @click="checkMyAlgorith">纭畾</el-button> - <p class="tip">鎻愮ず锛氳鍦ㄢ�滃凡婵�娲烩�濅腑鏌ョ湅骞跺畨瑁呯畻娉�</p> - </div> - </div> - </el-dialog> </div> </template> <script> @@ -883,6 +446,7 @@ installSdk, getInstallInfo, removeSdk, + uploadSDK, } from "./api"; import { getApps, @@ -894,39 +458,19 @@ getUnActivedApp, actApp, } from "@/api/app"; - -import bus from "@/plugin/bus"; -import FileUploader from "@/components/subComponents/FileUpload/index"; +import { getUrlKey } from "@/api/utils"; +import FileUploader from "../FileUpload/index"; +import detailPage from "./detail"; export default { name: "algorithmManage", - props: {}, components: { FileUploader, + detailPage, }, computed: { updateNum() { return this.hasNewVersionApp.length + this.hasNewVersionSdk.length; }, - // notInstalledList () { - // return this.sdkList.filter(sdk => { - // return sdk.installed === false; - // }); - // }, - // installedList () { - // return this.sdkList.filter(sdk => { - // return sdk.installed === true && !sdk.isUpgrade; - // }); - // }, - // ungradeList () { - // // 鍗囩骇澶勭悊浼氬鑷撮噸澶嶇殑key,闇�瑕佷慨鏀� - // let arr = this.sdkList.filter(sdk => { - // return sdk.isUpgrade === true; - // }); - // arr.forEach(sdk => { - // sdk.upgradeLoading = false; - // }); - // return arr; - // }, isAdmin() { if ( sessionStorage.getItem("userInfo") && @@ -935,40 +479,46 @@ let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username; return loginName === "superadmin" || loginName === "basic"; } - return false; }, }, data() { return { - sdkList: [], installedList: [], + recomandUpdateList: [], hasNewVersionSdk: [], + activeTab: "sdk", hasNewVersionApp: [], + tempDarkList: [], notInstalledList: [], + showUpload: false, + detailType: "", + detailProductID: "", + detailPrice: "", buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [], - activeName: "myAlgorithm", + activeName: "搴旂敤涓績", patchUpdateStatus: "", downloadItem: "", downloading: false, - direction: "rtl", actStep: 0, + showQuickPath: true, showActivateSuccess: false, activeCode: "", isInstall: false, installDialogVisible: false, - installPackage: {}, installAppPackage: null, installSdkPackage: null, isActive: true, isDefaultApp: false, - installPercentage: 0, unActivedSDKList: [], unActivedAppList: [], + inDetail: false, isSDKDialog: true, - //actSdkId: '', actType: "", actId: "", + inputText: "", + tempList: [], + select: "", activedSdkOrApp: { activateCode: "", productName: "", @@ -977,28 +527,26 @@ licence: "", devIds: "", }, - // unloadLoading: false, - // installLoading: false, installedApps: [], storeApps: [], installFile: {}, - freshTimer: null, - appUpgreading: true, - sdkUpgreading: true, + appUpgreading: false, + sdkUpgreading: false, autoRefresh: true, - curCheckTarget: {}, productDetailVisible: false, isUpgrading: false, productDetail: {}, otherProducts: [], backStack: [], + toUpdateArr1: [], forwardStack: [], + rocketIf: false, backDisable: true, forwardDisable: true, showInputCode: false, needToUpgradeInWin: false, - errMsg: "", - showInstallNotActive: false + showInstallNotActive: false, + menuArr: ["搴旂敤涓績", "宸叉縺娲�", "绂荤嚎鍗囩骇/瀹夎", "鏇存柊"], }; }, directives: { @@ -1008,223 +556,174 @@ }, }, }, - mounted() { - // 鑾峰彇鎵�鏈夊簲鐢� + var name = getUrlKey("activeName"); + if (name) { + this.pickMenu(name); + } this.autoRefreshAppAndSdkState(); - - this.getUnActivedList(); + this.getUnActivedList(1); this.getUnActivedAppList(); }, beforeDestroy() { this.autoRefresh = false; }, methods: { - isShow(authority) { - return ( - this.isAdmin || this.buttonAuthority.indexOf("," + authority + ",") > -1 - ); + searchAll() { + this.getAllApps(); + this.getAllSdk(); + this.getUnActivedList(1); + this.getUnActivedAppList(); }, - batchUpdate(type) { - if (type == "sdk") { - this.hasNewVersionSdk.forEach((sdk) => { - this.donwload(sdk, 0); - }); + goback() { + this.inDetail = false; + }, + batchUpdate(s) { + if (s == "both") { + this.batchUpdateSDK(); + this.batchUpdateApp(); + } else if (this.activeTab == "sdk") { + this.batchUpdateSDK(); } else { - this.hasNewVersionApp.forEach((app) => { - this.downloadApp(app, "upgrade"); - }); + this.batchUpdateApp(); } }, - closeDial() { - this.productDetailVisible = false - this.productDetail = {} - this.otherProducts = [] - }, - checkDetail(item, type) { - if (type == 'inactive') { - this.isActive = false - this.showInstallNotActive = false - this.showInputCode = false - } else if (type == 'active') { - this.showInputCode = false - this.showInstallNotActive = false - this.isActive = true - } else if (type == 'activeNotInstall') { - this.showInputCode = false - this.isActive = false - this.showInstallNotActive = true - } - this.checkIsDefOrNot(item.id) - this.needToUpgradeInWin = item.isUpgrade ? true : false - this.resetStack() - if (item.sdk_type === undefined) { - this.isSDKDialog = false - } else { - this.isSDKDialog = true - } - this.productDetailVisible = true; - let _this = this; - getAppDetail({ id: item.id }).then((res) => { - _this.productDetail = res.data.detail; - _this.productDetail.isUpgrade = item.isUpgrade; - _this.productDetail.iconBlob = item.iconBlob; - - _this.otherProducts = res.data.randoms; + batchUpdateSDK() { + this.hasNewVersionSdk.forEach((sdk) => { + this.donwloadSDK(sdk); }); }, - resetStack() { - this.forwardStack = [] - this.backStack = [] - this.backDisable = true - this.forwardDisable = true - - }, - checkInWindow(item) { - this.backStack.push([this.productDetail, this.otherProducts]) - this.backDisable = false - this.checkIsDefOrNot(item.id) - - let _this = this; - getAppDetail({ id: item.id }).then((res) => { - _this.productDetail = res.data.detail; - _this.productDetail.iconBlob = item.iconBlob - this.actId = _this.productDetail.productBaseId - let flag = false - const allNeedToNew = [...this.hasNewVersionSdk, ...this.hasNewVersionApp] - for (let i = 0; i < allNeedToNew.length; i++) { - const item = allNeedToNew[i]; - if (item.id == _this.productDetail.productBaseId) { - flag = true - } - } - this.needToUpgradeInWin = flag - _this.productDetail.isUpgrade = flag - - _this.otherProducts = res.data.randoms; + batchUpdateApp() { + this.hasNewVersionApp.forEach((app) => { + this.downloadApp(app, "upgrade"); }); + }, + pickMenu(name) { + this.activeName = name; + this.activeTab = "sdk"; + this.showQuickPath = true; + switch (name) { + case "搴旂敤涓績": + this.tempList = this.unActivedSDKList; + this.tempDarkList = []; + break; + case "宸叉縺娲�": + this.tempList = this.installedList; + this.tempDarkList = this.notInstalledList; + break; + case "鏇存柊": + this.showQuickPath = false; + this.tempList = this.hasNewVersionSdk; + this.tempDarkList = []; + break; + default: + this.tempList = []; + this.tempDarkList = []; + break; + } + }, + pickTab(val) { + if (val) { + this.activeTab = val; + } + if (this.activeName == "搴旂敤涓績") { + this.tempList = + this.activeTab == "sdk" + ? this.unActivedSDKList + : this.unActivedAppList; + this.tempDarkList = []; + } else if (this.activeName == "宸叉縺娲�") { + this.tempList = + this.activeTab == "sdk" ? this.installedList : this.installedApps; + this.tempDarkList = + this.activeTab == "sdk" ? this.notInstalledList : this.storeApps; + } else if (this.activeName == "鏇存柊") { + this.tempList = + this.activeTab == "sdk" + ? this.hasNewVersionSdk + : this.hasNewVersionApp; + + this.tempDarkList = []; + } + }, + checkDetail(item, typ, sdkName) { + /* if (!item.canUpOrIns && typ == "Appcenter") { + return false; + } */ + this.isSdk = Boolean(sdkName); + this.inDetail = true; + this.detailProductID = item.id; + this.detailPrice = item.price; + if (typ) { + this.detailType = typ; + } else { + this.detailType = this.activeName == "搴旂敤涓績" ? "inactive" : "active"; + } }, checkIsDefOrNot(id) { - if (id.length > 10) { - this.isDefaultApp = false - } else { - this.isDefaultApp = true - } - }, - backwards() { - if (this.backStack.length == 0) { - this.backDisable = true - return - } - - this.forwardStack.push([this.productDetail, this.otherProducts]) - let item = this.backStack.pop() - this.productDetail = item[0] - this.checkIsDefOrNot(this.productDetail.productBaseId) - this.otherProducts = item[1] - this.forwardDisable = false - if (this.backStack.length == 0) { - this.backDisable = true - - } + this.isDefaultApp = id.length <= 10; }, forwards() { if (this.forwardStack.length == 0) { - this.forwardDisable = true - return + this.forwardDisable = true; + return; } - this.backStack.push([this.productDetail, this.otherProducts]) - this.backDisable = false - let item = this.forwardStack.pop() + this.backStack.push([this.productDetail, this.otherProducts]); + this.backDisable = false; + let item = this.forwardStack.pop(); - this.productDetail = item[0] - this.otherProducts = item[1] + this.productDetail = item[0]; + this.otherProducts = item[1]; if (this.forwardStack.length == 0) { - this.forwardDisable = true + this.forwardDisable = true; } - }, - //绂荤嚎瀹夎 offlineInstall() { this.installDialogVisible = false; this.isInstall = true; - //瀹夎 installSdk(this.installFile) .then((res) => { if (res.success) { this.isInstall = false; - this.$message({ - type: "success", - message: '瀹夎鎴愬姛,灏嗚烦杞嚦"宸叉縺娲�"涓煡鐪�', - }); + this.$message.success('瀹夎鎴愬姛,灏嗚烦杞嚦"宸叉縺娲�"涓煡鐪�'); setTimeout(() => { this.getAllSdk(); - window.parent.postMessage( - { - msg: "AppUpdate", - }, - "*" - ); - this.activeName = "myAlgorithm"; + window.parent.postMessage({ msg: "AppUpdate" }, "*"); + this.activeName = "宸叉縺娲�"; }, 3000); } }) .catch((e) => { this.isInstall = false; - this.$message({ - type: "error", - message: e.data, - }); + this.$message.error(e.msg); }); }, - downloadApp(app, action) { - if (action == "upgrade") { - app.upgradeLoading = true; - } else { - app.installLoading = true; - } - let _this = this; + let timer = null; + app.upgradeLoading = true; + timer = setInterval(() => { + this.rocketIf = !this.rocketIf; + }, 350); + let _this = this; installApp({ path: app.id }) .then((res) => { if (res && res.success) { - _this.$notify({ - title: "鎴愬姛", - message: "瀹夎搴旂敤鎴愬姛", - type: "success", - }); + _this.$notify.success("瀹夎搴旂敤鎴愬姛"); + clearInterval(timer); + app.upgradeLoading = false; setTimeout(() => { - if (action == "upgrade") { - app.upgradeLoading = false; - } else { - app.installLoading = false; - } - // _this.getAllApps(); - window.parent.postMessage( - { - msg: "AppUpdate", - }, - "*" - ); + window.parent.postMessage({ msg: "AppUpdate" }, "*"); }, 3000); } else { } }) .catch((e) => { - _this.$notify({ - title: "瀹夎澶辫触", - message: e.data, - type: "warning", - }); - if (action == "upgrade") { - app.upgradeLoading = false; - } else { - app.installLoading = false; - } + _this.$notify.warning(e.msg); + clearInterval(timer); + app.upgradeLoading = false; }); - // 寮�鍚嚜鍔ㄥ埛鏂� this.appUpgreading = true; }, @@ -1232,7 +731,7 @@ let iArry = []; let sArry = []; let nArry = []; - let rsp = await getApps(); + let rsp = await getApps({ appName: this.inputText }); if (rsp && rsp.success) { // 閬嶅巻app鐨勮繃绋嬮噸缃� this.appUpgreading = false; @@ -1242,11 +741,19 @@ { unloadLoading: false, upgradeLoading: false }, item ); - if (obj.progressMsg !== "" && obj.progressMsg !== "宸插畨瑁�") { + if ( + obj.progressMsg !== "" && + obj.progressMsg !== "宸插畨瑁�" && + obj.progressMsg != "100%" + ) { obj.upgradeLoading = true; - this.appUpgreading = true; } + + if (obj.upgradeDone) { + this.$notify.success(1 ? "绠楁硶瀹夎鎴愬姛" : "绠楁硶鍗囩骇鎴愬姛"); + } + item.installed ? iArry.push(obj) : sArry.push(obj); item.isUpgrade && nArry.push(obj); }); @@ -1255,13 +762,11 @@ this.storeApps = sArry; this.hasNewVersionApp = nArry; }, - - //鍗歌浇 - unLoad(app) { + unloadApp(app) { let _this = this; this.$confirm("纭畾瑕佸嵏杞借搴旂敤鍚�?", "鎻愮ず") .then(() => { - _this.productDetailVisible = false + _this.productDetailVisible = false; app.unloadLoading = true; removeApp({ appId: app.id }) @@ -1269,41 +774,15 @@ if (res && res.success) { app.unloadLoading = false; _this.getAllApps(); - window.parent.postMessage( - { - msg: "AppUpdate", - }, - "*" - ); - _this.$notify({ - title: "鎴愬姛", - message: "鍗歌浇搴旂敤鎴愬姛", - type: "success", - }); + window.parent.postMessage({ msg: "AppUpdate" }, "*"); + _this.$notify.success("鍗歌浇搴旂敤鎴愬姛"); } }) .catch((e) => { - console.log(e); app.unloadLoading = false; }); }) - .catch((e) => { - console.log(e); - }); - }, - - actSdkOrApp(item, type = "sdk") { - this.checkDetail(item, "inactive"); - this.actType = type; - this.actId = item.id; - this.actStep = 0; - this.activeCode = ""; - this.activedSdkOrApp = this.newActInfo(); - }, - - cancelActivate() { - this.showInputCode = false - this.activeCode = "" + .catch((e) => {}); }, newActInfo() { return { @@ -1315,80 +794,77 @@ devIds: "", }; }, - getUnActivedList() { - getUnActivedSdk().then((res) => { + getUnActivedList(v) { + getUnActivedSdk({ sdkName: this.inputText }).then((res) => { if (res.code == 200) { this.unActivedSDKList = res.data; + const len = this.unActivedSDKList.length; + const set = new Set(); + if (len <= 3) { + this.recomandUpdateList = [...this.unActivedSDKList]; + } else { + for (let i = 0; i < 3; i++) { + const pickI = Math.floor(Math.random() * len); + if (set.has(pickI)) { + i--; + continue; + } + set.add(pickI); + this.recomandUpdateList.push(this.unActivedSDKList[pickI]); + } + } + v == 1 ? (this.tempList = res.data) : null; } }); }, getUnActivedAppList() { - getUnActivedApp().then((res) => { + getUnActivedApp({ appName: this.inputText }).then((res) => { if (res.code == 200) { this.unActivedAppList = res.data; + this.pickTab(); } }); }, - actived() { - let _this = this; - if (this.activeCode.trim() == "") { - this.$notify({ - type: "error", - message: "婵�娲荤爜涓嶈兘涓虹┖", - }); - return; + actived(item) { + if (!item.canUpOrIns) { + return false; } - if (this.actType == "sdk") { - //婵�娲荤畻娉� - actPageAlg(this.actId, this.activeCode) + + let _this = this; + if (this.activeTab == "sdk") { + actPageAlg(item.id, "") .then((res) => { if (res.data.isSuccess) { this.productDetailVisible = false; _this.activedSdkOrApp = res.data.successMsg; - this.showActivateSuccess = true + this.showActivateSuccess = true; _this.actStep++; - _this.getUnActivedList(); + _this.getUnActivedList(1); _this.getAllSdk(); } else { - _this.$notify({ - type: "error", - message: res.data.failMsg.failMsg, - }); + _this.$notify.error(res.data.failMsg.failMsg); } }) - .catch((e) => { - console.log(e); - }); - } else if (this.actType == "app") { + .catch((e) => {}); + } else if (this.activeTab == "app") { //婵�娲诲簲鐢� - actApp(this.actId, this.activeCode) + actApp(item.id, "") .then((res) => { if (res.data.isSuccess) { this.productDetailVisible = false; _this.activedSdkOrApp = res.data.successMsg; - this.showActivateSuccess = true + this.showActivateSuccess = true; _this.actStep++; _this.getUnActivedAppList(); _this.getAllApps(); } else { - _this.$notify({ - type: "error", - message: res.data.failMsg.failMsg, - }); + _this.$notify.error(res.data.failMsg.failMsg); } }) - .catch((e) => { - console.log(e); - }); + .catch((e) => {}); } }, - getCodeDetail() { }, - checkMyAlgorith() { - this.showActivateSuccess = false; - this.activeName = "myAlgorithm"; - }, onFileUpload(file) { - //this.patchUpdateStatus = `<span style="color:green">涓婁紶鎴愬姛, 鐐瑰嚮鍗囩骇鎸夐挳寮�濮嬪畨瑁�</span>`; this.patchFile = { ...file }; this.fileAdded = true; const h = this.$createElement; @@ -1415,31 +891,22 @@ installContent: res.data.sdks[0].installContent, }; } + } else { + this.$message.error(res.msg); } }) .catch((e) => { - this.$message({ - type: "error", - message: e.data, - }); + this.$message.error(e.msg); }); }, - openApp() { - let message = 'toOpenApp?' + this.productDetail.productBaseId; - window.parent.postMessage({ - msg: message - }, "*") - }, - onFileAdded(f) { this.patchUpdateStatus = ""; }, - async getAllSdk() { let installedList = []; let unInstalledList = []; let hasNewVersionList = []; - let res = await findAllSdk(); + let res = await findAllSdk({ sdkName: this.inputText }); if (res && res.success) { this.sdkUpgreading = false; @@ -1448,197 +915,84 @@ { unloadLoading: false, upgradeLoading: false }, item ); - if (obj.progressMsg !== "" && obj.progressMsg !== "宸插畨瑁�") { + if ( + obj.progressMsg !== "" && + obj.progressMsg !== "宸插畨瑁�" && + obj.progressMsg !== "100%" + ) { obj.upgradeLoading = true; - this.sdkUpgreading = true; } //绠楁硶杞欢 宸插畨瑁呭叾涓寘鍚緟鍗囩骇 鏈畨瑁� item.installed ? installedList.push(obj) : unInstalledList.push(obj); - item.isUpgrade ? hasNewVersionList.push(obj) : null + item.isUpgrade ? hasNewVersionList.push(obj) : null; }); } this.installedList = installedList; this.notInstalledList = unInstalledList; + this.toUpdateArr1 = this.installedList.slice(0, 10); this.hasNewVersionSdk = hasNewVersionList; + this.pickTab(); }, - unloadSDKinWin() { - - let appToUnload - let sdkToUnload - if (this.productDetail.productTypeName == "搴旂敤") { - appToUnload = this.installedApps.find((item) => { - return item.id == this.productDetail.productBaseId - }) - this.unLoad(appToUnload) - } else { - sdkToUnload = this.installedList.find((item) => { - return item.id == this.productDetail.productBaseId - }) - this.unLoadSdk(sdkToUnload) - } - }, - //鍗歌浇绠楁硶 - unLoadSdk(sdk) { + unloadSdk(sdk) { let _this = this; this.$confirm("纭畾瑕佸嵏杞借绠楁硶鍚�?", "鎻愮ず") .then(() => { - _this.productDetailVisible = false + _this.productDetailVisible = false; sdk.unloadLoading = true; removeSdk({ sdkId: sdk.id }) .then((res) => { if (res && res.success) { sdk.unloadLoading = false; - this.$notify({ - title: "鎴愬姛", - message: "鍗歌浇瀹屾垚", - type: "success", - }); + this.$notify.success("鍗歌浇瀹屾垚"); _this.getAllSdk(); - window.parent.postMessage( - { - msg: "AppUpdate", - }, - "*" - ); + window.parent.postMessage({ msg: "AppUpdate" }, "*"); } }) .catch((e) => { - console.log(e); sdk.unloadLoading = false; }); }) - .catch((e) => { - console.log(e); - }); + .catch((e) => {}); }, - upgradeSDKinWin() { - this.isUpgrading = !this.isUpgrading; - - let _this = this; - if (this.productDetail.productTypeName == "搴旂敤") { - installApp({ path: this.productDetail.productBaseId }) - .then((res) => { - if (res && res.success) { - this.$notify({ - title: "鎴愬姛", - message: "鍗囩骇瀹屾垚", - type: "success", - }); - this.needToUpgradeInWin = false - this.productDetail.isUpgrade = false - this.isUpgrading = !this.isUpgrading; - - } - }) - .catch((e) => { - _this.$notify({ - title: "鍗囩骇澶辫触", - message: e.data, - type: "warning", - }); - this.isUpgrading = !this.isUpgrading; - }); - - // 寮�鍚嚜鍔ㄥ埛鏂� - this.appUpgreading = true; - } else { - downloadSdk({ path: this.productDetail.productBaseId }).then((res) => { - this.needToUpgradeInWin = false - this.productDetail.isUpgrade = false - this.isUpgrading = !this.isUpgrading; - this.$notify({ - title: "鎴愬姛", - message: "鍗囩骇瀹屾垚", - type: "success", - }); - }).catch((err) => { - this.$notify({ - title: "鍗囩骇澶辫触", - message: err.data, - type: "warning", - }); - this.isUpgrading = !this.isUpgrading; - }) - this.sdkUpgreading = true; - } - - - - }, - downloadSdkInSide() { - this.downloadItem = this.productDetail.productBaseId; - this.isUpgrading = true; - downloadSdk({ path: this.productDetail.productBaseId }) - .then((rsp) => { - this.productDetailVisible = false; - this.downloadItem = ""; - this.$notify({ - type: "success", - message: "绠楁硶宸插畨瑁�", - }); - this.isUpgrading = false - }) - .catch((err) => { - this.$notify({ - type: "warning", - message: err.data, - }); - this.downloadItem = ""; - this.isUpgrading = false - }); - // 寮�鍚嚜鍔ㄥ埛鏂� - this.sdkUpgreading = true; - }, - donwload(item, typ) { + donwloadSDK(item) { + let timer = null; item.upgradeLoading = true; + timer = setInterval(() => { + this.rocketIf = !this.rocketIf; + }, 350); this.downloadItem = item.id; - downloadSdk({ path: item.id }) .then((rsp) => { + clearInterval(timer); item.upgradeLoading = false; - //this.downloading = false; this.downloadItem = ""; - this.$notify({ - type: "success", - message: typ == 1 ? "绠楁硶瀹夎鎴愬姛" : "绠楁硶鍗囩骇鎴愬姛" - }); + + window.parent.postMessage({ msg: "AppUpdate" }, "*"); }) .catch((err) => { - this.$notify({ - type: "warning", - message: err.data, - }); + this.$notify.warning(err.data); item.upgradeLoading = false; - //this.downloading = false; this.downloadItem = ""; }); // 寮�鍚嚜鍔ㄥ埛鏂� this.sdkUpgreading = true; }, - inputBlur(item) { - this.$set(item, "isEdit", false); - }, - handleTabClick() { }, autoRefreshAppAndSdkState() { - // 鍏抽棴鍚庨��鍑� + this.getAllApps(); + this.getAllSdk(); if (!this.autoRefresh) { return; } - - if (this.appUpgreading) { - this.getAllApps(); - } - - if (this.sdkUpgreading) { - this.getAllSdk(); - } - - let _this = this; setTimeout(() => { - _this.autoRefreshAppAndSdkState(); - }, 500); + if (this.appUpgreading) { + this.getAllApps(); + } + if (this.sdkUpgreading) { + this.getAllSdk(); + } + }, 1000); }, }, }; @@ -1646,347 +1000,13 @@ <style lang="scss"> .s-task-manage { width: 100% !important; + min-width: 754px !important; height: 100%; box-sizing: border-box; text-align: left; - min-width: 1106px; - - .el-tabs { - height: calc(100% - 50px); - // margin-top: 5px !important; - } - .el-tabs--border-card > .el-tabs__header { - border: none; - } - .el-tabs__item.is-top { - height: 50px; - padding: 5px 50px !important; - font-size: 15px; - border: none !important; - } - .el-tabs__item.is-top.is-active { - font-weight: bold; - } - .el-tabs__content { - width: 100%; - height: calc(100% - 34px); - box-sizing: border-box; - } - .el-tab-pane { - width: 100%; - height: 100%; - } - .product-detail-dialog { - .dialog-title { - font-size: 13px; - } - .el-dialog { - width: 50%; - min-width: 920px; - position: relative; - } - .el-dialog__header { - text-align: center; - padding: 6px; - - .el-dialog__headerbtn { - position: absolute; - top: 5px; - - right: 20px; - padding: 0; - background: transparent; - outline: none; - cursor: pointer; - font-size: 20px; - } - } - .el-dialog__body { - background-color: rgba(222, 225, 230, 1); - padding: 8px 3px; - .button-group { - position: absolute; - top: 3px; - - left: 6px; - left: 10px; - .el-button--small { - padding: 5px 12px; - } - button { - font-size: 18px; - line-height: 12px; - } - } - } - - .dialog-content { - .box-top { - height: 330px; - .top-left { - float: left; - width: 55%; - background-color: rgba(253, 253, 253, 1); - margin: 0 0.5%; - height: 330px; - border-radius: 2px; - .banner { - text-align: center; - margin-top: 3px; - video { - margin: 0px auto; - margin-top: 23px; - - width: 443px; - height: 277px; - } - img { - max-width: 90%; - margin-top: 28px; - } - } - } - .top-right { - float: left; - width: 43%; - margin: 0 0.5%; - height: 330px; - background-color: rgba(253, 253, 253, 1); - position: relative; - border-radius: 2px; - overflow: hidden; - .summary { - height: 120px; - margin: 5px 5px 0 5px; - .icon { - margin: 0 10px; - margin-top: 8px; - float: left; - .baseImg { - max-width: 106px; - max-height: 106px; - } - } - - .right-desc { - float: left; - position: absolute; - left: 140px; - .name { - font-size: 28px; - - margin-bottom: 5px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - width: 250px; - } - .tags { - margin-bottom: 10px; - .el-tag { - margin-right: 10px; - } - } - } - } - .jihuo-input { - margin-left: 10px; - margin-bottom: 10px; - .el-input { - float: left; - width: 63%; - margin-bottom: 8px; - margin-right: 10px; - } - el-button { - float: left; - } - } - .product-intruduction { - height: 200px; - margin-top: 3px; - - .part-title { - display: block; - line-height: 20px; - - font-size: 16px; - margin-left: 24px; - border-bottom: 3px solid #3d68e1; - width: fit-content; - height: 26px; - margin-bottom: 8px; - } - .text { - height: 156px; - overflow: auto; - padding: 0 15px 0px 15px; - - .single-desc { - margin-bottom: 10px; - font-size: 13px; - } - } - } - } - } - .box-bottom { - margin-top: 8px; - - height: 240px; - .bot-left { - width: 49%; - height: 240px; - background-color: rgba(253, 253, 253, 1); - margin: 0 0.5%; - border-radius: 2px; - float: left; - .part-title { - display: block; - line-height: 35px; - font-size: 16px; - margin-left: 24px; - border-bottom: 3px solid #3d68e1; - width: fit-content; - margin-bottom: 10px; - - height: 33px; - } - .list-zone { - overflow: auto; - height: 190px; - padding: 0 20px; - .list-item { - .desc { - background-color: rgba(242, 242, 242, 1.3); - margin: 5px 12px 0 12px; - font-size: 12px; - line-height: 18px; - } - margin-bottom: 12px; - } - } - } - .bot-right { - height: 240px; - float: left; - background-color: rgba(253, 253, 253, 1); - width: 49%; - margin: 0 0.5%; - border-radius: 2px; - - .part-title { - display: block; - line-height: 35px; - font-size: 16px; - margin-left: 24px; - border-bottom: 3px solid #3d68e1; - width: fit-content; - margin-bottom: 5px; - height: 33px; - } - .item-zone { - overflow: auto; - height: 225px; - padding: 0px 12px; - - .item { - height: 165px; - width: 130px; - float: left; - border-radius: 10px; - box-shadow: 0px 5px 14px rgba(0, 0, 0, 0.0666666666666667); - position: relative; - - .el-tag { - float: right; - margin: 8px; - } - .icon { - margin: 0 auto; - img { - max-width: 60px; - max-height: 60px; - position: absolute; - top: 20%; - left: 26%; - } - .icon-name { - text-align: center; - position: absolute; - top: 61%; - left: 12%; - width: 100px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - font-size: 13px; - } - } - .look-button { - position: absolute; - left: 30%; - - top: 76%; - } - } - } - } - } - } - } -} -.flex-title { - display: flex; - justify-content: space-between; - align-items: center; + background-color: #fff; } -.el-loading-mask .el-loading-spinner { - top: 40px !important; -} -.el-loading-mask .el-loading-spinner svg { - transform: none !important; - top: 20px !important; - left: 40% !important; -} -.el-loading-mask .el-loading-spinner p.el-loading-text { - display: block !important; - text-align: center !important; - bottom: 10px !important; - top: 80px !important; - right: 0 !important; - color: #78adf7; -} -.el-loading-mask .el-loading-spinner .path { - stroke: #78adf7; -} -.installInfo { - text-indent: 2em; - font-size: 14px; - line-height: 26px; - p { - text-align: center; - } -} -.src-title { - //color: #bfbfbf; - color: #bbcee8; - font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC"; - font-weight: 650; - font-style: normal; - height: 36px; - font-size: 15px; - padding-left: 25px; -} -.update-badge .el-badge__content.is-fixed { - top: 10px; - right: 4px; -} -.empty-tip { - padding-left: 25px; - color: #ccc; -} .task-manage { height: 100%; .installModel { @@ -2000,7 +1020,7 @@ .progress-bar { width: 70%; height: 17px; - border-radius: 3px; + border-radius: 3pxd; background-color: rgb(227, 229, 231); position: absolute; top: 50%; @@ -2019,28 +1039,11 @@ } } } - .el-tab-pane { - height: auto !important; - } - .el-tabs--border-card > .el-tabs__content { - padding: 0 !important; - overflow: auto !important; - background-color: #fff; - } - .el-tabs__content { - padding: 0 !important; - overflow: auto !important; - } - //height: calc(100% - 10px); - // .super { - // .right-box { - // width: 58% !important; - // } - // } .super { width: 100%; height: 100%; + // caret-color: rgba(0, 0, 0, 0); .title { margin-bottom: 10px; line-height: 30px; @@ -2049,182 +1052,476 @@ color: #222222; } .left-box { - // width: 41%; height: 100%; box-sizing: border-box; - // float: left; - .el-drawer__header { - border-bottom: 2px solid #eee; - padding-bottom: 10px; - font-size: 16px; - margin-bottom: 0px; - span { - outline: none !important; - } - } - .action-bar { - margin-bottom: 30px; - .el-input { - width: 100%; - } - } - .task-list { - // background: #1c364a; - background: #fff; - padding: 20px; - box-sizing: border-box; - - .flex-list { - display: flex; - flex-direction: row; - flex-wrap: wrap; - min-height: 200px; - .wrap-box { - width: 11%; - } - .list-choose-item-left { - width: 80%; - height: auto; - margin: auto; - margin-bottom: 30px; - max-width: 150px; - .mask { - width: 100%; - - .el-button + .el-button { - margin-left: 0 !important; - } - } - } - } - } - .store-list, - .app-list { + .nav-box { + height: 200px; display: flex; - flex-wrap: wrap; - .wrap-box { - width: 11%; - margin-bottom: 30px; - .list-choose-item-left { - width: 80%; - height: auto; - margin: auto; - margin-bottom: 30px; - max-width: 150px; - } - .inner { - width: 80%; - box-sizing: border-box; - position: relative; + justify-content: space-between; + padding: 35px 60px; + position: relative; + .nav-box-menu { + width: 200px; + height: 200px; + z-index: 99; + .menu-item { font-size: 14px; - padding-bottom: 10px; - transition: all 1s; - background: #ffffff; - border: 1px solid #e2e2e2; - box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); - border-radius: 4px; - margin: auto; - .alg-icon { - position: relative; - width: 80%; - margin: auto; - padding-top: 80%; - svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); + line-height: 50px; + height: 50px; + letter-spacing: 0.5px; + color: #828282; + padding-left: 20px; + border-left: 3px solid #f3f6fc; + cursor: pointer; + caret-color: transparent; + sup { + background-color: #f52323; + font-size: 12px; + color: #fff; + height: 18px; + line-height: 18px; + padding: 0 3.5px; + border-radius: 50%; + } + } + .menu-item:hover { + font-weight: 600; + color: #333; + transition: all 0.15s; + } + .menu-item-actiove { + border-left: 3px solid #23d7ee; + font-weight: 700; + font-size: 16px; + color: #333; + } + } + .nav-box-search { + z-index: 99; + position: relative; + .all-scene { + position: absolute; + z-index: 100; + right: 64px; + + top: 10px; + font-size: 12px; + } + .el-input { + position: relative; + font-size: 12px; + border: 2px solid #f2f2f7; + border-radius: 20px; + .el-input__inner { + border: none; + height: 30px; + line-height: 30px; + padding: 0 12px; + } + .el-input-group__prepend { + border-right: 0; + border: none; + border-radius: 20px; + background: #fff; + padding: 0 0 0 15px; + + i { + font-weight: 600; + color: #333; + font-size: 16px; } } - .alg-name { - height: 20px; - text-align: center; - line-height: 20px; + .el-input-group--append .el-input__inner, + .el-input-group__prepend { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border: none; } - .mask { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.65); - backdrop-filter: blur(1px) brightness(100%); - text-align: center; - z-index: 1; - border-radius: 3px; - display: none; - svg { - position: absolute; - top: 49%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 33; + .el-input-group__append { + border-left: 0; + border: none; + border-radius: 20px; + width: 52px; + background: linear-gradient( + 180deg, + #ecfcfe 0%, + #ebf4fd 47.92%, + #f4f4fe 100% + ); + .el-input--suffix { + border: none; + .el-input__icon { + line-height: 30px; + } + .el-input__inner { + font-size: 12px; + font-weight: bold; + letter-spacing: 0.5px; + padding: 0 0px 0 30px; + color: #474747; + } + .el-input__suffix { + display: none; + } + } + .el-input__inner::placeholder { + color: rgb(71, 71, 71); + } + .el-select-dropdown { + min-width: 120px !important; + left: -26px !important; + background: rgba(236, 245, 253, 0.6); + border-radius: 2px; + border: none; + .el-select-dropdown__item { + height: 22px; + line-height: 22px; + font-size: 12px; + letter-spacing: 0.4px; + color: #333333; + .icon { + margin-right: 5px; + font-size: 15px; + } + } + .el-select-dropdown__item.hover, + .el-select-dropdown__item:hover { + background-color: #ebf4fd; + font-weight: 600; + } } } - &:hover { - .mask { - display: block; - } + .el-input-group__prepend .el-select { + display: inline-block; + margin: -10px -20px; + border: none; + border-radius: 20px; + background: linear-gradient( + 180deg, + #ecfcfe 0%, + #ebf4fd 47.92%, + #f4f4fe 100% + ); } + } + } + .bg-img-wrap { + position: absolute; + z-index: 1; + right: 0; + top: 41px; + height: 229px; + img { + height: 100%; } } } - .drawer-content { - font-family: "PingFangSC-Regular"; - .el-step__title.is-process { - border-color: #3d68e1 !important; - color: #3d68e1 !important; - font-family: Tahoma, Helvetica, Arial, "\5B8B\4F53", sans-serif; + .quick-path { + position: relative; + height: 200px; + margin: 0 60px; + z-index: 99; + background: linear-gradient( + 180deg, + #ecfcfe 0%, + #ebf4fd 47.92%, + #f4f4fe 100% + ); + border-radius: 4px; + height: 75px; + display: flex; + align-items: center; + .left-items { + display: flex; } - .el-step__head.is-process { - border-color: #3d68e1 !important; - color: #3d68e1 !important; - font-family: Tahoma, Helvetica, Arial, "\5B8B\4F53", sans-serif; - } - .el-input { - width: 100%; - margin-bottom: 30px; - } - .current-step { - margin: 40px 30px 30px; - } - .act-code { - padding: 0 30px; - p { - font-size: 15px; - margin-bottom: 16px; + .quick-item { + display: flex; + cursor: pointer; + padding: 2px 20px; + height: 52px; + box-sizing: border-box; + + .icon-img { + width: 48px; + height: 48px; + position: relative; + .icon { + position: absolute; + right: -7px; + top: -7px; + font-size: 13px; + } + img { + width: 48px; + height: 48px; + } + } + .desc { + box-sizing: border-box; + padding: 0 12px; + color: #828282; + width: 140px; + .desc-1 { + font-size: 14px; + font-weight: bold; + line-height: 26px; + height: 26px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + .desc-2 { + font-size: 12px; + } + } + .right-icon { + padding: 2px 0; + + .icon { + font-size: 21px; + } } } - .desc { - padding: 0 30px; - margin-bottom: 30px; - li { - border-bottom: 1px solid #eee; - height: 45px; - line-height: 45px; - font-size: 14px; - &:last-child { - border-bottom: none; + .quick-item:not(:last-child) { + border-right: 1px solid #e0e0e0; + } + .down-all-btn { + position: absolute; + right: 30px; + .el-button { + width: 78px; + font-size: 12px; + font-weight: 600; + padding: 3px 10px; + border: 1px solid #eef0f7; + } + } + } + .main-content { + padding: 35px 82px; + z-index: 99; + .main-title { + line-height: 25px; + font-size: 16px; + font-weight: 600; + margin-bottom: 10px; + } + .tab-btns { + display: flex; + justify-content: space-between; + .group-left { + display: flex; + .tab { + font-size: 14px; + margin-right: 25px; + line-height: 28px; + cursor: pointer; + color: #828282; } - label { - display: inline-block; - width: 90px; - padding-left: 14px; + .tab-active { + border-bottom: 2px solid #23d7ee; + color: #333333; font-weight: bold; } } - } - .text-right { - padding-right: 30px; - text-align: right; - .tip { - color: #999; - line-height: 38px; + + .batch-update { + display: flex; + align-items: center; + .el-button { + padding: 3px 12px; + background-color: #1dd4ec !important; + border-color: #1dd4ec !important; + border-radius: 22px; + } + .el-button--primary:hover { + background: #089fb3 !important; + border-color: #089fb3 !important; + } } } - } - .tab-content { - padding: 20px 20px; + .front-page-items { + padding-top: 25px; + .front-page-item { + float: left; + display: flex; + margin: 0 5px; + margin-bottom: 15px; + box-sizing: border-box; + width: 274px; + + justify-content: center; + cursor: pointer; + + padding: 10px 0; + height: 76px; + border-radius: 4px; + + /* &.disabled { + cursor: default; + } */ + + .icon-img { + width: 58px; + height: 58px; + position: relative; + .icon { + position: absolute; + right: -9px; + top: -9px; + font-size: 16px; + } + img { + width: 58px; + height: 58px; + border-radius: 10px; + } + } + .desc { + box-sizing: border-box; + padding: 0 12px; + width: 147px; + + .desc-1 { + font-size: 14px; + font-weight: bold; + color: #4f4f4f; + line-height: 28px; + height: 28px; + letter-spacing: 0.1px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + .desc-2 { + color: #828282; + font-size: 12px; + } + } + .right-btn { + padding: 2px 0; + width: 50px; + text-align: center; + position: relative; + .check-btn { + background-color: #ffffff !important; + border-color: #bdbdbd !important; + color: #333333; + } + .update-btn { + border-color: #23d7ee !important; + background-color: rgba(29, 212, 236, 0.1) !important; + color: #4f4f4f; + } + .other-btn { + background-color: #1dd4ec !important; + border-color: #1dd4ec !important; + color: #ffffff; + } + @keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } + .anz-font { + font-size: 28px; + color: #333; + } + + .spin-icon { + animation: spin 0.8s linear infinite; + } + .status { + font-size: 12px; + color: #828282; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 100px; + text-align: end; + position: absolute; + right: 0; + width: 120px; + margin-top: 2px; + } + .rocket-icon { + font-size: 20px; + } + .el-button { + padding: 3px 12px; + border-radius: 22px; + font-weight: bold; + letter-spacing: 0.5px; + } + } + } + .front-page-item:hover { + background-color: #f2f2f7; + } + .item-dimmed { + color: gray; + filter: grayscale(100%); + } + } + .front-page-items:after { + content: ""; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + .upload-pkg { + .upload-head { + display: flex; + justify-content: space-between; + align-items: center; + .left { + display: flex; + align-items: center; + .iconfont { + font-size: 18px; + margin-right: 6px; + } + .txt { + font-size: 16px; + } + } + .right { + .icon { + margin-right: 11px; + font-size: 17px; + cursor: pointer; + } + } + } + } + .upload-demo { + margin: 30px 0px; + .drag-txt { + width: 340px; + height: 45px; + border: 1px dashed #bdbdbd; + display: flex; + margin-top: 30px; + align-items: center; + justify-content: center; + color: #828282; + font-size: 14px; + } + .txt-btn { + width: 78px; + margin-top: 18px; + height: 19px; + background: #23d7ee; + border-radius: 22px; + color: #ffffff; + font-weight: bold; + font-size: 12px; + } + } } } .mask { @@ -2262,312 +1559,13 @@ } } - .text-css { - width: 100%; - overflow: hidden; - text-overflow: ellipsis; - } - .move-hear { - margin: 10px 0 0 0; - font-size: 5rem; - } - .list-choose-item { - cursor: pointer; - position: relative; - font-size: 14px; - display: inline-block; - @media screen and(min-width: 1640px) { - margin: 30px 20px 20px 20px; - } - @media screen and(min-width: 1460px) and(max-width: 1640px) { - margin: 30px 20px 20px 10px; - } - @media screen and(max-width: 1460px) { - margin: 30px 10px 20px 10px; - } - min-width: 126px; - height: 120px; - transition: all 1s; - background: #fff; - border: 1px solid #e2e2e2; - box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); - border-radius: 4px; - } - .list-choose-item:hover { - .mask { - display: block; - } - } - - .alg-shadow { - -webkit-box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3); - box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3); - } - .select-color { - margin-top: 16px; - text-align: center; - line-height: 28px; - // background-color: #3498DB; - } - .list-choose-item-left { - cursor: pointer; - position: relative; - font-size: 14px; - - transition: all 1s; - // background: #ffffff; - border-radius: 4px; - p { - display: none; - text-align: right; - width: 100%; - position: absolute; - right: 10px; - top: 5px; - } - .click-download { - position: absolute; - left: 80%; - top: 5%; - } - } - .list-choose-item-left:hover { - .mask { - display: flex; - align-items: flex-end; - flex-wrap: wrap; - justify-content: center; - top: 0; - - .bot-btn { - flex: 1; - } - &.flex-center { - align-items: center; - justify-content: center; - } - } - } - .list-choose-item-left-uninstal { - color: gray; - filter: grayscale(100%); - } - .list-complete-item.sortable-chosen { - background: #4ab7bd; - } - .list-choose-item.sortable-ghost { - background: #30b08f; - } - .width-new-line { - word-wrap: break-word; - word-break: break-all; - } - .dndList-list { - max-width: 40%; - } - .dic-border { - width: 98%; - min-height: 170px; - background: #fff; - padding: 10px 10px 10px 20px; - } - .min-h { - min-height: 130px; - } - .parent-div { - border-right: 1px solid rgba(24, 28, 33, 0.5); - max-width: 140px; - position: relative; - } - .list-choose-header { - position: relative; - width: 74px; - height: 74px; - background-image: linear-gradient(-137deg, #7076f2 0%, #3d63e1 100%); - box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); - border-radius: 37px; - margin: 10px 25px; - } - - .task-name-div { - font-family: PingFangSC-Medium; - font-size: 15px; - color: #4b68e6; - text-align: center; - margin-top: 6px; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .border-dash { - height: 30px; - width: 96%; - margin-bottom: 10px; - border: 1px dashed rgba(24, 28, 33, 0.5); - } - .i-setting { - position: absolute; - font-size: 28px; - margin-top: -25px; - margin-left: -30px; - } - .i-delete { - position: absolute; - font-size: 28px; - margin-top: -25px; - margin-left: -8px; - color: red; - } - .i-bell { - float: left; - position: relative; - left: 10px; - top: 10px; - font-size: 24px; - color: red; - } - .task-msg { - padding-left: 10px; - } - .b-top { - width: 100%; - padding-top: 10px; - } - .b-bottom { - width: 100%; - border-bottom: 1px solid rgba(24, 28, 33, 0.5); - } - .i-set-right { - position: absolute; - left: 80px; - top: -11px; - font-size: 24px; - } - .i-remove-right { - position: absolute; - right: -1px; - top: -11px; - font-size: 24px; - color: red; - } - .alg-t { - line-height: 31px; - font-family: PingFangSC-Medium; - font-size: 14px; - color: #222222; - } - .alg-name { - //margin-top: 12px; - line-height: 20px; - font-family: PingFangSC-Regular; - font-size: 14px; - letter-spacing: 0.05em; - color: #333; - // background-color: #ecf5ff; - .el-input { - position: relative; - font-size: 14px; - display: inline-block; - width: 100%; - } - } - .unit-class { - margin-left: 10px; - text-align: center; - line-height: 38px; - } .el-input { position: relative; font-size: 14px; - display: inline-block; - width: 80%; + // display: inline-block; + // width: 80%; } - .list-complete-item-handle { - height: 100%; - //padding-bottom: 10px; - text-align: center; - .svg-wrap { - //width: 80%; - width: 100%; - margin: auto; - padding-top: 80%; - padding-top: 100%; - position: relative; - box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); - border-radius: 25px; - svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - .baseImg { - width: 100%; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - max-height: 150px; - // max-width: 106px; - // max-height: 106px; - } - } - .willUpGrade { - .update-icon { - position: absolute; - top: -8px; - right: -8px; - z-index: 999; - } - .iconupdate { - color: #01e667; - position: absolute; - top: 5px; - right: 5px; - font-weight: 550; - font-size: 26px; - z-index: 999; - } - } - &.uninstall { - .svg-wrap { - filter: grayscale(100%); - } - .alg-name { - color: grey; - } - } - } - .dragAreaR { - height: 100%; - } - .drag-info { - min-width: 126px; - height: 120px; - border: 1px dashed #3d68e1; - box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); - // box-shadow: 0px 0px 10px 3px rgba(0,0,0,0.3); - border-radius: 4px; - margin: 30px 10px 20px 10px; - } - .drag-info-text { - letter-spacing: 3px; - line-height: 20px; - width: 80px; - height: 42px; - font-family: PingFangSC-Regular; - font-size: 13px; - color: #3d68e1; - text-align: center; - } - .task-edit { - font-size: 26px; - position: relative; - bottom: -6px; - } .el-button--cancle { background: #eaeaea; border-radius: 2px; @@ -2577,85 +1575,15 @@ color: #222222; margin-right: 12px; } - .click-changeImg { - cursor: pointer; - display: none; - background: rgba(0, 0, 0, 0.35); - width: 74px; - line-height: 20px; - color: rgb(255, 255, 255); - font-size: 14px; - opacity: 1; - border-radius: 6px; - } - - .task-name-google { - position: relative; - top: 30px; - width: 126px; - height: 120px; - border: 1px solid #fff; - background: #fff; - border-radius: 4px; - cursor: pointer; - .set-task { - display: none; - cursor: pointer; - } - - .el-switch__core { - width: 27px !important; - height: 14px; - } - .el-switch__core:after { - width: 10px; - height: 10px; - } - .el-switch.is-checked .el-switch__core::after { - left: 100%; - margin-left: -11px; - } - } - .task-name-google:hover { - .mask { - display: block; - } - } } } -.active-Dial { - .el-dialog { - min-width: 400px; - } - .dialog-active { - .desc { - padding: 0 30px; - margin-bottom: 30px; - li { - border-bottom: 1px solid #eee; - height: 45px; - line-height: 45px; - font-size: 14px; - &:last-child { - border-bottom: none; - } - label { - display: inline-block; - width: 90px; - padding-left: 14px; - font-weight: bold; - } - } - } - .text-right { - padding-right: 30px; - text-align: right; - .tip { - color: #999; - line-height: 38px; - } - } +@media screen and (max-width: 800px) { + .quick-path .left-items .quick-item:last-child { + display: none !important; + } + .quick-path .left-items .quick-item:nth-child(2) { + border: none !important; } } </style> diff --git a/src/pages/ai/index/api.ts b/src/pages/ai/index/api.ts index 371bbfc..7acc4d6 100644 --- a/src/pages/ai/index/api.ts +++ b/src/pages/ai/index/api.ts @@ -142,6 +142,14 @@ params: data }) } +export const uploadSDK = (data: any) => { + return request({ + url: "/data/api-v/sdk/upload", + method: "post", + data + }) +} + //瀹夎宸蹭笂浼犵殑绠楁硶鎺ュ彛 export const installSdk = (file: any) => { return request({ diff --git a/src/pages/ai/index/detail.vue b/src/pages/ai/index/detail.vue new file mode 100644 index 0000000..8eb62e4 --- /dev/null +++ b/src/pages/ai/index/detail.vue @@ -0,0 +1,1117 @@ +<template> + <div class="detail-page"> + <div class="detail-top"> + <div class="title-area"> + <div class="icon-img"> + <img v-if="productDetail.logoUrl" :src="productDetail.logoUrl" alt /> + </div> + <div class="right-info"> + <div class="right-info-1"> + <span class="name">{{ productDetail.productName }}</span> + <el-tag type="info" size="mini" color="#fff">{{ isSDKDetail ? "绠楁硶" : "搴旂敤" }}</el-tag> + </div> + <div class="right-info-2"> + <el-button size="mini" round class="update-btn" @click="upgradeSDKinWin" v-if="productDetail.isUpgrade" + >鏇存柊</el-button + > + <el-button size="mini" round v-if="!isSDKDetail && isActive" @click="openApp">鎵撳紑</el-button> + <el-button size="mini" round v-if="isActive && !isDefaultApp" @click="unloadSDKinWin">鍗歌浇</el-button> + <el-button + size="mini" + round + v-if="!isActive && (!detailPrice || showInstallNotActive)" + @click="downloadSdkInSide" + >瀹夎</el-button + > + <!-- suffix-icon="iconfont iconchushaixuanxiang" --> + <el-input + class="activeInput" + placeholder="璇疯緭鍏ユ縺娲荤爜" + size="mini" + clearable + :autofocus="true" + v-model="activeCode" + v-if="!isActive && !showInstallNotActive && detailPrice" + > + </el-input> + <el-button + size="mini" + round + class="act-btn" + v-if="!isActive && !showInstallNotActive && detailPrice" + @click="actived" + >婵�娲�</el-button + > + <!-- <span + class="icon iconfont" + v-if="!isActive && !showInstallNotActive" + @click="activeCode = ''" + ></span + > --> + </div> + </div> + <!-- <div class="back-btn" @click="goback"> + <span class="icon iconfont"></span> + <span class="back-text">杩斿洖</span> + </div> --> + </div> + <div class="text-area"> + <div class="text-line"> + <span class="icon iconfont"></span> + <span class="title">鐗堟湰锛�</span> + <span class="desc">{{ productDetail.productVersion }}</span> + </div> + <div class="text-line"> + <span class="icon iconfont"></span> + <span class="title">姒傝堪锛�</span> + <span class="desc">{{ productDetail.description || "鏆傛棤" }}</span> + </div> + <div class="text-line"> + <span class="icon iconfont"></span> + <span class="title">璇﹁堪锛�</span> + <span class="desc">{{ productDetail.summary || "鏆傛棤" }}</span> + </div> + </div> + </div> + <div class="detail-mid"> + <div class="mid-left"> + <div class="mid-title">{{ isSDKDetail ? "搴旂敤鍦烘櫙" : "鍔熻兘鐗圭偣" }}</div> + <div v-for="(item, index) in productDetail.funcInfo" :key="index" class="desc-item"> + <div class="title">{{ item.title }}</div> + <div class="desc">{{ item.desc }}</div> + </div> + </div> + <div class="mid-right"> + <el-carousel + trigger="click" + :autoplay="false" + indicator-position="none" + :arrow="productDetail.pics !== undefined ? (productDetail.pics.length > 1 ? 'always' : 'never') : 'never'" + > + <el-carousel-item v-for="(item, index) in productDetail.pics" :key="index"> + <img v-if="item.type != 'video'" :src="item.url" class="cursor-pointer" preview /> + <video v-if="item.type == 'video'" :src="'/httpImage/' + item.url" controls></video> + </el-carousel-item> + </el-carousel> + </div> + </div> + <div class="rec-bot"> + <div class="rec-title">{{ isSDKDetail ? "鎺ㄨ崘绠楁硶" : "鎺ㄨ崘搴旂敤" }}</div> + + <div class="rec-items"> + <div class="rec-item" v-for="(item, index) in otherProducts" :key="index" @click="checkInWindow(item)"> + <div class="icon-img"> + <img + v-if="item.iconBlob" + :src="item.iconBlob.indexOf(',') > 0 ? item.iconBlob : `data:image/png;base64,${item.iconBlob}`" + alt + /> + </div> + <div class="desc"> + <el-tooltip :content="item.name" effect="light"> + <div class="desc-1">{{ item.name }}</div> + </el-tooltip> + <div class="desc-2">鐗堟湰 {{ item.productVersion || "2.0.0" }}</div> + </div> + <div class="right-btn"> + <el-button size="small" type="primary" round @click="checkInWindow(item)">鏌ョ湅</el-button> + </div> + </div> + </div> + </div> + + <el-dialog :visible.sync="showActivateSuccess" title="婵�娲绘垚鍔燂紒" width="30%" class="active-Dial"> + <div class="dialog-active"> + <ul class="desc"> + <li> + <label>婵�娲荤爜:</label> + <span>{{ activedSdkOrApp.activateCode }}</span> + </li> + <li> + <label>浜у搧鍚嶇О:</label> + <span>{{ activedSdkOrApp.productName }}</span> + </li> + <li> + <label>閰嶇疆璇︽儏:</label> + <span>{{ activedSdkOrApp.setting }}</span> + </li> + <li> + <label>鏈嶅姟鍒版湡鏃�:</label> + <span>{{ activedSdkOrApp.expireTime }}</span> + </li> + <li> + <label>璁稿彲璇�:</label> + <span>{{ activedSdkOrApp.licence }}</span> + </li> + </ul> + <div class="text-right"> + <el-button type="primary" @click="checkMyAlgorith">纭畾</el-button> + <p class="tip">鎻愮ず锛氳鍦ㄢ�滃凡婵�娲烩�濅腑鏌ョ湅骞跺畨瑁呯畻娉�</p> + </div> + </div> + </el-dialog> + </div> +</template> +<script> +import { findAllSdk, downloadSdk, installSdk, getInstallInfo, removeSdk } from "./api" +import { + getApps, + installApp, + getAppDetail, + removeApp, + getUnActivedSdk, + actPageAlg, + getUnActivedApp, + actApp +} from "@/api/app" +import { getUrlKey } from "@/api/utils" +export default { + components: {}, + computed: { + updateNum() { + return this.hasNewVersionApp.length + this.hasNewVersionSdk.length + }, + isAdmin() { + if (sessionStorage.getItem("userInfo") && sessionStorage.getItem("userInfo") !== "") { + let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username + return loginName === "superadmin" || loginName === "basic" + } + + return false + } + }, + data() { + return { + installedList: [], + hasNewVersionSdk: [], + hasNewVersionApp: [], + notInstalledList: [], + buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [], + activeName: "myAlgorithm", + patchUpdateStatus: "", + downloadItem: "", + downloading: false, + actStep: 0, + showActivateSuccess: false, + activeCode: "", + isInstall: false, + installDialogVisible: false, + installAppPackage: null, + installSdkPackage: null, + isActive: true, + isDefaultApp: false, + unActivedSDKList: [], + unActivedAppList: [], + isSDKDetail: true, + actType: "", + actId: "", + select: "", + activedSdkOrApp: { + activateCode: "", + productName: "", + setting: "", + expireTime: "", + licence: "", + devIds: "" + }, + installedApps: [], + storeApps: [], + installFile: {}, + appUpgreading: false, + sdkUpgreading: false, + autoRefresh: true, + productDetailVisible: false, + isUpgrading: false, + productDetail: {}, + otherProducts: [], + backStack: [], + toUpdateArr: [], + toUpdateArr1: [], + forwardStack: [], + backDisable: true, + forwardDisable: true, + showInputCode: false, + needToUpgradeInWin: false, + showInstallNotActive: false + } + }, + props: { + detailType: { + type: String + }, + detailProductID: { + type: String + }, + detailPrice: {}, + isSdk: {} + }, + directives: { + focus: { + inserted: function(el) { + el.querySelector("input").focus() + } + } + }, + mounted() { + this.getDetail() + this.autoRefreshAppAndSdkState() + // this.getUnActivedList(); + // this.getUnActivedAppList(); + this.showBackBtn() + this.addBackListener() + }, + beforeDestroy() { + this.autoRefresh = false + this.hiddenBackBtn() + }, + methods: { + getDetail(id) { + getAppDetail({ id: id || this.detailProductID }) + .then((res) => { + if (res.success) { + this.productDetail = res.data.detail + this.otherProducts = res.data.randoms + + this.isSDKDetail = this.productDetail.productTypeName == "SDK" + this.isDefaultApp = this.productDetail.productBaseId.length < 10 + } else { + this.$message.error(res.msg) + } + }) + .catch((err) => { + this.$message.error(err.msg) + }) + this.isActive = this.detailType == "active" + this.showInstallNotActive = this.detailType == "activeNotInstall" + }, + goback() { + this.productDetail = {} + this.$emit("goback") + }, + isShow(authority) { + return this.isAdmin || this.buttonAuthority.indexOf("," + authority + ",") > -1 + }, + closeDial() { + this.productDetailVisible = false + this.productDetail = {} + this.otherProducts = [] + }, + + resetStack() { + this.forwardStack = [] + this.backStack = [] + this.backDisable = true + this.forwardDisable = true + }, + checkInWindow(item) { + getAppDetail({ id: item.id }).then((res) => { + this.productDetail = res.data.detail + this.productDetail.iconBlob = item.iconBlob + this.actId = this.productDetail.productBaseId + this.isSDKDetail = this.productDetail.productTypeName == "SDK" + this.isDefaultApp = this.productDetail.productBaseId.length < 10 + + this.otherProducts = res.data.randoms + }) + }, + checkIsDefOrNot(id) { + if (id.length > 10) { + this.isDefaultApp = false + } else { + this.isDefaultApp = true + } + }, + backwards() { + if (this.backStack.length == 0) { + this.backDisable = true + return + } + this.forwardStack.push([this.productDetail, this.otherProducts]) + let item = this.backStack.pop() + this.productDetail = item[0] + this.checkIsDefOrNot(this.productDetail.productBaseId) + this.otherProducts = item[1] + this.forwardDisable = false + if (this.backStack.length == 0) { + this.backDisable = true + } + }, + forwards() { + if (this.forwardStack.length == 0) { + this.forwardDisable = true + return + } + + this.backStack.push([this.productDetail, this.otherProducts]) + this.backDisable = false + let item = this.forwardStack.pop() + + this.productDetail = item[0] + this.otherProducts = item[1] + if (this.forwardStack.length == 0) { + this.forwardDisable = true + } + }, + //绂荤嚎瀹夎 + offlineInstall() { + this.installDialogVisible = false + this.isInstall = true + //瀹夎 + installSdk(this.installFile) + .then((res) => { + if (res.success) { + this.isInstall = false + this.$message({ + type: "success", + message: '瀹夎鎴愬姛,灏嗚烦杞嚦"宸叉縺娲�"涓煡鐪�' + }) + setTimeout(() => { + this.getAllSdk() + window.parent.postMessage( + { + msg: "AppUpdate" + }, + "*" + ) + this.activeName = "myAlgorithm" + }, 3000) + } + }) + .catch((e) => { + console.log(e) + this.isInstall = false + this.$message({ + type: "error", + message: e.msg + }) + }) + }, + downloadApp(app, action) { + if (action == "upgrade") { + app.upgradeLoading = true + } else { + app.installLoading = true + } + let _this = this + + installApp({ path: app.id }) + .then((res) => { + if (res && res.success) { + _this.$notify({ + title: "鎴愬姛", + message: "瀹夎搴旂敤鎴愬姛", + type: "success" + }) + setTimeout(() => { + if (action == "upgrade") { + app.upgradeLoading = false + } else { + app.installLoading = false + } + window.parent.postMessage( + { + msg: "AppUpdate" + }, + "*" + ) + }, 3000) + } else { + } + }) + .catch((e) => { + _this.$notify({ + title: "瀹夎澶辫触", + message: e.data, + type: "warning" + }) + if (action == "upgrade") { + app.upgradeLoading = false + } else { + app.installLoading = false + } + }) + + // 寮�鍚嚜鍔ㄥ埛鏂� + this.appUpgreading = true + }, + async getAllApps() { + let iArry = [], + sArry = [], + nArry = [] + let rsp = await getApps() + if (rsp && rsp.success) { + // 閬嶅巻app鐨勮繃绋嬮噸缃� + this.appUpgreading = false + + rsp.data.forEach((item) => { + let obj = Object.assign({ unloadLoading: false, upgradeLoading: false }, item) + if (obj.progressMsg !== "" && obj.progressMsg !== "宸插畨瑁�") { + obj.upgradeLoading = true + this.appUpgreading = true + } + + if (obj.upgradeDone) { + this.$notify({ + type: "success", + message: 1 ? "绠楁硶瀹夎鎴愬姛" : "绠楁硶鍗囩骇鎴愬姛" + }) + } + + item.installed ? iArry.push(obj) : sArry.push(obj) + item.isUpgrade && nArry.push(obj) + }) + } + this.installedApps = iArry + this.storeApps = sArry + this.hasNewVersionApp = nArry + }, + unLoad(app) { + let _this = this + this.$confirm("纭畾瑕佸嵏杞借搴旂敤鍚�?", "鎻愮ず") + .then(() => { + _this.productDetailVisible = false + app.unloadLoading = true + removeApp({ appId: app.id }) + .then((res) => { + if (res && res.success) { + app.unloadLoading = false + this.$emit("flushApp") + window.parent.postMessage( + { + msg: "AppUpdate" + }, + "*" + ) + _this.$notify({ + title: "鎴愬姛", + message: "鍗歌浇搴旂敤鎴愬姛", + type: "success" + }) + this.goback() + } + }) + .catch((e) => { + app.unloadLoading = false + }) + }) + .catch((e) => {}) + }, + actSdkOrApp(item, type = "sdk") { + this.checkDetail(item, "inactive") + this.actType = type + this.actId = item.id + this.actStep = 0 + this.activeCode = "" + this.activedSdkOrApp = this.newActInfo() + }, + cancelActivate() { + this.showInputCode = false + this.activeCode = "" + }, + newActInfo() { + return { + activateCode: "", + productName: "", + setting: "", + expireTime: "", + licence: "", + devIds: "" + } + }, + getUnActivedList() { + getUnActivedSdk().then((res) => { + if (res.code == 200) { + this.unActivedSDKList = res.data + } + }) + }, + getUnActivedAppList() { + getUnActivedApp().then((res) => { + if (res.code == 200) { + this.unActivedAppList = res.data + } + }) + }, + actived() { + let _this = this + if (this.activeCode.trim() == "") { + this.$notify({ + type: "error", + message: "婵�娲荤爜涓嶈兘涓虹┖" + }) + return + } + if (this.isSdk) { + //婵�娲荤畻娉� + actPageAlg(this.detailProductID, this.activeCode) + .then((res) => { + if (res.data.isSuccess) { + this.productDetailVisible = false + _this.activedSdkOrApp = res.data.successMsg + this.showActivateSuccess = true + _this.actStep++ + _this.getUnActivedList() + _this.getAllSdk() + } else { + _this.$notify({ + type: "error", + message: res.data.failMsg.failMsg + }) + } + }) + .catch((e) => { + this.$notify({ + type: "error", + message: e.msg + }) + }) + } else { + //婵�娲诲簲鐢� + actApp(this.detailProductID, this.activeCode) + .then((res) => { + if (res.data.isSuccess) { + this.productDetailVisible = false + _this.activedSdkOrApp = res.data.successMsg + this.showActivateSuccess = true + _this.actStep++ + _this.getUnActivedAppList() + _this.getAllApps() + } else { + _this.$notify({ + type: "error", + message: res.data.failMsg.failMsg + }) + } + }) + .catch((e) => { + this.$notify({ + type: "error", + message: e.msg + }) + }) + } + }, + checkMyAlgorith() { + this.showActivateSuccess = false + this.goback() + this.activeName = "宸叉縺娲�" + }, + onFileUpload(file) { + this.patchFile = { ...file } + this.fileAdded = true + const h = this.$createElement + //涓婁紶瀹屾垚鑾峰彇瀹夎淇℃伅 + let _this = this + getInstallInfo(file) + .then((res) => { + _this.installFile = file + if (res.success) { + _this.installDialogVisible = true + if (res.data.apps.length > 0) { + _this.installAppPackage = { + appId: res.data.apps[0].appId, + version: res.data.apps[0].version, + productName: res.data.productName, + installContent: res.data.apps[0].installContent + } + } + if (res.data.sdks.length > 0) { + _this.installSdkPackage = { + appId: res.data.sdks[0].sdkId, + version: res.data.sdks[0].version, + productName: res.data.productName, + installContent: res.data.sdks[0].installContent + } + } + } else { + this.$message({ + type: "error", + message: res.msg + }) + } + }) + .catch((e) => { + this.$message({ + type: "error", + message: e.msg + }) + }) + }, + openApp() { + window.parent.postMessage({ msg: "toOpenApp?" + this.productDetail.productBaseId }, "*") + }, + onFileAdded(f) { + this.patchUpdateStatus = "" + }, + async getAllSdk() { + let installedList = [] + let unInstalledList = [] + let hasNewVersionList = [] + let res = await findAllSdk() + if (res && res.success) { + this.sdkUpgreading = false + + res.data.forEach((item) => { + let obj = Object.assign({ unloadLoading: false, upgradeLoading: false }, item) + if (obj.progressMsg !== "" && obj.progressMsg !== "宸插畨瑁�") { + obj.upgradeLoading = true + this.sdkUpgreading = true + } + + //绠楁硶杞欢 宸插畨瑁呭叾涓寘鍚緟鍗囩骇 鏈畨瑁� + item.installed ? installedList.push(obj) : unInstalledList.push(obj) + item.isUpgrade ? hasNewVersionList.push(obj) : null + }) + } + this.installedList = installedList + this.notInstalledList = unInstalledList + this.toUpdateArr = this.installedList.slice(0, 4) + this.hasNewVersionSdk = hasNewVersionList + }, + unloadSDKinWin() { + let appToUnload + let sdkToUnload + if (this.productDetail.productTypeName == "搴旂敤") { + appToUnload = this.installedApps.find((item) => { + return item.id == this.productDetail.productBaseId + }) + this.unLoad(appToUnload) + } else { + sdkToUnload = this.installedList.find((item) => { + return item.id == this.productDetail.productBaseId + }) + this.unLoadSdk(sdkToUnload) + } + }, + //鍗歌浇绠楁硶 + unLoadSdk(sdk) { + let _this = this + this.$confirm("纭畾瑕佸嵏杞借绠楁硶鍚�?", "鎻愮ず") + .then(() => { + _this.productDetailVisible = false + sdk.unloadLoading = true + removeSdk({ sdkId: sdk.id }) + .then((res) => { + if (res && res.success) { + sdk.unloadLoading = false + this.$notify.success("鍗歌浇瀹屾垚") + // _this.getAllSdk(); + this.$emit("flushSdk") + window.parent.postMessage({ msg: "AppUpdate" }, "*") + this.goback() + } + }) + .catch((e) => { + console.log(e) + sdk.unloadLoading = false + }) + }) + .catch((e) => { + console.log("鍙栨秷", e) + }) + }, + upgradeSDKinWin() { + this.isUpgrading = !this.isUpgrading + if (this.productDetail.productTypeName == "搴旂敤") { + installApp({ path: this.productDetail.productBaseId }) + .then((res) => { + if (res && res.success) { + this.$notify.success("鍗囩骇瀹屾垚") + this.needToUpgradeInWin = false + this.productDetail.isUpgrade = false + this.isUpgrading = !this.isUpgrading + } + }) + .catch((e) => { + this.$notify.error("鍗囩骇澶辫触") + this.isUpgrading = !this.isUpgrading + }) + + // 寮�鍚嚜鍔ㄥ埛鏂� + this.appUpgreading = true + } else { + downloadSdk({ path: this.productDetail.productBaseId }) + .then((res) => { + this.needToUpgradeInWin = false + this.productDetail.isUpgrade = false + this.isUpgrading = !this.isUpgrading + this.$notify.success("鍗囩骇瀹屾垚") + }) + .catch((err) => { + this.$notify.error("鍗囩骇澶辫触") + this.isUpgrading = !this.isUpgrading + }) + this.sdkUpgreading = true + } + }, + downloadSdkInSide() { + this.downloadItem = this.productDetail.productBaseId + this.isUpgrading = true + downloadSdk({ path: this.productDetail.productBaseId }) + .then((rsp) => { + this.productDetailVisible = false + this.downloadItem = "" + this.$notify.success("绠楁硶宸插畨瑁�") + this.isUpgrading = false + }) + .catch((err) => { + this.$notify.warning(err.data) + this.downloadItem = "" + this.isUpgrading = false + }) + // 寮�鍚嚜鍔ㄥ埛鏂� + this.sdkUpgreading = true + }, + donwload(item, typ) { + item.upgradeLoading = true + this.downloadItem = item.id + downloadSdk({ path: item.id }) + .then((rsp) => { + item.upgradeLoading = false + this.downloadItem = "" + window.parent.postMessage( + { + msg: "AppUpdate" + }, + "*" + ) + }) + .catch((err) => { + this.$notify({ + type: "warning", + message: err.data + }) + item.upgradeLoading = false + this.downloadItem = "" + }) + // 寮�鍚嚜鍔ㄥ埛鏂� + this.sdkUpgreading = true + }, + inputBlur(item) { + this.$set(item, "isEdit", false) + }, + autoRefreshAppAndSdkState() { + this.getAllApps() + this.getAllSdk() + if (!this.autoRefresh) { + return + } + setTimeout(() => { + if (this.appUpgreading) { + this.getAllApps() + } + if (this.sdkUpgreading) { + this.getAllSdk() + } + }, 1000) + }, + showBackBtn() { + window.parent.postMessage( + { + msg: "showBack" + }, + "*" + ) + }, + hiddenBackBtn() { + window.parent.postMessage( + { + msg: "hiddenBack" + }, + "*" + ) + }, + addBackListener() { + window.addEventListener("message", (e) => { + if (e.data.msg === "杩斿洖搴旂敤涓績") { + this.goback() + } + }) + } + } +} +</script> +<style lang="scss"> +.detail-page { + width: 100% !important; + height: 100%; + box-sizing: border-box; + text-align: left; + // min-width: 1106px; + .detail-top { + padding: 35px 60px; + padding-bottom: 20px; + border-bottom: 3px solid #f2f2f2; + .title-area { + display: flex; + margin-bottom: 10px; + position: relative; + .back-btn { + position: absolute; + right: 0; + top: 0; + width: 51px; + height: 20px; + line-height: 20px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + .icon { + margin-right: 3px; + font-size: 18px; + } + .back-text { + font-size: 14px; + letter-spacing: 0.5px; + } + } + .icon-img { + height: 60px; + width: 60px; + margin-right: 20px; + img { + width: 60px; + height: 60px; + } + } + .right-info { + .right-info-1 { + display: flex; + align-items: center; + margin-bottom: 10px; + + .name { + font-size: 16px; + font-weight: bold; + letter-spacing: 0.5px; + line-height: 26px; + margin-right: 12px; + } + .el-tag { + line-height: 18px; + height: 18px; + padding: 0 5px; + color: #bdbdbd; + border: 1px solid #e0e0e0; + } + } + .right-info-2 { + display: flex; + align-items: center; + .activeInput { + .el-input__suffix { + display: flex; + align-items: center; + .el-input__suffix-inner { + border-color: none; + .el-icon-circle-close:before { + content: "\e79d" !important; + font-size: 14px; + } + } + } + } + .iconfont { + margin-left: 10px; + font-size: 15px; + cursor: pointer; + } + .el-input { + margin-right: 12px; + width: 224px; + font-size: 12px; + .el-input__inner { + border: 1px solid #bdbdbd; + border-radius: 20px; + height: 22px; + line-height: 22px; + } + } + .el-button { + padding: 3px 13px; + color: #4f4f4f; + font-weight: bold; + letter-spacing: 0.5px; + background: #f2f2f7; + border: 1px solid #f2f2f7; + } + .update-btn { + border-color: #23d7ee; + background-color: rgba(29, 212, 236, 0.1); + } + .act-btn { + background: #23d7ee; + border: 1px solid #23d7ee; + color: #f2f2f2; + } + // .act-btn:hover { + // background: #089fb3 !important; + // border-color: #089fb3 !important; + // } + // .el-button:hover { + // border-color: #23d7ee; + // background-color: rgba(29, 212, 236, 0.1); + // } + .el-button + .el-button { + margin-left: 12px; + } + } + } + } + .text-area { + .text-line { + line-height: 17px; + height: 25px; + .icon { + font-size: 14px; + margin-right: 4px; + } + .title { + font-size: 12px; + font-weight: bold; + letter-spacing: 0.5px; + } + .desc { + letter-spacing: 0.5px; + } + } + } + } + .detail-mid { + padding: 20px 60px; + display: flex; + justify-content: space-between; + border-bottom: 3px solid #f2f2f2; + .mid-left { + max-width: 560px; + + .mid-title { + font-size: 16px; + font-weight: bold; + letter-spacing: 0.5px; + line-height: 26px; + margin-bottom: 10px; + } + .desc-item { + margin-bottom: 10px; + + .title { + display: inline-block; + line-height: 20px; + padding: 0px 10px; + letter-spacing: 0.5px; + font-size: 12px; + color: #828282; + font-weight: bold; + border: 1px solid #e0e0e0; + box-sizing: border-box; + border-radius: 22px; + } + .desc { + margin-left: 20px; + color: #4f4f4f; + font-size: 12px; + line-height: 17px; + } + } + } + .mid-right { + width: 460px; + .el-carousel__container { + position: relative; + height: 280px; + .el-carousel__item { + display: flex; + align-items: center; + img { + width: 100%; + } + } + } + .imgwrap { + img { + width: 100%; + } + } + } + } + .rec-bot { + padding: 20px 60px; + .rec-title { + font-size: 16px; + font-weight: bold; + letter-spacing: 0.5px; + line-height: 26px; + margin-bottom: 20px; + } + } + .rec-items { + .rec-item { + cursor: pointer; + float: left; + display: flex; + margin: 0 15px; + margin-bottom: 30px; + padding: 2px 0; + height: 62px; + box-sizing: border-box; + width: 248px; + .icon-img { + width: 58px; + height: 58px; + img { + width: 58px; + height: 58px; + } + } + .desc { + box-sizing: border-box; + padding: 0 12px; + + width: 100%; + .desc-1 { + font-size: 14px; + font-weight: bold; + line-height: 28px; + width: 116px; + height: 28px; + letter-spacing: 0.1px; + color: #4f4f4f; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + .desc-2 { + font-size: 12px; + color: #828282; + } + } + .right-btn { + padding: 5px 0; + .el-button { + padding: 3px 12px; + border-radius: 22px; + background-color: #f2f2f7 !important; + border-color: #f2f2f7 !important; + color: #4f4f4f; + font-size: 12px; + font-weight: bold; + } + // .el-button--primary:hover { + // background: #089fb3 !important; + // border-color: #089fb3 !important; + // } + } + } + } + .rec-items:after { + content: ""; + display: block; + height: 0; + clear: both; + visibility: hidden; + } +} +</style> diff --git a/src/pages/ai/index/mixins.ts b/src/pages/ai/index/mixins.ts deleted file mode 100644 index e69de29..0000000 --- a/src/pages/ai/index/mixins.ts +++ /dev/null diff --git a/src/pages/desktop/index/components/ToolsEntry.vue b/src/pages/desktop/index/components/ToolsEntry.vue index a69a0af..34a4eae 100644 --- a/src/pages/desktop/index/components/ToolsEntry.vue +++ b/src/pages/desktop/index/components/ToolsEntry.vue @@ -185,7 +185,7 @@ if (dock.type === "1") { window.open(dock.url) } else if (dock.type === "2" && !dock.isOpen) { - if (dock.url == "/view/debuggTool/") { + if ((dock.url).indexOf('/view/debuggTool')>=0||(dock.url).indexOf('/view/knowledge')>=0) { return true } this.$store.dispatch("desktop/addFrame", { -- Gitblit v1.8.0