index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <div
  3. ref="wrapperRef"
  4. @mousedown="addDrawAreaFocus"
  5. v-contextmenu="contextMenus"
  6. v-click-outside="remDrawAreaFocus"
  7. >
  8. <canvas ref="canvasRef" class="background-grid"></canvas>
  9. </div>
  10. </template>
  11. <script lang="ts" setup>
  12. import {storeToRefs} from 'pinia'
  13. import {onMounted, onUnmounted} from 'vue'
  14. import {useFabricStore, useMainStore, useTemplatesStore, useUserStore} from '@/store'
  15. import {useRouter} from 'vue-router'
  16. import {unzip} from "@/utils/crypto"
  17. import {getDesignTemplateEdit, getPreViewTemplate, getTemplateData, newDesignOrder, tmpSaveUserDesign, updateDesignTemplate} from '@/api/template'
  18. import {contextMenus} from '@/configs/contextMenu'
  19. import {initEditor} from '@/views/Canvas/useCanvas'
  20. import {initPixi} from '@/views/Canvas/usePixi'
  21. import {ElMessage, ElLoading} from 'element-plus'
  22. import useCanvasHotkey from '@/hooks/useCanvasHotkey'
  23. import useCanvasExport from "@/hooks/useCanvasExport";
  24. const fabricStore = useFabricStore()
  25. const mainStore = useMainStore()
  26. const router = useRouter()
  27. const templatesStore = useTemplatesStore()
  28. const userStore = useUserStore()
  29. const {uuid} = storeToRefs(userStore);
  30. const {wrapperRef, canvasRef} = storeToRefs(fabricStore)
  31. const {getJSONData, getSVGData} = useCanvasExport()
  32. let outerSessionId = ""
  33. let tmpSaveFlag = true
  34. const {drawAreaFocus} = storeToRefs(mainStore)
  35. const {keydownListener, keyupListener, pasteListener} = useCanvasHotkey()
  36. const addDrawAreaFocus = () => {
  37. if (!drawAreaFocus.value) mainStore.setDrawAreaFocus(true)
  38. }
  39. const remDrawAreaFocus = () => {
  40. if (drawAreaFocus.value) mainStore.setDrawAreaFocus(false)
  41. }
  42. const getTemplateDetail = async (pk: number) => {
  43. // const result = await getTemplateData(pk)
  44. // if (result.data && result.data.code === 200 && result.data.data) {
  45. // try {
  46. // router.push(`${router.currentRoute.value.path}?template=${pk}`)
  47. // console.log('result.data.data.id:', result.data.data.id)
  48. // const data = unzip(result.data.data.data)
  49. // await templatesStore.changeTemplate(data)
  50. // } catch (error) {
  51. // ElMessage({
  52. // type: 'error',
  53. // message: '模板加载失败,请联系管理员修改bug了',
  54. // })
  55. // }
  56. // }
  57. //todo 传参测试
  58. const templateParams = {
  59. backgroundWidth: 250.0,
  60. backgroundHeight: 300.0,
  61. backgroundColor: 'rgba(200, 100, 100, 1)'
  62. }
  63. const params = {
  64. id: pk,
  65. // params: JSON.stringify(templateParams)
  66. }
  67. const res = await getDesignTemplateEdit(params)
  68. if (res.httpCode == 200) {
  69. try {
  70. templatesStore.setTemplateName(res.data.templateName)
  71. templatesStore.setProductIdentity(res.data.productIdentity ? res.data.productIdentity.split(",") : [])
  72. const data = res.data.jsonContent
  73. await templatesStore.changeTemplate(JSON.parse(data))
  74. } catch (e) {
  75. ElMessage({
  76. type: 'error',
  77. message: '模板加载失败,请联系系统管理员',
  78. })
  79. }
  80. }
  81. }
  82. const getPreviewTemplateDetail = async (pk: number, templateParams: any, outerSessionId: any) => {
  83. //todo 传参测试
  84. // const templateParams = {
  85. // backgroundWidth: 250.0,
  86. // backgroundHeight: 300.0,
  87. // backgroundColor: 'rgba(200, 100, 100, 1)'
  88. // }
  89. if (!outerSessionId) return
  90. let params = {}
  91. if (!templateParams) {
  92. params = {
  93. id: pk,
  94. outerSessionId: outerSessionId
  95. }
  96. } else {
  97. params = {
  98. id: pk,
  99. params: JSON.stringify(templateParams),
  100. outerSessionId: outerSessionId
  101. }
  102. }
  103. const res = await getPreViewTemplate(params)
  104. if (res.httpCode == 200) {
  105. try {
  106. templatesStore.setTemplateName(res.data.templateName)
  107. templatesStore.setProductIdentity(res.data.productIdentity ? res.data.productIdentity.split(",") : [])
  108. const data = res.data.jsonContent
  109. await templatesStore.changeTemplate(JSON.parse(data))
  110. } catch (e) {
  111. ElMessage({
  112. type: 'error',
  113. message: '模板加载失败,请联系系统管理员',
  114. })
  115. }
  116. }
  117. }
  118. const initRouter = async (templateId: number, runMode: number, outerSessionId: any) => {
  119. if (templateId) {
  120. templatesStore.setTemplateId(templateId)
  121. const loadingInstance = ElLoading.service({fullscreen: true, background: 'rgba(122, 122, 122, 0.5)'})
  122. //判断一下是后台设计还是前台预览
  123. if (runMode == 1) {
  124. await getTemplateDetail(templateId)
  125. } else if (runMode == 0) {
  126. await getPreviewTemplateDetail(templateId, null, outerSessionId)
  127. }
  128. nextTick(() => loadingInstance.close())
  129. }
  130. }
  131. //递归调用的目的是不会导致任务堆积,虽然也没什么可能存一下超过5秒
  132. const tmpSaveCurrentTemplate = () => {
  133. if (tmpSaveFlag) {
  134. const tmpTemplate = {
  135. templateName: outerSessionId,
  136. jsonContent: getJSONData()
  137. }
  138. tmpSaveUserDesign(JSON.stringify(tmpTemplate)).then((res) => {
  139. if (res.httpCode == 200) {
  140. // ElMessage.success('暂存成功')
  141. setTimeout(tmpSaveCurrentTemplate, 5000);
  142. }
  143. })
  144. }
  145. }
  146. onMounted(async () => {
  147. const query = router.currentRoute.value.query
  148. initRouter(query.template, query.runMode, query.sessionId)
  149. initEditor(query.template)
  150. initPixi()
  151. outerSessionId = query.sessionId
  152. document.addEventListener('keydown', keydownListener)
  153. document.addEventListener('keyup', keyupListener)
  154. window.addEventListener('blur', keyupListener)
  155. window.addEventListener('paste', pasteListener as any)
  156. if (query.runMode == 0) {
  157. // 使用iframe方案,本网页是内嵌页面
  158. // 监听来自父页面的消息
  159. window.addEventListener("message", function (event) {
  160. // 确保消息来自信任的来源
  161. // if (event.origin !== "https://www.sd2000.com") {
  162. // return;
  163. // }
  164. // 处理接收到的消息
  165. console.log("Received message:", event.data);
  166. //消息格式
  167. // {
  168. // msgType: 'loadTemplate',
  169. // data: {
  170. // xxx
  171. // }
  172. // }
  173. const message = JSON.parse(event.data);
  174. if (message.msgType == "loadTemplate") {
  175. getPreviewTemplateDetail(query.template, message.data, uuid.value)
  176. } else if (message.msgType == "submitOrder") {
  177. //提交当前设计
  178. // const svgData: string[] = []
  179. // svgData.push(btoa(unescape(encodeURIComponent(getSVGData()))))
  180. // exportSVG()
  181. //先停止自动暂存定时器
  182. tmpSaveFlag = false
  183. const svgHtml = getSVGData()
  184. console.log(svgHtml)
  185. newDesignOrder(svgHtml, uuid.value).then((response) => {
  186. if (response.httpCode == 200) {
  187. console.log(response.data)
  188. //给父页面发送canClose消息,表示可以关掉本页面了
  189. const closeMsg = {
  190. msgType: 'canClose'
  191. }
  192. window.parent.postMessage(JSON.stringify(closeMsg), '*');
  193. }
  194. });
  195. }
  196. })
  197. //每隔5秒暂存一次用户的设计
  198. setTimeout(tmpSaveCurrentTemplate, 5000);
  199. }
  200. })
  201. onUnmounted(() => {
  202. document.removeEventListener('keydown', keydownListener)
  203. document.removeEventListener('keyup', keyupListener)
  204. window.removeEventListener('blur', keyupListener)
  205. window.removeEventListener('paste', pasteListener as any)
  206. })
  207. </script>
  208. <style lang="scss" scoped>
  209. .full-size {
  210. height: 100%;
  211. width: 100%;
  212. }
  213. .background-grid {
  214. --offsetX: 0px;
  215. --offsetY: 0px;
  216. --size: 8px;
  217. --color: #dedcdc;
  218. background-image: linear-gradient(45deg, var(--color) 25%, transparent 0, transparent 75%, var(--color) 0),
  219. linear-gradient(45deg, var(--color) 25%, transparent 0, transparent 75%, var(--color) 0);
  220. background-position: var(--offsetX) var(--offsetY), calc(var(--size) + var(--offsetX)) calc(var(--size) + var(--offsetY));
  221. background-size: calc(var(--size) * 2) calc(var(--size) * 2);
  222. }
  223. </style>@/views/Canvas/usePixi