|
@@ -25,27 +25,35 @@
|
|
|
|
|
|
<div v-if="selectedFiles.length > 0" class="file-list">
|
|
|
<h3>已选择的文件</h3>
|
|
|
- <div class="file-item" v-for="(file, index) in selectedFiles" :key="index">
|
|
|
- <div class="file-info">
|
|
|
- <div class="file-icon">
|
|
|
- <i :class="getFileIcon(file.type)"></i>
|
|
|
- </div>
|
|
|
- <div class="file-details">
|
|
|
- <div class="file-name">{{ file.name }}</div>
|
|
|
- <div class="file-size">{{ formatFileSize(file.size) }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="file-actions">
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- @click="removeFile(index)"
|
|
|
- icon="el-icon-delete"
|
|
|
- >
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="file-item" v-for="(file, index) in selectedFiles" :key="index">
|
|
|
+ <div class="file-info">
|
|
|
+ <div class="file-icon">
|
|
|
+ <i :class="getFileIcon(file.type)"></i>
|
|
|
+ </div>
|
|
|
+ <div class="file-details">
|
|
|
+ <div class="file-name">{{ file.name }}</div>
|
|
|
+ <div class="file-size">{{ formatFileSize(file.size) }}</div>
|
|
|
+ <div class="file-status">
|
|
|
+ <span v-if="uploadedFiles[index]" class="status-success">
|
|
|
+ <i class="el-icon-check"></i> 已上传
|
|
|
+ </span>
|
|
|
+ <span v-else class="status-uploading">
|
|
|
+ <i class="el-icon-loading"></i> 上传中...
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="file-actions">
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ size="mini"
|
|
|
+ @click="removeFile(index)"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<div class="submit-area">
|
|
@@ -53,31 +61,23 @@
|
|
|
type="primary"
|
|
|
size="large"
|
|
|
@click="submitToMiniProgram"
|
|
|
- :disabled="selectedFiles.length === 0"
|
|
|
+ :disabled="uploadedFiles.length === 0"
|
|
|
:loading="submitting"
|
|
|
>
|
|
|
- {{ submitting ? '提交中...' : '提交给小程序' }}
|
|
|
+ {{ submitting ? '提交中...' : '提交给小程序' }} ({{ uploadedFiles.length }}个文件)
|
|
|
</el-button>
|
|
|
-
|
|
|
- <el-button
|
|
|
- type="info"
|
|
|
- size="large"
|
|
|
- @click="goBackToMiniProgram"
|
|
|
- style="margin-left: 15px;"
|
|
|
- >
|
|
|
- 关闭页面
|
|
|
- </el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import wx from 'weixin-js-sdk';
|
|
|
+import wx from 'weixin-js-sdk'
|
|
|
export default {
|
|
|
name: 'FileUpload',
|
|
|
data() {
|
|
|
return {
|
|
|
selectedFiles: [],
|
|
|
+ uploadedFiles: [], // 存储上传后的文件URL
|
|
|
submitting: false
|
|
|
}
|
|
|
},
|
|
@@ -99,25 +99,34 @@ export default {
|
|
|
},
|
|
|
|
|
|
// 处理文件选择
|
|
|
- handleFileSelect(event) {
|
|
|
+ async handleFileSelect(event) {
|
|
|
const files = Array.from(event.target.files)
|
|
|
|
|
|
- files.forEach(file => {
|
|
|
+ for (const file of files) {
|
|
|
// 检查文件大小限制 (50MB)
|
|
|
if (file.size > 50 * 1024 * 1024) {
|
|
|
this.$message.error(`文件 ${file.name} 超过50MB限制`)
|
|
|
- return
|
|
|
+ continue
|
|
|
}
|
|
|
|
|
|
// 检查是否已存在同名文件
|
|
|
const exists = this.selectedFiles.find(f => f.name === file.name)
|
|
|
if (exists) {
|
|
|
this.$message.warning(`文件 ${file.name} 已存在`)
|
|
|
- return
|
|
|
+ continue
|
|
|
}
|
|
|
|
|
|
+ // 添加到选中文件列表
|
|
|
this.selectedFiles.push(file)
|
|
|
- })
|
|
|
+
|
|
|
+ // 上传文件并获取URL
|
|
|
+ try {
|
|
|
+ await this.uploadFile(file)
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`上传文件 ${file.name} 失败:`, error)
|
|
|
+ this.$message.error(`上传文件 ${file.name} 失败`)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 清空input值,允许重复选择同一文件
|
|
|
event.target.value = ''
|
|
@@ -126,6 +135,10 @@ export default {
|
|
|
// 删除文件
|
|
|
removeFile(index) {
|
|
|
this.selectedFiles.splice(index, 1)
|
|
|
+ // 同时删除对应的上传文件信息
|
|
|
+ if (this.uploadedFiles[index]) {
|
|
|
+ this.uploadedFiles.splice(index, 1)
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// 获取文件图标
|
|
@@ -158,8 +171,8 @@ export default {
|
|
|
|
|
|
// 提交给小程序
|
|
|
async submitToMiniProgram() {
|
|
|
- if (this.selectedFiles.length === 0) {
|
|
|
- this.$message.warning('请先选择文件')
|
|
|
+ if (this.uploadedFiles.length === 0) {
|
|
|
+ this.$message.warning('请先选择并上传文件')
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -172,101 +185,83 @@ export default {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // 准备文件数据
|
|
|
- const filesData = await this.prepareFilesData()
|
|
|
-
|
|
|
// 通过微信JS-SDK发送消息给小程序
|
|
|
if (wx && wx.miniProgram) {
|
|
|
// 在微信小程序web-view中
|
|
|
wx.miniProgram.postMessage({
|
|
|
data: {
|
|
|
type: 'file_upload',
|
|
|
- files: filesData
|
|
|
+ files: this.uploadedFiles
|
|
|
}
|
|
|
})
|
|
|
|
|
|
this.$message.success('文件已提交给小程序')
|
|
|
this.selectedFiles = []
|
|
|
-
|
|
|
- // 延迟关闭当前页面,让用户看到成功提示
|
|
|
- setTimeout(() => {
|
|
|
- wx.miniProgram.navigateBack({ delta: 1 })
|
|
|
- }, 1500)
|
|
|
+ this.uploadedFiles = []
|
|
|
} else {
|
|
|
- // 尝试通过WeixinJSBridge
|
|
|
- WeixinJSBridge.invoke('sendAppMessage', {
|
|
|
- title: '文件上传',
|
|
|
- desc: `已选择 ${this.selectedFiles.length} 个文件`,
|
|
|
- link: window.location.href,
|
|
|
- imgUrl: '',
|
|
|
- data: {
|
|
|
- type: 'file_upload',
|
|
|
- files: filesData
|
|
|
- }
|
|
|
- }, (res) => {
|
|
|
- if (res.err_msg === 'send_app_msg:ok') {
|
|
|
- this.$message.success('文件已提交给小程序')
|
|
|
- this.selectedFiles = []
|
|
|
-
|
|
|
- // 延迟关闭当前页面
|
|
|
- setTimeout(() => {
|
|
|
- if (wx && wx.miniProgram) {
|
|
|
- wx.miniProgram.navigateBack({ delta: 1 })
|
|
|
- }
|
|
|
- }, 1500)
|
|
|
- } else {
|
|
|
- this.$message.error('提交失败,请重试!')
|
|
|
- }
|
|
|
- })
|
|
|
+ // 如果不在小程序web-view中,提示用户
|
|
|
+ this.$message.error('请在微信小程序中打开此页面')
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
console.error('提交文件失败:', error)
|
|
|
- this.$message.error('提交失败,请重试.')
|
|
|
+ this.$message.error('提交失败,请重试')
|
|
|
} finally {
|
|
|
this.submitting = false
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
- // 准备文件数据
|
|
|
- async prepareFilesData() {
|
|
|
- const filesData = []
|
|
|
-
|
|
|
- for (const file of this.selectedFiles) {
|
|
|
- try {
|
|
|
- const base64 = await this.fileToBase64(file)
|
|
|
- filesData.push({
|
|
|
- name: file.name,
|
|
|
- type: file.type,
|
|
|
- size: file.size,
|
|
|
- data: base64
|
|
|
- })
|
|
|
- } catch (error) {
|
|
|
- console.error('转换文件失败:', error)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return filesData
|
|
|
- },
|
|
|
-
|
|
|
- // 文件转Base64
|
|
|
- fileToBase64(file) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- const reader = new FileReader()
|
|
|
- reader.onload = () => resolve(reader.result)
|
|
|
- reader.onerror = reject
|
|
|
- reader.readAsDataURL(file)
|
|
|
- })
|
|
|
+ uploadFile(file) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('file', file);
|
|
|
+
|
|
|
+ this.$store.dispatch('pool/uploadFile', formData).then(res => {
|
|
|
+ if(res.code == 200){
|
|
|
+ const fileInfo = {
|
|
|
+ imgUrl:res.data.imgUrl,
|
|
|
+ id:res.data.id,
|
|
|
+ src:res.data.src,
|
|
|
+ fileName:res.data.fileName,
|
|
|
+ fileType:res.data.fileType,
|
|
|
+ oldFileName:res.data.oldFileName,
|
|
|
+ oldName:res.data.oldName,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加到已上传文件列表
|
|
|
+ this.uploadedFiles.push(fileInfo);
|
|
|
+ console.log('文件上传成功:', fileInfo);
|
|
|
+ resolve(fileInfo);
|
|
|
+ }else{
|
|
|
+ this.$message({
|
|
|
+ type: 'info',
|
|
|
+ message: res.message
|
|
|
+ });
|
|
|
+
|
|
|
+ // 从selectedFiles中删除上传失败的文件
|
|
|
+ const fileIndex = this.selectedFiles.findIndex(f => f.name === file.name);
|
|
|
+ if (fileIndex !== -1) {
|
|
|
+ this.selectedFiles.splice(fileIndex, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ reject(res.message);
|
|
|
+ }
|
|
|
+ }).catch((error) => {
|
|
|
+ console.error('文件上传失败:', error);
|
|
|
+ this.$message({
|
|
|
+ type: 'error',
|
|
|
+ message: `上传文件 ${file.name} 失败,请重试!`
|
|
|
+ });
|
|
|
+
|
|
|
+ // 从selectedFiles中删除上传失败的文件
|
|
|
+ const fileIndex = this.selectedFiles.findIndex(f => f.name === file.name);
|
|
|
+ if (fileIndex !== -1) {
|
|
|
+ this.selectedFiles.splice(fileIndex, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ reject(error);
|
|
|
+ });
|
|
|
+ });
|
|
|
},
|
|
|
-
|
|
|
- // 关闭当前页面
|
|
|
- goBackToMiniProgram() {
|
|
|
- if (wx && wx.miniProgram) {
|
|
|
- wx.miniProgram.navigateBack({ delta: 1 })
|
|
|
- } else {
|
|
|
- this.$message.warning('请在微信小程序中打开此页面')
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
@@ -379,6 +374,38 @@ export default {
|
|
|
color: #909399;
|
|
|
}
|
|
|
|
|
|
+.file-status {
|
|
|
+ margin-top: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.status-success {
|
|
|
+ color: #67c23a;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.status-success i {
|
|
|
+ margin-right: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.status-uploading {
|
|
|
+ color: #e6a23c;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.status-uploading i {
|
|
|
+ margin-right: 3px;
|
|
|
+ animation: rotating 2s linear infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes rotating {
|
|
|
+ from {
|
|
|
+ transform: rotate(0deg);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ transform: rotate(360deg);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.file-actions {
|
|
|
margin-left: 15px;
|
|
|
}
|