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>&nbsp;&nbsp;{{ 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">&#xe712;</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">&#xe703;</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">&#xe713;</span>
+                      <span>閾佽矾鍦烘櫙</span>
+                    </el-option>
+                    <el-option label="瀹夊叏鍦烘櫙" value="2">
+                      <span class="icon iconfont">&#xe702;</span>
+                      <span>瀹夊叏鍦烘櫙</span>
+                    </el-option>
+                    <el-option label="閫氱敤鍦烘櫙" value="3">
+                      <span class="icon iconfont">&#xe70d;</span>
+                      <span>閫氱敤鍦烘櫙</span>
+                    </el-option>
+                    <el-option label="鏍″洯鍥尯" value="4">
+                      <span class="icon iconfont">&#xe70e;</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"
+                      >&#xe72a;</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">&#xe71a;</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"
+                      >&#xe72a;</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
+                      "
+                      >&#xe70c;</span
+                    >
+                    <span
+                      class="icon iconfont rocket-icon"
+                      v-if="
+                        activeName == '鏇存柊' &&
+                        item.isUpgrade &&
+                        item.upgradeLoading &&
+                        !rocketIf
+                      "
+                      >&#xe717;</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"
+                        >&#xe70a;</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">&#xe754;</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>&#60;</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 = ''"
+              >&#xe6cb;</span
+            > -->
+          </div>
+        </div>
+        <!-- <div class="back-btn" @click="goback">
+          <span class="icon iconfont">&#xe680;</span>
+          <span class="back-text">杩斿洖</span>
+        </div> -->
+      </div>
+      <div class="text-area">
+        <div class="text-line">
+          <span class="icon iconfont">&#xe710;</span>
+          <span class="title">鐗堟湰锛�</span>
+          <span class="desc">{{ productDetail.productVersion }}</span>
+        </div>
+        <div class="text-line">
+          <span class="icon iconfont">&#xe75b;</span>
+          <span class="title">姒傝堪锛�</span>
+          <span class="desc">{{ productDetail.description || "鏆傛棤" }}</span>
+        </div>
+        <div class="text-line">
+          <span class="icon iconfont">&#xe716;</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