绿满眶商城微信小程序-uniapp
zxl
2025-07-11 01439f14432ee731be561d193c88e3ea31399345
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<template>
  <text :data="flag" :props="config" :change:data="fileManager.watchData" :change:props="fileManager.watchProps"></text>
</template>
 
<script>
/**
 * 文件选择 - APP端
 * @author sonve
 * @version 1.0.0
 * @date 2024-12-04
 */
 
export default {
  props: {
    /**
     * 配置项
     * @tutorial https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file
     */
    config: {
      type: Object,
      default: () => {
        return {
          accept: `.doc,.docx,.xls,.xlsx,.pdf,.zip,.rar,
          application/msword,
          application/vnd.openxmlformats-officedocument.wordprocessingml.document,
          application/vnd.ms-excel,
          application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
          application/pdf,
          application/zip,
          application/x-rar-compressed`,
          multiple: false
        }
      }
    }
  },
  data() {
    return {
      flag: 0 // 监听标志
    }
  },
  methods: {
    chooseFile() {
      this.flag++ // 修改监听标志
    },
    rawFile(file) {
      this.$emit('confirm', file)
    }
  }
}
</script>
 
<script module="fileManager" lang="renderjs">
import { base64ToPath } from '../common/file-handler.js';
export default {
  data() {
    return {
      configCopy: {}, // 跟随vue中props的配置
    }
  },
  methods: {
    watchData(newValue, oldValue, ownerInstance, instance) {
      if (newValue) {
        this.openFileManager()
      }
    },
    watchProps(newValue, oldValue, ownerInstance, instance) {
      if (newValue) {
        this.configCopy = newValue
      }
    },
    openFileManager() {
      try {
        const { accept, multiple } = this.configCopy
        // 创建文件选择器input
        let fileInput = document.createElement('input')
        fileInput.setAttribute('type', 'file')
        fileInput.setAttribute('accept', accept)
        // 注:是否多选不要直接赋值multiple,应当是为false时不添加multiple属性
        if(multiple) fileInput.setAttribute('multiple', multiple)
        fileInput.click()
 
        // 封装为Promise的FileReader读取文件
        const readFileAsDataURL = (file) => {
          return new Promise((resolve, reject) => {
            let reader = new FileReader();
            reader.readAsDataURL(file);
 
            reader.onload = async (event) => {
              const base64 = event.target.result
              const path = await base64ToPath(base64)
              resolve({
                name: file.name,
                type: file.type,
                size: file.size,
                base64,
                path
              });
            };
            reader.onerror = (error) => {
              reject(error);
            };
          });
        }
 
        fileInput.addEventListener('change', async (e) => {
          let files = e.target.files // 注:此处为FileList对象,并非常规数组
 
          let results = await Promise.all(
            // Array.from 方法可以将类数组对象转换为真正的数组
            Array.from(files).map(item => readFileAsDataURL(item))
          );
 
          // callMethod不支持流数据,无法直接传递文件流对象
          this.$ownerInstance.callMethod('rawFile', results)
        })
      } catch (err) {
        console.warn('==== openFileManager catch error :', err);
      }
    }
  }
}
</script>