filemanage.uvue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <template>
  2. <view style="flex-direction: row;" id="rootview">
  3. <radio-group @change="switchCacheOrData">
  4. <radio value="data" :checked="true">数据目录</radio>
  5. <radio value="cache"
  6. <!-- #ifdef MP-WEIXIN -->
  7. disabled
  8. <!-- #endif -->
  9. >缓存目录</radio>
  10. </radio-group>
  11. <button @click="refreshFile">刷新</button>
  12. <!-- #ifdef APP -->
  13. <button @click="clearFile">清空缓存</button>
  14. <!-- #endif -->
  15. <button @click="snapshot">截图</button>
  16. </view>
  17. <text>文件总数:{{ count }};\n文件总大小:{{size}} M</text>
  18. <text style="border: 1px solid #ccc;margin: 5px;">根路径:{{rootPath}}</text>
  19. <list-view style="flex: 1;">
  20. <list-item v-for="(item, index) in fileList" :key="index" style="padding: 5px;border-bottom: 1px solid #ccc;" :style="getIndentStyle(item.shotPath)"
  21. @click="showDialog(item)">
  22. <view style="flex-direction: row;">
  23. <!-- <text style="font-family: uni-icon;" v-if="!item.isFile">\uE661</text> -->
  24. <!-- #ifdef APP -->
  25. <!-- TODO: 微信小程序不支持uni内置字体,还得再找一个图标-->
  26. <text style="font-family: uni-icon;" v-if="!item.isFile">{{uniIcon}}</text> <!-- TODO @颜伊林 必须写响应式变量,多端表现不一致-->
  27. <!-- #endif -->
  28. <text >{{(item.shotPath as string)}}</text>
  29. </view>
  30. <text style="font-size: 12px;color: #ccc;" v-if="item.isFile" >{{item.size}}k</text>
  31. </list-item>
  32. </list-view>
  33. <view v-if="dialogShow" style="position: fixed; top: 0; bottom: 0; left: 0; right: 0; align-items: center; justify-content: center; z-index: 1000; background-color: rgba(16, 16, 16, 0.5);">
  34. <view style="background-color: #fff;padding: 10px;border-radius: 10px;width: 90%;margin: 0 auto;">
  35. <text style="font-size: 20px;font-weight: bold;">{{currentFile.shotPath}}</text>
  36. <text>类型:{{currentFile.isFile ? '文件' : '目录'}}</text>
  37. <text>路径:{{currentFile.path}}</text>
  38. <text>大小:{{currentFile.size}}k</text>
  39. <text>修改时间:{{currentFile.modifyTime}}</text>
  40. <view style="flex-direction: row;width: 100%;justify-content: space-between;padding: 10px;">
  41. <button @click="openFile(currentFile)" size="mini" v-if="currentFile.isFile">打开</button>
  42. <button @click="deleteFile(currentFile)" size="mini">删除</button>
  43. <button @click="closeDialog" size="mini">关闭</button>
  44. </view>
  45. </view>
  46. </view>
  47. </template>
  48. <script setup>
  49. type fileListType = {
  50. path : string,
  51. shotPath : string,
  52. size : number,
  53. isFile : boolean,
  54. modifyTime : string
  55. }
  56. let fileList = ref([] as fileListType[])
  57. let count = ref(0), size = ref(0)
  58. let rootPath = ref("")
  59. let dialogShow = ref(false)
  60. const uniIcon = ref("\uE661")
  61. let currentFile = ref({"path":"","shotPath":"","size":0,isFile:false,modifyTime:''} as fileListType)
  62. let cacheOrData = ref(uni.env.USER_DATA_PATH)
  63. const switchCacheOrData = (e : UniRadioGroupChangeEvent) => {
  64. cacheOrData.value = (e.detail.value=="cache") ? uni.env.CACHE_PATH : uni.env.USER_DATA_PATH
  65. }
  66. // 遍历文件刷新列表
  67. const refreshFile = () => {
  68. const fileManager = uni.getFileSystemManager()
  69. fileManager.stat({
  70. // path: uni.env.CACHE_PATH, //沙盒cache目录
  71. // path: uni.env.USER_DATA_PATH, //沙盒根目录
  72. path: cacheOrData.value,
  73. recursive: true,
  74. success: (res : StatSuccessResult) => {
  75. // log.value += 'statFileInfoTest success:' + JSON.stringify(res) + '\n\n'
  76. console.log('statFileInfo success1')
  77. console.log('res.stats', res.stats)
  78. console.log('uni.env.CACHE_PATH: ',uni.env.CACHE_PATH);
  79. console.log('uni.env.USER_DATA_PATH: ',uni.env.USER_DATA_PATH);
  80. console.log('uni.env.SANDBOX_PATH: ',uni.env.SANDBOX_PATH);
  81. let tempFileList = [] as fileListType[]
  82. let tempSize = 0
  83. for (let i=0;i<res.stats.length;i++) {
  84. console.log("resitem",res.stats[i].path);
  85. if (i==0) {
  86. rootPath.value = res.stats[i].path
  87. continue
  88. }
  89. let tempFileItem = {
  90. "path":"",
  91. "shotPath":"",
  92. "size":0,
  93. isFile:false,
  94. modifyTime:''
  95. } as fileListType
  96. tempFileItem.shotPath = res.stats[i].path.replace(rootPath.value, "")
  97. tempFileItem.path = res.stats[i].path
  98. tempFileItem.size = res.stats[i].stats.size/1024
  99. tempFileItem.isFile = res.stats[i].stats.isFile()
  100. const mdate = new Date(res.stats[i].stats.lastModifiedTime * 1000)
  101. tempFileItem.modifyTime = mdate.getFullYear().toString() + "-" + (mdate.getMonth()+1).toString() + "-" + mdate.getDate().toString() + " "
  102. + mdate.getHours().toString() + ":" + mdate.getMinutes().toString() + ":" + mdate.getSeconds().toString()
  103. tempSize = tempSize + res.stats[i].stats.size
  104. tempFileList.push(tempFileItem)
  105. }
  106. fileList.value = tempFileList
  107. size.value = tempSize/1024/1024
  108. count.value = tempFileList.length
  109. },
  110. fail: (res : IUniError) => {
  111. uni.showModal({
  112. title: '获取文件状态失败',
  113. content: res.errMsg,
  114. showCancel: false
  115. })
  116. console.error('statFileInfo fail', res)
  117. },
  118. complete: (res : any) => {
  119. console.log("statFileInfo complete", res)
  120. }
  121. } as StatOptions)
  122. }
  123. const showDialog = (item: fileListType) => {
  124. currentFile.value = item
  125. dialogShow.value = true
  126. }
  127. const closeDialog = () => {
  128. dialogShow.value = false
  129. }
  130. const deleteFile = (fileItem: fileListType) => {
  131. const fileManager = uni.getFileSystemManager()
  132. let path = cacheOrData.value + fileItem.path
  133. if (fileItem.isFile) {
  134. fileManager.unlink({
  135. filePath: path,
  136. success: () => {
  137. refreshFile()
  138. closeDialog()
  139. },
  140. fail: (err : IFileSystemManagerFail) => {
  141. uni.showModal({
  142. title: '删除文件失败',
  143. content: err.errMsg,
  144. showCancel: false
  145. })
  146. }
  147. })
  148. } else {
  149. fileManager.rmdir({
  150. dirPath: path,
  151. recursive: true,
  152. success: () => {
  153. refreshFile()
  154. closeDialog()
  155. },
  156. fail: (err : IFileSystemManagerFail) => {
  157. uni.showModal({
  158. title: '删除目录失败',
  159. content: err.errMsg,
  160. showCancel: false
  161. })
  162. }
  163. })
  164. }
  165. }
  166. const clearFile = () => {
  167. const fileManager = uni.getFileSystemManager()
  168. // TODO 3个App平台表现不一致 @颜伊林
  169. fileManager.rmdir({
  170. "dirPath":uni.env.CACHE_PATH,
  171. "recursive":true,
  172. success: (res : FileManagerSuccessResult) => {
  173. console.log("rmdir success", res)
  174. fileList.value = [] as fileListType[]
  175. size.value = 0
  176. count.value = 0
  177. uni.showToast({
  178. title:"清空缓存目录成功",
  179. icon:"success"
  180. })
  181. },
  182. fail: (res : IFileSystemManagerFail) => {
  183. console.error('清空缓存目录失败', res)
  184. uni.showModal({
  185. title: '清空缓存目录失败',
  186. content: res.errMsg,
  187. showCancel: false
  188. })
  189. },
  190. complete: (res : any) => {
  191. console.log("rmdir complete", res)
  192. }
  193. })
  194. }
  195. const openFile = (fileItem: fileListType) => {
  196. let path = cacheOrData.value + fileItem.path
  197. let suffix = path.split('.').pop()
  198. switch(suffix) {
  199. case 'jpg':
  200. case 'png':
  201. case 'gif':
  202. case 'jpeg':
  203. case 'webp':
  204. case 'bmp':
  205. case 'ico':
  206. case 'heic':
  207. case 'heif':
  208. case 'tif':
  209. console.log("path:", path)
  210. uni.previewImage({
  211. urls: [path]
  212. })
  213. break
  214. default:
  215. uni.openDocument({
  216. filePath: path,
  217. success: (res) => {
  218. console.log("openDocument success", res)
  219. },
  220. fail: (res) => {
  221. console.error("openDocument fail", res)
  222. uni.showModal({
  223. title: '打开文件失败',
  224. content: res.errMsg,
  225. showCancel: false
  226. })
  227. }
  228. })
  229. }
  230. }
  231. const snapshot = () => {
  232. uni.getElementById("rootview")!.takeSnapshot({})
  233. }
  234. // 根据路径中/的数量计算缩进样式
  235. const getIndentStyle = (path: string) => {
  236. const matches = path.match(/\//g)
  237. // console.log("matches", matches)
  238. let level = 0
  239. if (matches!=null) {
  240. level = matches.length
  241. }
  242. return {
  243. paddingLeft: `${level * 20}px`
  244. }
  245. }
  246. </script>