fIleOperation.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <el-dropdown trigger="click">
  3. <div class="el-dropdown-link" title="文件">
  4. <img :src="local_storage" alt="" class="header_right_icon left">
  5. <span class="header_right_title_span">文件</span>
  6. </div>
  7. <template #dropdown>
  8. <el-dropdown-menu>
  9. <el-dropdown-item class="header_menu_li" @click="cloudSave()"
  10. style="color: #26a69a;">云端存储</el-dropdown-item>
  11. <el-dropdown-item class="header_menu_li" @click="importFile()"
  12. style="color: #26a69a;">导入</el-dropdown-item>
  13. <el-dropdown-item class="header_menu_li" @click="exportFile()"
  14. style="color: #26a69a;">导出</el-dropdown-item>
  15. </el-dropdown-menu>
  16. </template>
  17. </el-dropdown>
  18. <el-dialog v-model="cloudDialog" title="云端存储" width="800">
  19. <el-row :gutter="24" style="text-align: center;">
  20. <el-col :span="7" style="margin-top: 15px;">
  21. <el-card :body-style="{ padding: '0px' }">
  22. <div style="padding: 14px;">
  23. </div>
  24. </el-card>
  25. </el-col>
  26. <el-col :span="7" v-for="(item, index) in cloudData" style="margin-top: 15px;">
  27. <el-card :body-style="{ padding: '0px' }" @click="openFile($event, item)">
  28. <div class="cloud_card_top">
  29. <img @click="share($event, item.filenameid)" src="../../assets/img/分享.png" alt="">
  30. <div>
  31. <img @click="saveFile($event, item.filenameid)" src="../../assets//img/save.png" alt="">
  32. <img @click="deleteFile($event, item.filename)" src="../../assets//img/delete.png" alt="">
  33. </div>
  34. </div>
  35. <div class="cloud_card_bottom" style="padding: 14px;">
  36. <span>{{ item.filename }}</span><br />
  37. <span>上次修改:{{ new Date(item.date).toLocaleDateString() }}</span>
  38. </div>
  39. </el-card>
  40. </el-col>
  41. </el-row>
  42. <template #footer>
  43. <div class="dialog-footer">
  44. <el-button @click="cloudDialog = false">关闭</el-button>
  45. </div>
  46. </template>
  47. </el-dialog>
  48. </template>
  49. <script setup>
  50. import { ref} from 'vue'
  51. import { ElMessage } from 'element-plus'
  52. import Blockly from 'blockly';
  53. import local_storage from '../../assets/img/local_storage.png'
  54. import '../../assets/css/header.css'
  55. import store from '../../stores/blockly'
  56. import { exportFileGlobal } from '../../gloabl/globalMethods'
  57. import userInfo from '../../stores/modules/userInfo'
  58. import axios from 'axios'
  59. import server from '@/config/index'
  60. const props = defineProps({
  61. exportImportFileName: {
  62. type: String
  63. }
  64. })
  65. const emit = defineEmits(["setFileName"])
  66. const user = userInfo()
  67. const exportXml = store.useyXmlStore()
  68. const importFileName = store.useImportFileNameStore()
  69. const LoadBlocklyStatus = store.useLoadBlocklyStatus()
  70. const cloudDialog = ref(false)
  71. const cloudData = ref([])
  72. const cloudSave = () => {
  73. console.log("云端存储", user.userInfo, server)
  74. if (JSON.stringify(user.userInfo) != "{}") {
  75. console.log("云端存储", user.userInfo)
  76. axios.defaults.withCredentials = true
  77. axios.changeOrigin = true
  78. axios.get(`${server.host}blockx/files`).then(res => {
  79. console.table(res.data)
  80. cloudData.value = res.data
  81. })
  82. cloudDialog.value = true
  83. } else {
  84. ElMessage({
  85. message: '请先登录',
  86. type: 'warning',
  87. })
  88. }
  89. }
  90. // 导入文件
  91. const importFile = () => {
  92. const input = document.createElement('input');
  93. input.type = 'file';
  94. input.accept = '.xml';
  95. // input.onClick = e => {
  96. // e.stopPropagation();
  97. // }
  98. input.onchange = e => {
  99. const file = e.target.files[0];
  100. const reader = new FileReader();
  101. reader.onload = e => {
  102. let xml = e.target.result;
  103. exportXml.$patch({ xmlStr: xml })
  104. LoadBlocklyStatus.$patch({ status: true })
  105. importFileName.$patch({ fileName: file.name })
  106. emit("setFileName", file.name)
  107. localStorage.setItem('workspaceXml', xml)
  108. setTimeout(() => {
  109. LoadBlocklyStatus.$patch({ status: false })
  110. }, 100)
  111. };
  112. reader.readAsText(file);
  113. };
  114. input.click();
  115. }
  116. // 导出文件
  117. const exportFile = () => {
  118. let name = props.exportImportFileName + '.xml'
  119. if (exportXml.xmlStr && exportXml.xmlStr != `<xml xmlns="https://developers.google.com/blockly/xml"></xml>`) {
  120. exportFileGlobal(exportXml.xmlStr, name)
  121. } else {
  122. ElMessage({
  123. message: '导出内容为空',
  124. type: 'warning',
  125. })
  126. }
  127. // let blob = new Blob([exportXml], { type: 'text/plain;charset=utf-8' })
  128. // // 创建一个指向Blob对象的URL
  129. // const textURL = window.URL.createObjectURL(blob);
  130. // // 创建一个临时的a标签用于触发下载
  131. // const link = document.createElement('a');
  132. // link.href = textURL;
  133. // link.download = props.exportImportFileName + '.xml'; // 指定下载文件的名称
  134. // document.body.appendChild(link); // 将a标签添加到文档中
  135. // // 触发点击事件以开始下载
  136. // link.click();
  137. // // 清理:移除a标签,释放创建的URL
  138. // document.body.removeChild(link);
  139. // window.URL.revokeObjectURL(textURL);
  140. }
  141. // 分享
  142. const share = (e, id) => {
  143. e.stopPropagation();
  144. // console.log("分享", location.href)
  145. // "https://beta.v.cocorobo.cn/?lang=zh-hans&Qd=5ed71aeb0ff4fc69b32e866b_1721619372665";
  146. const text = location.href + "&Qd=" + id;
  147. navigator.clipboard.writeText(text).then(() => {
  148. console.log('内容已复制到剪贴板');
  149. }).catch(err => {
  150. console.error('复制到剪贴板失败: ', err);
  151. });
  152. }
  153. // 删除文件
  154. const deleteFile = (e, id) => {
  155. e.stopPropagation();
  156. // https://api.cocorobo.cn/blockx/1721619372665
  157. axios.delete(`https://api.cocorobo.cn/blockx/${id}`).then(res => {
  158. console.log(res)
  159. if (res.status == 200) {
  160. ElMessage({
  161. message: '删除成功',
  162. type: 'success',
  163. })
  164. cloudSave()
  165. } else {
  166. ElMessage({
  167. message: '删除失败',
  168. type: 'error',
  169. })
  170. }
  171. })
  172. }
  173. // 保存文件
  174. const saveFile = (e, name) => {
  175. e.stopPropagation();
  176. // https://api.cocorobo.cn/blockx/1716428157190
  177. let form = new FormData()
  178. // form.append('platformType', "CocoPi")
  179. form.append('filename', name)
  180. form.append('xml', exportXml.xmlStr)
  181. // form.append('code', "")
  182. axios.put(`https://api.cocorobo.cn/blockx/${name}`, form).then(res => {
  183. console.log(res)
  184. if (res.data == "OK") {
  185. ElMessage({
  186. message: '保存成功',
  187. type: 'success',
  188. })
  189. }
  190. else {
  191. ElMessage({
  192. message: '保存失败',
  193. type: 'error',
  194. })
  195. }
  196. })
  197. }
  198. // 打开文件
  199. const openFile = (e, item) => {
  200. e.stopPropagation();
  201. // https://api.cocorobo.cn/blockx/5ed71aeb0ff4fc69b32e866b_1710676497206
  202. axios.get(`https://api.cocorobo.cn/blockx/${item.filenameid}`).then(res => {
  203. console.log(res.data.xml.slice(5))
  204. if (res.status == 200) {
  205. const xml = res.data.xml.slice(5)
  206. importFileName.$patch({ fileName: item.filename })
  207. emit("setFileName", item.filename)
  208. exportXml.$patch({ xmlStr: xml })
  209. LoadBlocklyStatus.$patch({ status: true })
  210. localStorage.setItem('workspaceXml', xml)
  211. setTimeout(() => {
  212. LoadBlocklyStatus.$patch({ status: false })
  213. cloudDialog.value = false
  214. }, 100)
  215. }
  216. else {
  217. ElMessage({
  218. message: '打开失败',
  219. type: 'error',
  220. })
  221. }
  222. })
  223. }
  224. </script>
  225. <style scoped lang="scss">
  226. .cloud_card_top {
  227. display: flex;
  228. justify-content: space-between;
  229. background-color: #454fb5;
  230. padding: 8px 10px;
  231. img {
  232. width: 25px;
  233. height: 25px;
  234. }
  235. }
  236. </style>