sync.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import axios from "@/dbo/main";
  2. import {list} from "@/store/measure";
  3. import {baseLines} from "@/store/baseLine";
  4. import {basePoints} from "@/store/basePoint";
  5. import {fixPoints} from "@/store/fixPoint";
  6. import {photos} from "@/store/photos";
  7. import {accidentPhotos} from "@/store/accidentPhotos";
  8. import {roadPhotos} from "@/store/roadPhotos";
  9. import {base64ToBlob, blobToBase64, debounce, getId} from "@/utils";
  10. import {watch} from "vue";
  11. import {params} from "@/hook";
  12. import router, {writeRouteName} from "@/router";
  13. import {baseURL} from "@/dbo/main";
  14. import {defaultUses, uses} from '@/store/SVGLabel'
  15. const global = window as any;
  16. let count = 0;
  17. export const api =
  18. !global.android
  19. // true
  20. ? // const api = import.meta.env.DEV
  21. {
  22. async setStore(data) {
  23. return axios.post("sceneStore", data);
  24. },
  25. async getStore() {
  26. return (await axios.get("/attach/sceneStore")).data;
  27. },
  28. async uploadImage(file) {
  29. return (
  30. await axios({
  31. url: "/upload",
  32. headers: { "Content-Type": "multipart/form-data" },
  33. method: "post",
  34. data: { file },
  35. })
  36. ).data.data as string;
  37. },
  38. async downloadImage(file) {
  39. window.open(URL.createObjectURL(file));
  40. return true;
  41. },
  42. async getFile(url) {
  43. if (url.includes(baseURL)) {
  44. url = url.substring(baseURL.length);
  45. }
  46. url = url.trim();
  47. const paths = url.split("/")
  48. const notBase64BaseTypes = [
  49. ".png", ".jpg"
  50. ]
  51. const notBase64 = notBase64BaseTypes.some(type => paths[paths.length - 1].includes(type))
  52. if (notBase64) {
  53. // await new Promise(resolve => setTimeout(resolve, 2000))
  54. return baseURL + url
  55. } else {
  56. const data = await axios.get(url, { responseType: "blob" });
  57. const base64 = await blobToBase64(data.data);
  58. return URL.createObjectURL(base64ToBlob(base64))
  59. }
  60. },
  61. async photograph() {
  62. const file = await new Promise<File>(resolve => {
  63. const input = document.createElement('input');
  64. input.type = 'file';
  65. input.click();
  66. input.addEventListener("change", ev => {
  67. resolve(input.files[0])
  68. })
  69. })
  70. return await this.uploadImage(file)
  71. },
  72. async selectPhotoAlbum() {
  73. return await this.photograph()
  74. },
  75. async closePage() {
  76. return router.push({ name: writeRouteName.scene });
  77. },
  78. }
  79. : {
  80. setStore(data) {
  81. return new Promise((resolve) => {
  82. console.log("调用setSceneStore参数", JSON.stringify(data));
  83. global.setSceneStoreCallback = (data) => {
  84. console.log("setSceneStoreCallback返回", data);
  85. resolve(data);
  86. };
  87. global.android.setSceneStore(
  88. params.m + "/store.json",
  89. JSON.stringify(data),
  90. "setSceneStoreCallback"
  91. );
  92. });
  93. },
  94. getStore() {
  95. return new Promise((resolve) => {
  96. console.log("调用getSceneStore");
  97. global.getSceneStoreCallback = (data) => {
  98. console.log("getSceneStoreCallback返回", data);
  99. resolve(data);
  100. };
  101. global.android.getSceneStore(params.m + "/store.json", "getSceneStoreCallback");
  102. });
  103. },
  104. async getFile(fileUrl: string) {
  105. fileUrl = fileUrl.trim();
  106. if (fileUrl.includes(params.m)) {
  107. fileUrl = fileUrl.substring(fileUrl.indexOf(params.m) + params.m.length)
  108. }
  109. fileUrl = new URL(fileUrl, "http://www.a.com").pathname
  110. fileUrl = (params.realPath || params.m) + fileUrl
  111. const paths = fileUrl.split("/")
  112. const notBase64BaseTypes = [
  113. // ".png", ".jpg"
  114. // , ".bin"
  115. ]
  116. const notBase64 = notBase64BaseTypes.some(type => paths[paths.length - 1].includes(type))
  117. if (!notBase64) {
  118. return await new Promise<string>((resolve) => {
  119. const apiName = `getImageCallback${count++}`
  120. global[apiName] = (base64) => {
  121. // console.error("请求url:" + fileUrl, "返回:" + base64.substring(0, 60))
  122. resolve(URL.createObjectURL(base64ToBlob(base64)));
  123. delete global[apiName]
  124. };
  125. global.android.getImage(fileUrl, apiName);
  126. });
  127. } else {
  128. console.log("图片文件直接文件系统读取", fileUrl)
  129. return fileUrl
  130. }
  131. },
  132. uploadImage(file: File) {
  133. return new Promise<string>(async (resolve) => {
  134. const apiName = `uploadImageCallback${count++}`
  135. global[apiName] = (data) => {
  136. console.log("上传图片成功,返回路径为:", data)
  137. resolve(data);
  138. delete global[apiName]
  139. }
  140. const data = await blobToBase64(file);
  141. // console.log("上传图片", params.m + "/" + file.name, "参数:", data);
  142. global.android.uploadImage(params.m + "/attach/upload/" + file.name, data, apiName);
  143. });
  144. },
  145. downloadImage(file: File) {
  146. return new Promise<boolean>(async (resolve) => {
  147. const apiName = `downloadImageCallback${count++}`
  148. global[apiName] = () => {
  149. console.log("已成功下载")
  150. resolve(true);
  151. delete global[apiName]
  152. }
  153. const data = await blobToBase64(file);
  154. // file为base64
  155. console.log("下载图片", file.name);
  156. global.android.downloadImage(file.name, data, apiName);
  157. });
  158. },
  159. photograph() {
  160. return new Promise<string>((resolve) => {
  161. const apiName = `photograph${count++}`
  162. global[apiName] = (data) => {
  163. console.log("拍照后路径:", data)
  164. resolve(data);
  165. delete global[apiName]
  166. }
  167. global.android.cameraPhotograph(params.m, apiName);
  168. });
  169. },
  170. selectPhotoAlbum() {
  171. return new Promise<string>((resolve) => {
  172. const apiName = `selectPhotoAlbum${count++}`
  173. global[apiName] = (data) => {
  174. console.log("获得相册图片路径:", data)
  175. resolve(data);
  176. delete global[apiName]
  177. }
  178. global.android.selectPhotoAlbum(params.m, apiName);
  179. });
  180. },
  181. closePage() {
  182. return new Promise((resolve) => {
  183. global.closeWebViewCallback = resolve;
  184. global.android.closeWebView('closeWebViewCallback');
  185. });
  186. },
  187. };
  188. export const back = () => {
  189. if (history.state.back) {
  190. router.back();
  191. } else {
  192. api.closePage();
  193. }
  194. };
  195. const loadStore = async () => {
  196. const data: any = await api.getStore();
  197. list.value = data?.measures || [];
  198. baseLines.value = data?.baseLines || [];
  199. basePoints.value = data?.basePoints || [];
  200. fixPoints.value = data?.fixPoints || [];
  201. photos.value = data?.photos || [];
  202. accidentPhotos.value = data?.accidentPhotos || [];
  203. roadPhotos.value = data?.roadPhotos || [];
  204. uses.value = data?.uses || defaultUses
  205. syncSceneStore();
  206. console.log("开始同步syncSceneStore")
  207. };
  208. export const updateSceneStore = debounce(api.setStore, 300);
  209. export const uploadImage = (blob: Blob) => {
  210. const file = new File([blob], `${getId()}.jpg`);
  211. return api.uploadImage(file);
  212. };
  213. export const downloadImage = async (
  214. data: Blob | string,
  215. name: string = getId()
  216. ) => {
  217. const blob: Blob =
  218. typeof data === "string"
  219. ? (await axios.get(data, { responseType: "blob" })).data
  220. : data;
  221. const file = new File([blob], name, { type: "image/jpeg" });
  222. return await api.downloadImage(file);
  223. };
  224. const syncSceneStore = () => {
  225. return watch(
  226. () => ({
  227. measures: list.value,
  228. baseLines: baseLines.value,
  229. basePoints: basePoints.value,
  230. fixPoints: fixPoints.value,
  231. photos: photos.value,
  232. uses: uses.value,
  233. accidentPhotos: accidentPhotos.value,
  234. roadPhotos: roadPhotos.value,
  235. }),
  236. (data) => {
  237. console.log("监听到数据变化,自动保存store")
  238. updateSceneStore(data);
  239. },
  240. { deep: true }
  241. );
  242. };
  243. //
  244. // // if (global.android) {
  245. // const isEditInput = (dom: HTMLElement) => {
  246. // const tagName = dom.tagName.toUpperCase();
  247. // const isInput = tagName === "INPUT"
  248. // const isTextarea = tagName === "TEXTAREA"
  249. // console.log(isInput && dom.getAttribute("type") === "text")
  250. // if (!(isInput && dom.getAttribute("type") === "text") && !isTextarea) {
  251. // return false;
  252. // }
  253. // console.log("???")
  254. // return !dom.hasAttribute("readonly")
  255. // }
  256. // document.documentElement.addEventListener('focusin', ev => {
  257. // console.log("获得焦点")
  258. // console.log(ev.target)
  259. // if (isEditInput(ev.target as HTMLElement)) {
  260. // global.android.inputMethodManager(true);
  261. // }
  262. // })
  263. // document.documentElement.addEventListener('focusout', ev => {
  264. // console.log("失去焦点")
  265. // console.log(ev.target)
  266. // if (isEditInput(ev.target as HTMLElement)) {
  267. // global.android.inputMethodManager(false);
  268. // }
  269. // })
  270. // // }
  271. loadStore().catch((e) => {
  272. console.error(e);
  273. alert("场景数据加载失败");
  274. });