diff --git a/im-platform/src/main/java/com/bx/implatform/controller/FileController.java b/im-platform/src/main/java/com/bx/implatform/controller/FileController.java index 91b3ab9..204f639 100644 --- a/im-platform/src/main/java/com/bx/implatform/controller/FileController.java +++ b/im-platform/src/main/java/com/bx/implatform/controller/FileController.java @@ -8,6 +8,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -26,6 +27,7 @@ public class FileController { return ResultUtils.success(fileService.uploadImage(file)); } + @CrossOrigin @ApiOperation(value = "上传文件", notes = "上传文件,上传后返回文件url") @PostMapping("/file/upload") public Result uploadFile(MultipartFile file) { diff --git a/im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java b/im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java index 590de81..f703960 100644 --- a/im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java +++ b/im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java @@ -29,7 +29,10 @@ public class GlobalExceptionHandler { public Result handleException(Exception e) { if (e instanceof GlobalException) { GlobalException ex = (GlobalException) e; - log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e); + // token过期是正常情况,不打印 + if(!ex.getCode().equals(ResultCode.INVALID_TOKEN.getCode())){ + log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e); + } return ResultUtils.error(ex.getCode(), ex.getMessage()); } else if (e instanceof UndeclaredThrowableException) { GlobalException ex = (GlobalException) e.getCause(); diff --git a/im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java b/im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java index bf6b9a4..d964cd5 100644 --- a/im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java +++ b/im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java @@ -36,14 +36,15 @@ public class AuthInterceptor implements HandlerInterceptor { log.error("未登陆,url:{}", request.getRequestURI()); throw new GlobalException(ResultCode.NO_LOGIN); } + String strJson = JwtUtil.getInfo(token); + UserSession userSession = JSON.parseObject(strJson, UserSession.class); //验证 token if (!JwtUtil.checkSign(token, jwtProperties.getAccessTokenSecret())) { - log.error("token已失效,url:{}", request.getRequestURI()); + log.error("token已失效,用户:{}", userSession.getUserName()); + log.error("token:{}", token); throw new GlobalException(ResultCode.INVALID_TOKEN); } // 存放session - String strJson = JwtUtil.getInfo(token); - UserSession userSession = JSON.parseObject(strJson, UserSession.class); request.setAttribute("session", userSession); return true; } diff --git a/im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java b/im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java index 0ba44b2..bd0da21 100644 --- a/im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java +++ b/im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java @@ -87,8 +87,9 @@ public class MinioUtil { } String objectName = DateTimeUtils.getFormatDate(new Date(), DateTimeUtils.PARTDATEFORMAT) + "/" + fileName; try { + InputStream stream = new ByteArrayInputStream(file.getBytes()); PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(path + "/" + objectName) - .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); + .stream(stream, file.getSize(), -1).contentType(file.getContentType()).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); } catch (Exception e) { diff --git a/im-ui/src/api/httpRequest.js b/im-ui/src/api/httpRequest.js index d3d0dd5..1f9849e 100644 --- a/im-ui/src/api/httpRequest.js +++ b/im-ui/src/api/httpRequest.js @@ -7,10 +7,7 @@ import { const http = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 1000 * 30, - withCredentials: true, - headers: { - 'Content-Type': 'application/json; charset=utf-8' - } + withCredentials: true }) /** @@ -53,10 +50,6 @@ http.interceptors.response.use(async response => { // 保存token sessionStorage.setItem("accessToken", data.accessToken); sessionStorage.setItem("refreshToken", data.refreshToken); - // 这里需要把headers清掉,否则请求时会报错,原因暂不详... - if(typeof response.config.data != 'object'){ - response.config.headers=undefined; - } // 重新发送刚才的请求 return http(response.config) } else { diff --git a/im-ui/src/components/chat/ChatBox.vue b/im-ui/src/components/chat/ChatBox.vue index 9919f97..3a8c163 100644 --- a/im-ui/src/components/chat/ChatBox.vue +++ b/im-ui/src/components/chat/ChatBox.vue @@ -336,6 +336,7 @@ } let msgInfo = { id: 0, + tmpId: this.generateId(), fileId: file.uid, sendId: this.mine.id, content: JSON.stringify(data), @@ -391,6 +392,7 @@ } let msgInfo = { id: 0, + tmpId: this.generateId(), sendId: this.mine.id, content: JSON.stringify(data), sendTime: new Date().getTime(), @@ -738,7 +740,6 @@ }); }, refreshPlaceHolder() { - console.log("placeholder") if (this.isReceipt) { this.placeholder = "【回执消息】" } else if (this.$refs.editBox && this.$refs.editBox.innerHTML) { @@ -746,7 +747,10 @@ } else { this.placeholder = "聊点什么吧~"; } - + }, + generateId(){ + // 生成临时id + return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000)); } }, computed: { diff --git a/im-ui/src/components/common/FileUpload.vue b/im-ui/src/components/common/FileUpload.vue index e66c0c9..5284adf 100644 --- a/im-ui/src/components/common/FileUpload.vue +++ b/im-ui/src/components/common/FileUpload.vue @@ -1,6 +1,6 @@ @@ -49,7 +49,6 @@ background: 'rgba(0, 0, 0, 0.7)' }); } - let formData = new FormData() formData.append('file', file.file) this.$http({ @@ -82,7 +81,6 @@ this.$message.error(`文件大小不能超过 ${this.fileSizeStr}!`); return false; } - this.$emit("before", file); return true; } diff --git a/im-ui/src/store/chatStore.js b/im-ui/src/store/chatStore.js index b8e8774..81f199d 100644 --- a/im-ui/src/store/chatStore.js +++ b/im-ui/src/store/chatStore.js @@ -318,9 +318,9 @@ export default { if (msgInfo.id && chat.messages[idx].id == msgInfo.id) { return chat.messages[idx]; } - // 正在发送中的消息可能没有id,通过发送时间判断 - if (msgInfo.selfSend && chat.messages[idx].selfSend && - chat.messages[idx].sendTime == msgInfo.sendTime) { + // 正在发送中的消息可能没有id,只有tmpId + if (msgInfo.tmpId && chat.messages[idx].tmpId && + chat.messages[idx].tmpId == msgInfo.tmpId) { return chat.messages[idx]; } } diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 7bd7d24..72cb7d5 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -1,6 +1,7 @@ diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue index bb906e7..1988662 100644 --- a/im-uniapp/pages/chat/chat-box.vue +++ b/im-uniapp/pages/chat/chat-box.vue @@ -61,8 +61,7 @@ 拍摄 - - + @@ -70,7 +69,7 @@ 文件 - + 语音消息 @@ -331,7 +330,7 @@ } }, scrollToBottom() { - let size = this.chat.messages.length; + let size = this.messageSize; if (size > 0) { this.scrollToMsgIdx(size - 1); } @@ -391,6 +390,7 @@ } let msgInfo = { id: 0, + tmpId: this.generateId(), fileId: file.uid, sendId: this.mine.id, content: JSON.stringify(data), @@ -441,6 +441,7 @@ } let msgInfo = { id: 0, + tmpId: this.generateId(), sendId: this.mine.id, content: JSON.stringify(data), sendTime: new Date().getTime(), @@ -537,7 +538,6 @@ } }, fail(e) { - console.log(e); uni.showToast({ title: "文件下载失败", icon: "none" @@ -550,7 +550,6 @@ console.log("消息已滚动到顶部") return; } - // #ifndef H5 // 防止滚动条定格在顶部,不能一直往上滚 this.scrollToMsgIdx(this.showMinIdx); @@ -591,7 +590,6 @@ }); }, readedMessage() { - console.log("readedMessage") if (this.unreadCount == 0) { return; } @@ -642,6 +640,10 @@ let info = uni.getSystemInfoSync() let px = info.windowWidth * rpx / 750; return Math.floor(rpx); + }, + generateId(){ + // 生成临时id + return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000)); } }, computed: { @@ -669,6 +671,9 @@ return this.chat.messages.length; }, unreadCount() { + if (!this.chat || !this.chat.unreadCount) { + return 0; + } return this.chat.unreadCount; }, atUserItems() { @@ -693,7 +698,6 @@ messageSize: function(newSize, oldSize) { // 接收到消息时滚动到底部 if (newSize > oldSize) { - console.log("messageSize",newSize,oldSize) let pages = getCurrentPages(); let curPage = pages[pages.length-1].route; if(curPage == "pages/chat/chat-box"){ @@ -716,7 +720,7 @@ // 聊天数据 this.chat = this.$store.state.chatStore.chats[options.chatIdx]; // 初始状态只显示20条消息 - let size = this.chat.messages.length; + let size = this.messageSize; this.showMinIdx = size > 20 ? size - 20 : 0; // 消息已读 this.readedMessage() diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index 3641d21..a89fae7 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -380,9 +380,10 @@ export default { if (msgInfo.id && chat.messages[idx].id == msgInfo.id) { return chat.messages[idx]; } - // 正在发送中的消息可能没有id,通过发送时间判断 - if (msgInfo.selfSend && chat.messages[idx].selfSend && - chat.messages[idx].sendTime == msgInfo.sendTime) { + // 正在发送中的消息可能没有id,只有tmpId + if (msgInfo.tmpId && chat.messages[idx].tmpId && + chat.messages[idx].tmpId == msgInfo.tmpId) { + console.log("chat.messages[idx].tmpId == msgInfo.tmpId") return chat.messages[idx]; } } diff --git a/im-uniapp/uni_modules/lsj-upload/changelog.md b/im-uniapp/uni_modules/lsj-upload/changelog.md new file mode 100644 index 0000000..090bca0 --- /dev/null +++ b/im-uniapp/uni_modules/lsj-upload/changelog.md @@ -0,0 +1,120 @@ +## 2.3.2(2024-06-13) +问题修复:2.3.1版本引起的部分设备不支持findLastIndex问题 +## 2.3.1(2024-05-20) +修复:文件不去重时返回文件列表name与组件内置列表key不一致问题。 +## 2.3.0(2024-05-20) +优化:1:增加属性distinct【选择文件是否去重】、2:对show/hide函数增加uni.$emit事件监听,若页面存在多个上传组件时,可通过uni.$emit控制所有上传组件webview透明层是否显示。 +## 2.2.9(2023-06-01) +优化:将是否多选与count字段解绑(原逻辑是count>1为允许多选),改为新增multiple属性控制是否多选。 +## 2.2.8(2023-06-01) +修复上版本提交时accept测试值未删除导致h5端只能选择图片的问题。 +## 2.2.7(2023-05-06) +应群友建议,当instantly为true时,触发change事件后延迟1000毫秒再自动上传,方便动态修改参数,其实个人还是建议想在change事件动态设置参数的伙伴将instantly设置为false,修改参数后手动调用upload() +## 2.2.6(2023-02-09) +修复多个文件同时选择时返回多次change回调的问题 +## 2.2.5(2022-12-27) +1.修复多选文件时未能正常校验数量的问题; +2.app端与H5端支持单选或多选文件,通过count数量控制,超过1开启多选。 +## 2.2.4(2022-12-27) +1.修复多选文件时未能正常校验数量的问题; +2.app端修复多选只取到第一个文件的问题。 +## 2.2.3(2022-12-06) +修复手动调用show()导致count失效的问题 +## 2.2.2(2022-12-01) +Vue3自行修改兼容 +## 2.2.1(2022-10-19) +修复childId警告提示 +## 2.2.0(2022-10-10) +更新app端webview窗口参数clidId,默认值添加时间戳保证唯一性 +## 2.1.9(2022-07-13) +[修复] app端选择文件后初始化设置的文件列表被清空问题 +## 2.1.8(2022-07-13) +[新增] ref方法初始化文件列表,用于已提交后再次编辑时需带入已上传文件:setFiles(files),可传入数组或Map对象,传入格式请与组件选择返回格式保持一致,且name为必须属性。 +## 2.1.7(2022-07-12) +修复ios端偶现创建webview初始化参数未生效的问题 +## 2.1.6(2022-07-11) +[修复]:修复上个版本更新导致nvue窗口组件不能选择文件的问题; +[新增]: +1.应群友建议(填写禁止格式太多)格式限制formats由原来填写禁止选择的格式改为填写允许被选择的格式; +2.应群友建议(增加上传结束回调事件),上传结束回调事件@uploadEnd +3.如能帮到你请留下你的免费好评,组件使用过程中有问题可以加QQ群交流,至于Map对象怎么使用这类前端基础问题请自行百度 +## 2.1.5(2022-07-01) +app端组件销毁时添加自动销毁webview功能,避免v-if销毁组件的情况控件还能被点击的问题 +## 2.1.4(2022-07-01) +修复小程序端回显问题 +## 2.1.3(2022-06-30) +回调事件返回参数新增path字段(文件临时地址),用于回显 +## 2.1.2(2022-06-16) +修复APP端Tabbar窗口无法选择文件的问题 +## 2.1.1(2022-06-16) +优化: +1.组件优化为允许在v-if中使用; +2.允许option直接在data赋值,不再强制在onRead中初始化; +## 2.1.0(2022-06-13) +h5 pc端更改为单次可多选 +## 2.0.9(2022-06-10) +更新演示内容,部分同学不知道怎么获取服务端返回的数据 +## 2.0.8(2022-06-09) +优化动态更新上传参数函数,具体查看下方说明:动态更新参数演示 +## 2.0.7(2022-06-07) +新增wxFileType属性,用于小程序端选择附件时可选文件类型 +## 2.0.6(2022-06-07) +修复小程序端真机选择文件提示失败的问题 +## 2.0.5(2022-06-02) +优化小程序端调用hide()后未阻止触发文件选择问题 +## 2.0.4(2022-06-01) +优化APP端选择器初始定位 +## 2.0.3(2022-05-31) +修复nvue窗口选择文件报错问题 +## 2.0.2(2022-05-20) +修复ios端opiton设置过早未传入webview导致不自动上传问题 +## 2.0.1(2022-05-19) +修复APP端子窗口点击选择文件不响应问题 +## 2.0.0(2022-05-18) +此次组件更新至2.0版本,与1.0版本使用上略有差异,已使用1.0的同学请自行斟酌是否需要升级! +部分差异: +一、 2.0新增异步触发上传功能; +二、2.0新增文件批量上传功能; +三、2.0优化option,剔除属性,只保留上传接口所需字段,且允许异步更改option的值; +四、组件增加size(文件大小限制)、count(文件个数限制)、formats(文件后缀限制)、accept(文件类型限制)、instantly(是否立即自动上传)、debug(日志打印)等属性; +五、回调事件取消input事件、callback事件,新增change事件和progress事件; +六、ref事件新增upload事件、clear事件; +七、优化组件代码,show和hide函数改为显示隐藏,不再重复开关webview; + +## 1.2.3(2022-03-22) +修复Demo里传入待完善功能[手动上传属性manual=true]导致不自动上传的问题,手动提交上传待下个版本更新 +## 1.2.2(2022-02-21) +修复上版本APP优化导致H5和小程序端不自动初始化的问题,此次更新仅修复此问题。异步提交功能下个版本更新~ +## 1.2.1(2022-01-25) +QQ1群已满,已开放2群:469580165 +## 1.2.0(2021-12-09) +优化APP端页面中DOM重排后每次需要重新定位的问题 +## 1.1.1(2021-12-09) +优化,与上版本使用方式有改变,请检查后确认是否需要更新,create更名为show, close更名为hide,取消初始化时手动create, 传参方式改为props=>option +## 1.1.0(2021-12-09) +新增refresh方法,用于DOM发生重排时重新定位控件(APP端) +## 1.0.9(2021-07-15) +修复上传进度未同步渲染,直接返回100%的BUG +## 1.0.8(2021-07-12) +修复H5端传入height和width未生效的bug +## 1.0.7(2021-07-07) +修复h5和小程序端上传完成callback未返回fileName字段问题 +## 1.0.6(2021-07-07) +修复h5端提示信息debug +## 1.0.5(2021-06-29) +感谢小伙伴找出bug,上传成功回调success未置为true,已修复 +## 1.0.4(2021-06-28) +新增兼容APP,H5,小程序手动关闭控件,关闭后不再弹出文件选择框,需要重新create再次开启 +## 1.0.3(2021-06-28) +close增加条件编译,除app端外不需要close +## 1.0.2(2021-06-28) +1.修复页面滚动位置后再create控件导致控件位置不正确的问题; +2.修复nvue无法create控件; +3.示例项目新增nvue使用案例; +## 1.0.1(2021-06-28) +因为有的朋友不清楚app端切换tab时应该怎么处理webview,现重新上传一版示例项目,需要做tab切换的朋友可以导入示例项目查看 +## 1.0.0(2021-06-25) +此插件为l-file插件中上传功能改版,更新内容为: +1. 按钮内嵌入页面,不再强制固定底部,可跟随页面滚动 +2.无需再单独弹框点击上传,减去中间层 +3.通过slot自定义按钮样式 diff --git a/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js b/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js new file mode 100644 index 0000000..a86233e --- /dev/null +++ b/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js @@ -0,0 +1,414 @@ +export class LsjFile { + constructor(data) { + this.dom = null; + // files.type = waiting(等待上传)|| loading(上传中)|| success(成功) || fail(失败) + this.files = new Map(); + this.debug = data.debug || false; + this.id = data.id; + this.width = data.width; + this.height = data.height; + this.option = data.option; + this.instantly = data.instantly; + this.prohibited = data.prohibited; + this.onchange = data.onchange; + this.onprogress = data.onprogress; + this.uploadHandle = this._uploadHandle; + // #ifdef MP-WEIXIN + this.uploadHandle = this._uploadHandleWX; + // #endif + } + + + /** + * 创建File节点 + * @param {string}path webview地址 + */ + create(path) { + if (!this.dom) { + // #ifdef H5 + let dom = document.createElement('input'); + dom.type = 'file' + dom.value = '' + dom.style.height = this.height + dom.style.width = this.width + dom.style.position = 'absolute' + dom.style.top = 0 + dom.style.left = 0 + dom.style.right = 0 + dom.style.bottom = 0 + dom.style.opacity = 0 + dom.style.zIndex = 999 + dom.accept = this.prohibited.accept; + if (this.prohibited.multiple) { + dom.multiple = 'multiple'; + } + dom.onchange = event => { + for (let file of event.target.files) { + if (this.files.size >= this.prohibited.count) { + this.toast(`只允许上传${this.prohibited.count}个文件`); + this.dom.value = ''; + break; + } + this.addFile(file); + } + + this._uploadAfter(); + + this.dom.value = ''; + }; + this.dom = dom; + // #endif + + // #ifdef APP-PLUS + let styles = { + top: '-200px', + left: 0, + width: '1px', + height: '200px', + background: 'transparent' + }; + let extras = { + debug: this.debug, + instantly: this.instantly, + prohibited: this.prohibited, + } + this.dom = plus.webview.create(path, this.id, styles,extras); + this.setData(this.option); + this._overrideUrlLoading(); + // #endif + return this.dom; + } + } + + + /** + * 设置上传参数 + * @param {object|string}name 上传参数,支持a.b 和 a[b] + */ + setData() { + let [name,value = ''] = arguments; + if (typeof name === 'object') { + Object.assign(this.option,name); + } + else { + this._setValue(this.option,name,value); + } + + this.debug&&console.log(JSON.stringify(this.option)); + + // #ifdef APP-PLUS + this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`); + // #endif + } + + /** + * 上传 + * @param {string}name 文件名称 + */ + async upload(name='') { + if (!this.option.url) { + throw Error('未设置上传地址'); + } + + // #ifndef APP-PLUS + if (name && this.files.has(name)) { + await this.uploadHandle(this.files.get(name)); + } + else { + for (let item of this.files.values()) { + if (item.type === 'waiting' || item.type === 'fail') { + await this.uploadHandle(item); + } + } + } + // #endif + + // #ifdef APP-PLUS + this.dom&&this.dom.evalJS(`vm.upload('${name}')`); + // #endif + } + + // 选择文件change + addFile(file,isCallChange) { + + let name = file.name; + this.debug&&console.log('文件名称',name,'大小',file.size); + + if (file) { + // 限制文件格式 + let path = ''; + let suffix = name.substring(name.lastIndexOf(".")+1).toLowerCase(); + let formats = this.prohibited.formats.toLowerCase(); + + // #ifndef MP-WEIXIN + path = URL.createObjectURL(file); + // #endif + // #ifdef MP-WEIXIN + path = file.path; + // #endif + if (formats&&!formats.includes(suffix)) { + this.toast(`不支持上传${suffix.toUpperCase()}格式文件`); + return false; + } + // 限制文件大小 + if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) { + this.toast(`附件大小请勿超过${this.prohibited.size}M`) + return false; + } + + try{ + if (!this.prohibited.distinct) { + let homonymIndex = [...this.files.keys()].findIndex(item=>{ + return (item.substring(0,item.lastIndexOf("("))||item.substring(0,item.lastIndexOf("."))) == name.substring(0,name.lastIndexOf(".")) && + item.substring(item.lastIndexOf(".")+1).toLowerCase() === suffix; + }) + if (homonymIndex > -1) { + name = `${name.substring(0,name.lastIndexOf("."))}(${homonymIndex+1}).${suffix}`; + } + } + }catch(e){ + //TODO handle the exception + } + + this.files.set(name,{file,path,name: name,size: file.size,progress: 0,type: 'waiting'}); + return true; + } + } + + /** + * 移除文件 + * @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件 + */ + clear(name='') { + // #ifdef APP-PLUS + this.dom&&this.dom.evalJS(`vm.clear('${name}')`); + // #endif + + if (!name) { + this.files.clear(); + } + else { + this.files.delete(name); + } + return this.onchange(this.files); + } + + /** + * 提示框 + * @param {string}msg 轻提示内容 + */ + toast(msg) { + uni.showToast({ + title: msg, + icon: 'none' + }); + } + + /** + * 微信小程序选择文件 + * @param {number}count 可选择文件数量 + */ + chooseMessageFile(type,count) { + wx.chooseMessageFile({ + count: count, + type: type, + success: ({ tempFiles }) => { + for (let file of tempFiles) { + this.addFile(file); + } + this._uploadAfter(); + }, + fail: () => { + this.toast(`打开失败`); + } + }) + } + + _copyObject(obj) { + if (typeof obj !== "undefined") { + return JSON.parse(JSON.stringify(obj)); + } else { + return obj; + } + } + + /** + * 自动根据字符串路径设置对象中的值 支持.和[] + * @param {Object} dataObj 数据源 + * @param {String} name 支持a.b 和 a[b] + * @param {String} value 值 + * setValue(dataObj, name, value); + */ + _setValue(dataObj, name, value) { + // 通过正则表达式 查找路径数据 + let dataValue; + if (typeof value === "object") { + dataValue = this._copyObject(value); + } else { + dataValue = value; + } + let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g"); + const patten = name.match(regExp); + // 遍历路径 逐级查找 最后一级用于直接赋值 + for (let i = 0; i < patten.length - 1; i++) { + let keyName = patten[i]; + if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {}; + dataObj = dataObj[keyName]; + } + // 最后一级 + dataObj[patten[patten.length - 1]] = dataValue; + this.debug&&console.log('参数更新后',JSON.stringify(this.option)); + } + + _uploadAfter() { + this.onchange(this.files); + setTimeout(()=>{ + this.instantly&&this.upload(); + },1000) + } + + _overrideUrlLoading() { + this.dom.overrideUrlLoading({ mode: 'reject' }, e => { + let {retype,item,files,end} = this._getRequest( + e.url + ); + let _this = this; + switch (retype) { + case 'updateOption': + this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`); + break + case 'change': + try { + _this.files = new Map([..._this.files,...JSON.parse(unescape(files))]); + } catch (e) { + return console.error('出错了,请检查代码') + } + _this.onchange(_this.files); + break + case 'progress': + try { + item = JSON.parse(unescape(item)); + } catch (e) { + return console.error('出错了,请检查代码') + } + _this._changeFilesItem(item,end); + break + default: + break + } + }) + } + + _getRequest(url) { + let theRequest = new Object() + let index = url.indexOf('?') + if (index != -1) { + let str = url.substring(index + 1) + let strs = str.split('&') + for (let i = 0; i < strs.length; i++) { + theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]) + } + } + return theRequest + } + + _changeFilesItem(item,end=false) { + this.debug&&console.log('onprogress',JSON.stringify(item)); + this.onprogress(item,end); + this.files.set(item.name,item); + } + + _uploadHandle(item) { + item.type = 'loading'; + delete item.responseText; + return new Promise((resolve,reject)=>{ + this.debug&&console.log('option',JSON.stringify(this.option)); + let {url,name,method='POST',header,formData} = this.option; + let form = new FormData(); + for (let keys in formData) { + form.append(keys, formData[keys]) + } + form.append(name, item.file); + let xmlRequest = new XMLHttpRequest(); + xmlRequest.open(method, url, true); + for (let keys in header) { + xmlRequest.setRequestHeader(keys, header[keys]) + } + + xmlRequest.upload.addEventListener( + 'progress', + event => { + if (event.lengthComputable) { + let progress = Math.ceil((event.loaded * 100) / event.total) + if (progress <= 100) { + item.progress = progress; + this._changeFilesItem(item); + } + } + }, + false + ); + + xmlRequest.ontimeout = () => { + console.error('请求超时') + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + + xmlRequest.onreadystatechange = ev => { + if (xmlRequest.readyState == 4) { + if (xmlRequest.status == 200) { + this.debug&&console.log('上传完成:' + xmlRequest.responseText) + item['responseText'] = xmlRequest.responseText; + item.type = 'success'; + this._changeFilesItem(item,true); + return resolve(true); + } else if (xmlRequest.status == 0) { + console.error('status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求') + } + console.error('--ERROR--:status = ' + xmlRequest.status) + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + } + xmlRequest.send(form) + }); + } + + _uploadHandleWX(item) { + item.type = 'loading'; + delete item.responseText; + return new Promise((resolve,reject)=>{ + this.debug&&console.log('option',JSON.stringify(this.option)); + let form = {filePath: item.file.path,...this.option }; + form['fail'] = ({ errMsg = '' }) => { + console.error('--ERROR--:' + errMsg) + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + form['success'] = res => { + if (res.statusCode == 200) { + this.debug&&console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data) + item['responseText'] = res.data; + item.type = 'success'; + this._changeFilesItem(item,true); + return resolve(true); + } + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + + let xmlRequest = uni.uploadFile(form); + xmlRequest.onProgressUpdate(({ progress = 0 }) => { + if (progress <= 100) { + item.progress = progress; + this._changeFilesItem(item); + } + }) + }); + } +} \ No newline at end of file diff --git a/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue b/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue new file mode 100644 index 0000000..46ac296 --- /dev/null +++ b/im-uniapp/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue @@ -0,0 +1,338 @@ + + + + + diff --git a/im-uniapp/uni_modules/lsj-upload/hybrid/html/js/vue.min.js b/im-uniapp/uni_modules/lsj-upload/hybrid/html/js/vue.min.js new file mode 100644 index 0000000..97ac4cf --- /dev/null +++ b/im-uniapp/uni_modules/lsj-upload/hybrid/html/js/vue.min.js @@ -0,0 +1,8 @@ +/*! + * Vue.js v2.3.0 + * (c) 2014-2017 Evan You + * Released under the MIT License. + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(e){return void 0===e||null===e}function t(e){return void 0!==e&&null!==e}function n(e){return!0===e}function r(e){return"string"==typeof e||"number"==typeof e}function i(e){return null!==e&&"object"==typeof e}function o(e){return"[object Object]"===Ai.call(e)}function a(e){return"[object RegExp]"===Ai.call(e)}function s(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function c(e){var t=parseFloat(e);return isNaN(t)?e:t}function u(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}function f(e,t){return Si.call(e,t)}function p(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function d(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function v(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function h(e,t){for(var n in t)e[n]=t[n];return e}function m(e){for(var t={},n=0;n=0&&$o[n].id>e.id;)n--;$o.splice(Math.max(n,Ao)+1,0,e)}else $o.push(e);Co||(Co=!0,ro($e))}}function Ae(e){To.clear(),Oe(e,To)}function Oe(e,t){var n,r,o=Array.isArray(e);if((o||i(e))&&Object.isExtensible(e)){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.length;n--;)Oe(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)Oe(e[r[n]],t)}}function Se(e,t,n){Eo.get=function(){return this[t][n]},Eo.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Eo)}function Te(e){e._watchers=[];var t=e.$options;t.props&&Ee(e,t.props),t.methods&&Me(e,t.methods),t.data?je(e):E(e._data={},!0),t.computed&&Le(e,t.computed),t.watch&&Pe(e,t.watch)}function Ee(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[],o=!e.$parent;lo.shouldConvert=o;for(var a in t)!function(o){i.push(o);var a=U(o,t,n,e);j(r,o,a),o in e||Se(e,"_props",o)}(a);lo.shouldConvert=!0}function je(e){var t=e.$options.data;t=e._data="function"==typeof t?Ne(t,e):t||{},o(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,i=n.length;i--;)r&&f(r,n[i])||$(n[i])||Se(e,"_data",n[i]);E(t,!0)}function Ne(e,t){try{return e.call(t)}catch(e){return C(e,t,"data()"),{}}}function Le(e,t){var n=e._computedWatchers=Object.create(null);for(var r in t){var i=t[r],o="function"==typeof i?i:i.get;n[r]=new So(e,o,g,jo),r in e||Ie(e,r,i)}}function Ie(e,t,n){"function"==typeof n?(Eo.get=De(t),Eo.set=g):(Eo.get=n.get?!1!==n.cache?De(t):n.get:g,Eo.set=n.set?n.set:g),Object.defineProperty(e,t,Eo)}function De(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),oo.target&&t.depend(),t.value}}function Me(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?g:d(t[n],e)}function Pe(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i=0||n.indexOf(e[i])<0)&&r.push(e[i]);return r}return e}function pt(e){this._init(e)}function dt(e){e.use=function(e){if(!e.installed){var t=v(arguments,1);return t.unshift(this),"function"==typeof e.install?e.install.apply(e,t):"function"==typeof e&&e.apply(null,t),e.installed=!0,this}}}function vt(e){e.mixin=function(e){this.options=B(this.options,e)}}function ht(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=B(n.options,e),a.super=n,a.options.props&&mt(a),a.options.computed&>(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Di.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=h({},a.options),i[r]=a,a}}function mt(e){var t=e.options.props;for(var n in t)Se(e.prototype,"_props",n)}function gt(e){var t=e.options.computed;for(var n in t)Ie(e.prototype,n,t[n])}function yt(e){Di.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&o(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function _t(e){return e&&(e.Ctor.options.name||e.tag)}function bt(e,t){return"string"==typeof e?e.split(",").indexOf(t)>-1:!!a(e)&&e.test(t)}function $t(e,t,n){for(var r in e){var i=e[r];if(i){var o=_t(i.componentOptions);o&&!n(o)&&(i!==t&&xt(i),e[r]=null)}}}function xt(e){e&&e.componentInstance.$destroy()}function wt(e){for(var n=e.data,r=e,i=e;t(i.componentInstance);)i=i.componentInstance._vnode,i.data&&(n=Ct(i.data,n));for(;t(r=r.parent);)r.data&&(n=Ct(n,r.data));return kt(n)}function Ct(e,n){return{staticClass:At(e.staticClass,n.staticClass),class:t(e.class)?[e.class,n.class]:n.class}}function kt(e){var n=e.class,r=e.staticClass;return t(r)||t(n)?At(r,Ot(n)):""}function At(e,t){return e?t?e+" "+t:e:t||""}function Ot(n){if(e(n))return"";if("string"==typeof n)return n;var r="";if(Array.isArray(n)){for(var o,a=0,s=n.length;a-1?ua[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:ua[e]=/HTMLUnknownElement/.test(t.toString())}function Et(e){if("string"==typeof e){var t=document.querySelector(e);return t||document.createElement("div")}return e}function jt(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function Nt(e,t){return document.createElementNS(ia[e],t)}function Lt(e){return document.createTextNode(e)}function It(e){return document.createComment(e)}function Dt(e,t,n){e.insertBefore(t,n)}function Mt(e,t){e.removeChild(t)}function Pt(e,t){e.appendChild(t)}function Rt(e){return e.parentNode}function Ft(e){return e.nextSibling}function Bt(e){return e.tagName}function Ht(e,t){e.textContent=t}function Ut(e,t,n){e.setAttribute(t,n)}function Vt(e,t){var n=e.data.ref;if(n){var r=e.context,i=e.componentInstance||e.elm,o=r.$refs;t?Array.isArray(o[n])?l(o[n],i):o[n]===i&&(o[n]=void 0):e.data.refInFor?Array.isArray(o[n])&&o[n].indexOf(i)<0?o[n].push(i):o[n]=[i]:o[n]=i}}function zt(e,n){return e.key===n.key&&e.tag===n.tag&&e.isComment===n.isComment&&t(e.data)===t(n.data)&&Jt(e,n)}function Jt(e,n){if("input"!==e.tag)return!0;var r;return(t(r=e.data)&&t(r=r.attrs)&&r.type)===(t(r=n.data)&&t(r=r.attrs)&&r.type)}function Kt(e,n,r){var i,o,a={};for(i=n;i<=r;++i)o=e[i].key,t(o)&&(a[o]=i);return a}function qt(e,t){(e.data.directives||t.data.directives)&&Wt(e,t)}function Wt(e,t){var n,r,i,o=e===pa,a=t===pa,s=Zt(e.data.directives,e.context),c=Zt(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,Yt(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(Yt(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n=0&&" "===(m=e.charAt(h));h--);m&&_a.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=e.slice(0,i).trim()):t();if(void 0===o?o=e.slice(0,i).trim():0!==v&&t(),a)for(i=0;i=Bo}function gn(e){return 34===e||39===e}function yn(e){var t=1;for(zo=Vo;!mn();)if(e=hn(),gn(e))_n(e);else if(91===e&&t++,93===e&&t--,0===t){Jo=Vo;break}}function _n(e){for(var t=e;!mn()&&(e=hn())!==t;);}function bn(e,t,n){Ko=n;var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if("select"===o)wn(e,r,i);else if("input"===o&&"checkbox"===a)$n(e,r,i);else if("input"===o&&"radio"===a)xn(e,r,i);else if("input"===o||"textarea"===o)Cn(e,r,i);else if(!Pi.isReservedTag(o))return pn(e,r,i),!1;return!0}function $n(e,t,n){var r=n&&n.number,i=ln(e,"value")||"null",o=ln(e,"true-value")||"true",a=ln(e,"false-value")||"false";an(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),un(e,$a,"var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$c){$$i<0&&("+t+"=$$a.concat($$v))}else{$$i>-1&&("+t+"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}}else{"+dn(t,"$$c")+"}",null,!0)}function xn(e,t,n){var r=n&&n.number,i=ln(e,"value")||"null";i=r?"_n("+i+")":i,an(e,"checked","_q("+t+","+i+")"),un(e,$a,dn(t,i),null,!0)}function wn(e,t,n){var r=n&&n.number,i='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",o="var $$selectedVal = "+i+";";o=o+" "+dn(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),un(e,"change",o,null,!0)}function Cn(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?ba:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=dn(t,l);c&&(f="if($event.target.composing)return;"+f),an(e,"value","("+t+")"),un(e,u,f,null,!0),(s||a||"number"===r)&&un(e,"blur","$forceUpdate()")}function kn(e){var n;t(e[ba])&&(n=zi?"change":"input",e[n]=[].concat(e[ba],e[n]||[]),delete e[ba]),t(e[$a])&&(n=Zi?"click":"change",e[n]=[].concat(e[$a],e[n]||[]),delete e[$a])}function An(e,t,n,r,i){if(n){var o=t,a=qo;t=function(n){null!==(1===arguments.length?o(n):o.apply(null,arguments))&&On(e,t,r,a)}}qo.addEventListener(e,t,Gi?{capture:r,passive:i}:r)}function On(e,t,n,r){(r||qo).removeEventListener(e,t,n)}function Sn(t,n){if(!e(t.data.on)||!e(n.data.on)){var r=n.data.on||{},i=t.data.on||{};qo=n.elm,kn(r),G(r,i,An,On,n.context)}}function Tn(n,r){if(!e(n.data.domProps)||!e(r.data.domProps)){var i,o,a=r.elm,s=n.data.domProps||{},c=r.data.domProps||{};t(c.__ob__)&&(c=r.data.domProps=h({},c));for(i in s)e(c[i])&&(a[i]="");for(i in c)if(o=c[i],"textContent"!==i&&"innerHTML"!==i||(r.children&&(r.children.length=0),o!==s[i]))if("value"===i){a._value=o;var u=null==o?"":String(o);En(a,r,u)&&(a.value=u)}else a[i]=o}}function En(e,t,n){return!e.composing&&("option"===t.tag||jn(e,n)||Nn(e,n))}function jn(e,t){return document.activeElement!==e&&e.value!==t}function Nn(e,n){var r=e.value,i=e._vModifiers;return t(i)&&i.number||"number"===e.type?c(r)!==c(n):t(i)&&i.trim?r.trim()!==n.trim():r!==n}function Ln(e){var t=In(e.style);return e.staticStyle?h(e.staticStyle,t):t}function In(e){return Array.isArray(e)?m(e):"string"==typeof e?Ca(e):e}function Dn(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)i=i.componentInstance._vnode,i.data&&(n=Ln(i.data))&&h(r,n);(n=Ln(e.data))&&h(r,n);for(var o=e;o=o.parent;)o.data&&(n=Ln(o.data))&&h(r,n);return r}function Mn(n,r){var i=r.data,o=n.data;if(!(e(i.staticStyle)&&e(i.style)&&e(o.staticStyle)&&e(o.style))){var a,s,c=r.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,p=In(r.data.style)||{};r.data.normalizedStyle=t(p.__ob__)?h({},p):p;var d=Dn(r,!0);for(s in f)e(d[s])&&Oa(c,s,"");for(s in d)(a=d[s])!==f[s]&&Oa(c,s,null==a?"":a)}}function Pn(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function Rn(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t);else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");e.setAttribute("class",n.trim())}}function Fn(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&h(t,ja(e.name||"v")),h(t,e),t}return"string"==typeof e?ja(e):void 0}}function Bn(e){Fa(function(){Fa(e)})}function Hn(e,t){(e._transitionClasses||(e._transitionClasses=[])).push(t),Pn(e,t)}function Un(e,t){e._transitionClasses&&l(e._transitionClasses,t),Rn(e,t)}function Vn(e,t,n){var r=zn(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===La?Ma:Ra,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=La,l=a,f=o.length):t===Ia?u>0&&(n=Ia,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?La:Ia:null,f=n?n===La?o.length:c.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===La&&Ba.test(r[Da+"Property"])}}function Jn(e,t){for(;e.length1}function Yn(e,t){!0!==t.data.show&&qn(t)}function Qn(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s-1,a.selected!==o&&(a.selected=o);else if(y(er(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Xn(e,t){for(var n=0,r=t.length;n=0&&a[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(var c=a.length-1;c>=i;c--)t.end&&t.end(a[c].tag,n,r);a.length=i,o=i&&a[i-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,r):"p"===s&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var i,o,a=[],s=t.expectHTML,c=t.isUnaryTag||Ni,u=t.canBeLeftOpenTag||Ni,l=0;e;){if(i=e,o&&Ns(o)){var f=o.toLowerCase(),p=Ls[f]||(Ls[f]=new RegExp("([\\s\\S]*?)(]*>)","i")),d=0,v=e.replace(p,function(e,n,r){return d=r.length,Ns(f)||"noscript"===f||(n=n.replace(//g,"$1").replace(//g,"$1")),t.chars&&t.chars(n),""});l+=e.length-v.length,e=v,r(f,l-d,l)}else{var h=e.indexOf("<");if(0===h){if(fs.test(e)){var m=e.indexOf("--\x3e");if(m>=0){n(m+3);continue}}if(ps.test(e)){var g=e.indexOf("]>");if(g>=0){n(g+2);continue}}var y=e.match(ls);if(y){n(y[0].length);continue}var _=e.match(us);if(_){var b=l;n(_[0].length),r(_[1],b,l);continue}var $=function(){var t=e.match(ss);if(t){var r={tagName:t[1],attrs:[],start:l};n(t[0].length);for(var i,o;!(i=e.match(cs))&&(o=e.match(os));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=l,r}}();if($){!function(e){var n=e.tagName,i=e.unarySlash;s&&("p"===o&&rs(n)&&r(o),u(n)&&o===n&&r(n));for(var l=c(n)||"html"===n&&"head"===o||!!i,f=e.attrs.length,p=new Array(f),d=0;d=0){for(w=e.slice(h);!(us.test(w)||ss.test(w)||fs.test(w)||ps.test(w)||(C=w.indexOf("<",1))<0);)h+=C,w=e.slice(h);x=e.substring(0,h),n(h)}h<0&&(x=e,e=""),t.chars&&x&&t.chars(x)}if(e===i){t.chars&&t.chars(e);break}}r()}function mr(e,t){var n=t?Rs(t):Ps;if(n.test(e)){for(var r,i,o=[],a=n.lastIndex=0;r=n.exec(e);){i=r.index,i>a&&o.push(JSON.stringify(e.slice(a,i)));var s=tn(r[1].trim());o.push("_s("+s+")"),a=i+r[0].length}return a0,Ki=Vi&&Vi.indexOf("edge/")>0,qi=Vi&&Vi.indexOf("android")>0,Wi=Vi&&/iphone|ipad|ipod|ios/.test(Vi),Zi=Vi&&/chrome\/\d+/.test(Vi)&&!Ki,Gi=!1;if(Ui)try{var Yi={};Object.defineProperty(Yi,"passive",{get:function(){Gi=!0}}),window.addEventListener("test-passive",null,Yi)}catch(e){}var Qi,Xi,eo=function(){return void 0===Qi&&(Qi=!Ui&&"undefined"!=typeof global&&"server"===global.process.env.VUE_ENV),Qi},to=Ui&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,no="undefined"!=typeof Symbol&&k(Symbol)&&"undefined"!=typeof Reflect&&k(Reflect.ownKeys),ro=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t1?v(n):n;for(var r=v(arguments,1),i=0,o=n.length;i1&&(t[n[0].trim()]=n[1].trim())}}),t}),ka=/^--/,Aa=/\s*!important$/,Oa=function(e,t,n){if(ka.test(t))e.style.setProperty(t,n);else if(Aa.test(n))e.style.setProperty(t,n.replace(Aa,""),"important");else{var r=Ta(t);if(Array.isArray(n))for(var i=0,o=n.length;iv?(f=e(i[g+1])?null:i[g+1].elm,y(n,f,i,d,g,o)):d>g&&b(n,r,p,v)}function w(r,i,o,a){if(r!==i){if(n(i.isStatic)&&n(r.isStatic)&&i.key===r.key&&(n(i.isCloned)||n(i.isOnce)))return i.elm=r.elm,void(i.componentInstance=r.componentInstance);var s,c=i.data;t(c)&&t(s=c.hook)&&t(s=s.prepatch)&&s(r,i);var u=i.elm=r.elm,l=r.children,f=i.children;if(t(c)&&h(i)){for(s=0;s',n.innerHTML.indexOf(t)>0}("\n"," "),ts=u("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),ns=u("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),rs=u("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),is=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^\s"'=<>`]+)/.source],os=new RegExp("^\\s*"+/([^\s"'<>\/=]+)/.source+"(?:\\s*("+/(?:=)/.source+")\\s*(?:"+is.join("|")+"))?"),as="[a-zA-Z_][\\w\\-\\.]*",ss=new RegExp("^<((?:"+as+"\\:)?"+as+")"),cs=/^\s*(\/?)>/,us=new RegExp("^<\\/((?:"+as+"\\:)?"+as+")[^>]*>"),ls=/^]+>/i,fs=/^