project.ts 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681
  1. import { reactive, ref } from 'vue';
  2. import { addCollection, updateCollection, getCollection, cdn } from './api';
  3. import {
  4. getPayList,
  5. getDownloadList,
  6. Frame,
  7. get2dComponentJs,
  8. getTemPngs,
  9. // getDeployPngs,
  10. img_cdn,
  11. img_upCdn,
  12. getFrameDownloadList,
  13. getComponentPurchased,
  14. getGoods,
  15. // getDeployAccess,
  16. } from './download';
  17. import { rootDomain } from './defaults';
  18. import { newFile, queryURLParams } from './common';
  19. import axios from 'axios';
  20. import { MessagePlugin } from 'tdesign-vue-next';
  21. import { useUser } from '@/services/user';
  22. import { getResource } from './handle3d';
  23. import { s8 } from './random';
  24. import { load3d } from './load3d';
  25. import router from '@/router';
  26. import { noLoginTip } from './utils';
  27. import localforage from 'localforage';
  28. export const activedGroup = ref('');
  29. export const activeAssets = ref('system');
  30. const { user } = useUser();
  31. const isVip = () => {
  32. if (!(user && user.id)) {
  33. MessagePlugin.warning(noLoginTip);
  34. return;
  35. }
  36. if (!user.vip) {
  37. MessagePlugin.info('需要开通会员~');
  38. return;
  39. }
  40. return true;
  41. };
  42. const taskDialog = reactive({
  43. visible: false,
  44. tasks: [],
  45. cancel: false,
  46. reload: false,
  47. downloadList: [],
  48. });
  49. export const useTask = () => {
  50. const setTask = (key, value) => {
  51. taskDialog[key] = value;
  52. };
  53. return {
  54. taskDialog,
  55. setTask,
  56. };
  57. };
  58. export const reDownload = async () => {
  59. taskDialog.tasks[1].status = 'process';
  60. taskDialog.reload = false;
  61. let result = await saveZip(taskDialog.downloadList);
  62. if (result === 'error') {
  63. taskDialog.tasks[1].status = 'error';
  64. taskDialog.reload = true;
  65. return;
  66. }
  67. taskDialog.tasks[1].status = 'success';
  68. MessagePlugin.closeAll();
  69. taskDialog.tasks[2].status = 'success';
  70. MessagePlugin.success('下载成功,请在浏览器下载列表中查看');
  71. taskDialog.visible = false;
  72. };
  73. const payDialog = reactive({
  74. visible: false,
  75. data: {
  76. price: 0,
  77. list: [],
  78. hasJs: false,
  79. checked: true,
  80. },
  81. token: false,
  82. });
  83. export const usePay = () => {
  84. const setPay = (key, value) => {
  85. payDialog[key] = value;
  86. };
  87. return {
  88. payDialog,
  89. setPay,
  90. };
  91. };
  92. const prePay = async () => {
  93. if (user.vipData?.deployment) {
  94. //可视化会员
  95. if ((user.vipData.deployment & 128) === 128) {
  96. //直接下载
  97. payDialog.token = true;
  98. doDownloadProjectSource();
  99. return;
  100. }
  101. }
  102. //TODO 付费
  103. let purchased = await getComponentPurchased({
  104. pngs: [...prePayList.pngs],
  105. jsPens: [],
  106. iotPens: [],
  107. svgPens: [],
  108. });
  109. if (
  110. [...prePayList.jsPens].length ||
  111. [...prePayList.iotPens].length ||
  112. [...prePayList.svgPens].length
  113. ) {
  114. payDialog.data.hasJs = true;
  115. } else {
  116. payDialog.data.hasJs = false;
  117. }
  118. let names = purchased.map((item) => item.name);
  119. let goods = await getGoods();
  120. let list = [...prePayList.pngs].filter((item) => !names.includes(item));
  121. if (!list.length) {
  122. //直接下载
  123. doDownloadProjectSource();
  124. } else {
  125. let unitPrice = goods.find((item) => item.type === '图片图元').unitPrice;
  126. payDialog.data.price = unitPrice * list.length;
  127. payDialog.data.checked = true;
  128. payDialog.visible = true;
  129. payDialog.data.list = list;
  130. }
  131. };
  132. export const payProjectDialog = reactive({
  133. visible: false,
  134. data: {
  135. price: 0,
  136. payAll: false,
  137. list: [],
  138. title: '',
  139. checked: true,
  140. payList: [],
  141. },
  142. token: '',
  143. });
  144. /*
  145. const prePayProject = async () => {
  146. if (user.vipData?.deployment) {
  147. //可视化会员
  148. if ((user.vipData.deployment & 128) === 128) {
  149. //直接下载
  150. payDialog.token = true;
  151. doDownloadProject();
  152. return;
  153. }
  154. }
  155. const result: {
  156. token?: string;
  157. vip?: boolean;
  158. error?: string;
  159. deployment?: any;
  160. } = await getDeployAccess(
  161. Object.keys(page3dDatas).length ? '3d,v' : 'v',
  162. prePayList
  163. );
  164. if (result.vip) {
  165. if (result.token) {
  166. payProjectDialog.token = result.token;
  167. doDownloadProject();
  168. return;
  169. }
  170. }
  171. //图形库
  172. let _goods = await getGoods();
  173. let purchasedList = await getComponentPurchased(prePayList);
  174. payProjectDialog.data.list = [];
  175. // return;
  176. payProjectDialog.data.payAll = false;
  177. // _goods.forEach((goods)=>{
  178. for (let i = 0; i < _goods.length; i++) {
  179. let goods = _goods[i];
  180. let purchased = purchasedList?.filter((_item) => _item.type === goods.type);
  181. let names = purchased.map((item) => item.name);
  182. let list = [];
  183. if (goods.type === '图片图元') {
  184. list = [...prePayList.pngs];
  185. } else if (goods.type === 'JS线性图元') {
  186. list = [...prePayList.jsPens];
  187. } else if (goods.type === 'SVG线性图元') {
  188. list = [...prePayList.svgPens];
  189. } else if (goods.type === '控件') {
  190. list = [...prePayList.iotPens];
  191. }
  192. let num = 0;
  193. if (goods.type === 'SVG线性图元' && [...prePayList.svgPens].includes('*')) {
  194. //需要购买全部
  195. num = goods.count - names.length;
  196. payProjectDialog.data.payAll = true;
  197. } else {
  198. // list.forEach((item)=>{
  199. for (let j = 0; j < list.length; j++) {
  200. let item = list[j];
  201. if (!names.includes(item)) {
  202. if (goods.type === '控件') {
  203. payProjectDialog.data.list.push({
  204. name: item,
  205. });
  206. } else if (goods.type === 'JS线性图元') {
  207. payProjectDialog.data.list.push({
  208. svg: globalThis.jsPensMap ? globalThis.jsPensMap[item] : item,
  209. });
  210. } else {
  211. payProjectDialog.data.list.push({
  212. img: item,
  213. });
  214. }
  215. num += 1;
  216. }
  217. }
  218. }
  219. goods.num = num;
  220. }
  221. let price = 0;
  222. for (let i = 0; i < _goods.length; i++) {
  223. price += _goods[i].num * _goods[i].unitPrice;
  224. }
  225. payProjectDialog.data.price = price;
  226. let payList = [];
  227. let names = purchasedList.map((item) => item.name);
  228. prePayList.pngs.forEach((item) => {
  229. if (!names.includes(item)) {
  230. payList.push({
  231. type: '图片图元',
  232. name: item,
  233. });
  234. }
  235. });
  236. prePayList.jsPens.forEach((item) => {
  237. if (!names.includes(item)) {
  238. payList.push({
  239. type: 'JS线性图元',
  240. name: item,
  241. });
  242. }
  243. });
  244. prePayList.iotPens.forEach((item) => {
  245. if (!names.includes(item)) {
  246. payList.push({
  247. type: '控件',
  248. name: item,
  249. });
  250. }
  251. });
  252. if ([...prePayList.svgPens].includes('*')) {
  253. payList.push({
  254. type: 'SVG线性图元',
  255. });
  256. } else {
  257. prePayList.svgPens.forEach((item) => {
  258. if (!names.includes(item)) {
  259. payList.push({
  260. type: 'SVG线性图元',
  261. name: item,
  262. });
  263. }
  264. });
  265. }
  266. payProjectDialog.data.checked = true;
  267. payProjectDialog.data.payList = payList;
  268. switch (downloadType) {
  269. case Frame.html:
  270. payProjectDialog.data.title = '下载离线部署包';
  271. break;
  272. case Frame.vue2:
  273. payProjectDialog.data.title = '下载vue2组件包';
  274. break;
  275. case Frame.vue3:
  276. payProjectDialog.data.title = '下载vue3组件包';
  277. break;
  278. case Frame.react:
  279. payProjectDialog.data.title = '下载react组件包';
  280. break;
  281. }
  282. if (payProjectDialog.data.price === 0) {
  283. doDownloadProject();
  284. } else {
  285. payProjectDialog.visible = true;
  286. }
  287. };*/
  288. const data = reactive({
  289. id: undefined,
  290. tree: [
  291. // {
  292. // value: '1',
  293. // label: '文件夹1',
  294. // children: [
  295. // {
  296. // value: '11',
  297. // label: '页面1',
  298. // type: 'page',
  299. // pageId: '1',
  300. // pageType: '', //v/2d/3d
  301. // tag: '首页',
  302. // },
  303. // ],
  304. // },
  305. // {
  306. // value: '2',
  307. // label: '文件夹2',
  308. // children: [
  309. // {
  310. // value: '21',
  311. // label: '页面1',
  312. // type: 'page',
  313. // },
  314. // {
  315. // value: '22',
  316. // label: '页面1',
  317. // type: 'page',
  318. // },
  319. // ],
  320. // },
  321. ],
  322. actived: [],
  323. });
  324. export const graphicsRef = ref(null);
  325. const tree = ref();
  326. const activeNode = ref(null);
  327. let activePage = null;
  328. //新建工程
  329. export const newProject = () => {
  330. //新建页面
  331. newFile();
  332. //新建工程
  333. data.tree = [
  334. {
  335. value: s8(),
  336. label: '文件夹',
  337. children: [
  338. {
  339. value: s8(),
  340. label: '页面',
  341. type: 'page',
  342. pageType: '', //v/2d/3d
  343. },
  344. ],
  345. },
  346. ];
  347. data.id = undefined;
  348. //展示工程
  349. activeAssets.value = 'structure';
  350. graphicsRef.value.assetsChange(activeAssets.value);
  351. activedGroup.value = '工程';
  352. };
  353. const getHomePage = (treeData) => {
  354. for (let i = 0; i < treeData.length; i++) {
  355. if (treeData[i].type === 'page' && treeData[i].tag === '首页') {
  356. return treeData[i];
  357. }
  358. if (treeData[i].children) {
  359. const page = getHomePage(treeData[i].children);
  360. if (page) {
  361. return page;
  362. }
  363. }
  364. }
  365. };
  366. export const loadProject = () => {
  367. if (!isVip()) {
  368. return;
  369. }
  370. const input = document.createElement('input');
  371. input.type = 'file';
  372. input.onchange = async (event) => {
  373. const elem = event.target as HTMLInputElement;
  374. if (elem.files && elem.files[0]) {
  375. // 路由跳转 可能在 openFile 后执行
  376. if (elem.files[0].name.endsWith('.zip')) {
  377. let projectData = await uploadProjectSource(elem.files[0]);
  378. if (projectData) {
  379. let home = getHomePage(projectData.data);
  380. if (!home) {
  381. home = projectData.data[0].children?.length
  382. ? projectData.data[0].children[0]
  383. : projectData.data[0];
  384. }
  385. router.push({
  386. path: '/',
  387. query: {
  388. r: Date.now() + '',
  389. id: home.pageId,
  390. },
  391. });
  392. }
  393. //获取首页
  394. if (activedGroup.value !== '工程') {
  395. activeAssets.value = 'structure';
  396. graphicsRef.value.assetsChange(activeAssets.value);
  397. activedGroup.value = '工程';
  398. }
  399. } else {
  400. MessagePlugin.info('打开工程文件只支持 zip 格式');
  401. }
  402. }
  403. };
  404. input.click();
  405. };
  406. export const useProject = () => {
  407. const getProject = async (id: string) => {
  408. if (id === data.id) {
  409. setActive(meta2d.store.data.id);
  410. return;
  411. }
  412. const ret: any = await getCollection('web', id);
  413. data.tree = ret.data;
  414. data.id = ret.id;
  415. setActive(meta2d.store.data.id);
  416. };
  417. const setActive = (pageId) => {
  418. const find = (treeData) => {
  419. for (let i = 0; i < treeData.length; i++) {
  420. if (treeData[i].pageId === pageId) {
  421. data.actived = [treeData[i].value];
  422. return;
  423. }
  424. if (treeData[i].children) {
  425. find(treeData[i].children);
  426. }
  427. }
  428. };
  429. find(data.tree);
  430. };
  431. const setProject = async (data) => {};
  432. const saveProject = async (id?: string, over?: boolean) => {
  433. if (!data.tree.length) {
  434. //无数据
  435. return;
  436. }
  437. if (!activeNode.value && !over) {
  438. return;
  439. }
  440. if (id) {
  441. if (!tree.value) {
  442. // let activePage = getLeaf(activeNode.value.data.value,data.tree);
  443. setData(data.tree, activeNode.value.data.value, 'pageId', id);
  444. // activePage.pageId = id;
  445. } else {
  446. await activeNode.value.setData({ pageId: id });
  447. }
  448. setData(data.tree, activeNode.value.data.value, 'pageId', id);
  449. }
  450. // return
  451. const treeData = (await tree?.value?.getTreeData?.()) || data.tree;
  452. if (!(treeData && treeData.length > 0)) {
  453. return;
  454. }
  455. const _data = {
  456. id: data.id,
  457. data: treeData,
  458. name: 'test',
  459. image: '',
  460. };
  461. // if(data.id&&!id){
  462. // // 已经有工程 没有 不需要更新数据
  463. // return data.id;
  464. // }
  465. if (data.id) {
  466. await updateCollection('web', _data);
  467. return data.id;
  468. } else {
  469. const ret: any = await addCollection('web', _data);
  470. data.id = ret.id;
  471. return ret.id;
  472. }
  473. };
  474. const clearProject = () => {
  475. data.id = undefined;
  476. data.tree = [];
  477. };
  478. const setActivedNode = (node) => {
  479. activeNode.value = node;
  480. // if(!data.tree){
  481. // }
  482. // activePage = getLeaf(node.data.value,data.tree);
  483. };
  484. return {
  485. data,
  486. tree,
  487. activePage,
  488. activeNode,
  489. saveProject,
  490. getProject,
  491. setProject,
  492. clearProject,
  493. setActivedNode,
  494. };
  495. };
  496. const getLeaf = (id, arr: any) => {
  497. arr.forEach((item) => {
  498. if (item.children) {
  499. getLeaf(id, item.children);
  500. } else {
  501. if (item.value === id) {
  502. return item;
  503. }
  504. }
  505. });
  506. };
  507. const setData = (arr: any, id, key, value) => {
  508. arr.forEach((item) => {
  509. if (item.children) {
  510. setData(item.children, id, key, value);
  511. } else {
  512. if (item.value === id) {
  513. item[key] = value;
  514. }
  515. }
  516. });
  517. };
  518. let downloadType: Frame = Frame.html;
  519. let pageDatas = {};
  520. let page3dDatas = {};
  521. let page2dDatas = {};
  522. const setDownloadType = (type: Frame) => {
  523. downloadType = type;
  524. };
  525. const prePayList = reactive({
  526. pngs: new Set<string>(),
  527. jsPens: new Set<string>(),
  528. iotPens: new Set<string>(),
  529. svgPens: new Set<string>(),
  530. });
  531. let downloadList = [];
  532. const isV = (url) => {
  533. return (
  534. url.indexOf(`v${rootDomain}`) !== -1 ||
  535. url.indexOf(`view${rootDomain}/v`) !== -1 ||
  536. url.indexOf(`/view/v`) !== -1 ||
  537. url.indexOf(`/preview`) !== -1
  538. );
  539. };
  540. const is3D = (url) => {
  541. return (
  542. url.indexOf(`3d${rootDomain}`) !== -1 ||
  543. url.indexOf(`view${rootDomain}/3d`) !== -1 ||
  544. url.indexOf(`/view/3d`) !== -1
  545. );
  546. };
  547. const is2D = (url) => {
  548. return (
  549. url.indexOf(`2d${rootDomain}`) !== -1 ||
  550. url.indexOf(`view${rootDomain}/2d`) !== -1 ||
  551. url.indexOf(`/view/2d`) !== -1
  552. );
  553. };
  554. const getPageDataByUrl = async (url) => {
  555. let id = queryURLParams(url.split('?')[1])?.id;
  556. if (isV(url)) {
  557. if (!pageDatas[id]) {
  558. let data = await getCollection('v', id);
  559. pageDatas[id] = data.data;
  560. }
  561. //TODO 更改图纸中的iframe地址
  562. if (downloadType === Frame.html) {
  563. return `/view?data=${id}`; //`/view/v?data=${id}`
  564. } else {
  565. return `/2d?id=${id}`;
  566. }
  567. } else if (is3D(url)) {
  568. if (!page3dDatas[id]) {
  569. let data = await getCollection('3d', id);
  570. page3dDatas[id] = data.data;
  571. }
  572. if (downloadType === Frame.html) {
  573. return `/view?data=${id}`; //`/view/v?data=${id}`
  574. } else {
  575. return `/view/index.html?data=${id}`;
  576. }
  577. } else if (is2D(url)) {
  578. if (!page2dDatas[id]) {
  579. let data = await getCollection('2d', id);
  580. page2dDatas[id] = data.data;
  581. }
  582. if (downloadType === Frame.html) {
  583. return `/view?data=${id}`; //`/view/v?data=${id}`
  584. } else {
  585. return `/2d?id=${id}`;
  586. }
  587. }
  588. };
  589. //获取工程包含的所有数据内容
  590. /**
  591. *
  592. * @param replace 是否替换地址
  593. */
  594. const getDatas = async (replace = true) => {
  595. const list = treeToList(data.tree).filter((item) => item.type && item.pageId);
  596. pageDatas = {};
  597. page3dDatas = {};
  598. page2dDatas = {};
  599. await Promise.all(
  600. list.map(async (item: any) => {
  601. let v = await getCollection('v', item.pageId);
  602. pageDatas[item.pageId] = v.data;
  603. if (v.data?.pens?.length) {
  604. // 内嵌iframe网页
  605. const pens = v.data.pens.filter(
  606. (pen) =>
  607. pen.name === 'iframe' &&
  608. (isV(pen.iframe) || is3D(pen.iframe) || is2D(pen.iframe))
  609. );
  610. for (let i = 0; i < pens.length; i++) {
  611. let pen = pens[i];
  612. let iframe = await getPageDataByUrl(pen.iframe);
  613. if (replace) {
  614. pen.iframe = iframe;
  615. }
  616. }
  617. for (let i = 0; i < v.data.pens.length; i++) {
  618. let pen = v.data.pens[i];
  619. if (pen.events?.length) {
  620. for (let j = 0; j < pen.events.length; j++) {
  621. //打开弹框
  622. const actions = pen.events[j].actions; //.filter((action)=>action.action === 14);
  623. for (let k = 0; k < actions.length; k++) {
  624. let action = actions[k];
  625. if (action.action === 14) {
  626. //打开弹框
  627. let iframe = await getPageDataByUrl(action.params);
  628. if (replace) {
  629. action.params = iframe;
  630. }
  631. } else if (action.action === 1) {
  632. //更改iframe属性
  633. if (action.value?.iframe) {
  634. let iframe = await getPageDataByUrl(action.value.iframe);
  635. if (replace) {
  636. action.value.iframe = iframe;
  637. }
  638. }
  639. }
  640. }
  641. }
  642. }
  643. if (pen.triggers?.length) {
  644. for (let j = 0; j < pen.triggers.length; j++) {
  645. const trigger = pen.triggers[j];
  646. for (let k = 0; k < trigger.status.length; k++) {
  647. let status = trigger.status[k];
  648. for (let l = 0; l < status.actions.length; l++) {
  649. let action = status.actions[l];
  650. if (action.action === 14) {
  651. //打开弹框
  652. // action.params = await getPageDataByUrl(action.params);
  653. let iframe = await getPageDataByUrl(action.params);
  654. if (replace) {
  655. action.params = iframe;
  656. }
  657. } else if (action.action === 1) {
  658. //更改iframe属性
  659. if (action.value?.iframe) {
  660. // action.value.iframe = await getPageDataByUrl(action.value.iframe);
  661. let iframe = await getPageDataByUrl(action.value.iframe);
  662. if (replace) {
  663. action.value.iframe = iframe;
  664. }
  665. }
  666. }
  667. }
  668. }
  669. }
  670. }
  671. }
  672. }
  673. })
  674. );
  675. };
  676. const getEnterprisePens = async () => {
  677. let pngs = [],
  678. jsPens = [],
  679. iotPens = [],
  680. svgPens = [];
  681. for (let key in pageDatas) {
  682. const pageData = pageDatas[key];
  683. const payList = getPayList(pageData);
  684. pngs.push(...payList.pngs);
  685. jsPens.push(...payList.jsPens);
  686. iotPens.push(...payList.iotPens);
  687. svgPens.push(...payList.svgPens);
  688. }
  689. for (let key in page2dDatas) {
  690. const pageData = page2dDatas[key];
  691. const payList = getPayList(pageData);
  692. pngs.push(...payList.pngs);
  693. jsPens.push(...payList.jsPens);
  694. iotPens.push(...payList.iotPens);
  695. svgPens.push(...payList.svgPens);
  696. }
  697. prePayList.pngs = new Set(pngs);
  698. prePayList.jsPens = new Set(jsPens);
  699. prePayList.iotPens = new Set(iotPens);
  700. prePayList.svgPens = new Set(svgPens);
  701. };
  702. // 下载工程
  703. export const downloadProject = async (type: Frame) => {
  704. // if (!isVip()) {
  705. // return;
  706. // }
  707. downloadType = type;
  708. //通过工程获取所有的页面数据 ,包括2d 3d v
  709. await getDatas();
  710. // if (isDownload) {
  711. //安装包
  712. await doDownloadProject();
  713. return;
  714. // }
  715. //获取 2d 大屏企业图形库
  716. // await getEnterprisePens();
  717. // await prePayProject();
  718. };
  719. export const doDownloadProject = async () => {
  720. //TODO 验证付费图形库
  721. taskDialog.visible = true;
  722. taskDialog.tasks = [
  723. {
  724. status: 'prepare',
  725. title: '获取工程数据资源',
  726. },
  727. {
  728. status: 'prepare',
  729. title: '下载工程资源',
  730. },
  731. {
  732. status: 'prepare',
  733. title: '完成',
  734. },
  735. ];
  736. taskDialog.tasks[0].status = 'process';
  737. let dList = [];
  738. let flag_3d = false;
  739. if (downloadType === Frame.html) {
  740. for (let key in pageDatas) {
  741. pageDatas[key].userId = user.id;
  742. dList.push(...(await getDownloadList(pageDatas[key], key, false)));
  743. }
  744. for (let key in page2dDatas) {
  745. page2dDatas[key].userId = user.id;
  746. dList.push(...(await getDownloadList(page2dDatas[key], key, false)));
  747. }
  748. for (let key in page3dDatas) {
  749. flag_3d = true;
  750. let source3dList = await getResource(
  751. page3dDatas[key].data,
  752. key,
  753. 'deploy'
  754. );
  755. dList.push(...source3dList);
  756. }
  757. //下载运行环境文件
  758. dList.push(...getDownloadList(undefined, 'v', flag_3d));
  759. } else {
  760. for (let key in pageDatas) {
  761. pageDatas[key].userId = user.id;
  762. dList.push(
  763. ...(await getFrameDownloadList(
  764. pageDatas[key],
  765. key,
  766. downloadType,
  767. false
  768. ))
  769. );
  770. }
  771. for (let key in page2dDatas) {
  772. page2dDatas[key].userId = user.id;
  773. dList.push(
  774. ...(await getFrameDownloadList(
  775. page2dDatas[key],
  776. key,
  777. downloadType,
  778. false
  779. ))
  780. );
  781. }
  782. for (let key in page3dDatas) {
  783. flag_3d = true;
  784. let source3dList = await getResource(
  785. page3dDatas[key].data,
  786. key,
  787. 'deploy'
  788. );
  789. dList.push(...source3dList);
  790. }
  791. //下载运行环境文件
  792. dList.push(...getFrameDownloadList(undefined, 'v', downloadType, flag_3d));
  793. }
  794. taskDialog.tasks[0].status = 'success';
  795. taskDialog.tasks[1].status = 'process';
  796. downloadList = uniqueObjArrayFast(dList, 'path');
  797. //下载列表
  798. let result = await saveDownload(downloadList);
  799. if (!result) {
  800. return;
  801. }
  802. taskDialog.tasks[1].status = 'success';
  803. taskDialog.tasks[2].status = 'process';
  804. taskDialog.visible = false;
  805. };
  806. const saveDownload = async (downloadList) => {
  807. const list = [...downloadList];
  808. //控件
  809. let jsPath = '';
  810. let jsPensPath = '';
  811. switch (downloadType) {
  812. case Frame.html:
  813. jsPath = '/view/js/2d-components.js';
  814. jsPensPath = `/view/js/1.js`;
  815. break;
  816. case Frame.vue2:
  817. jsPath = '/meta2d-vue2/public/js/2d-components.js';
  818. jsPensPath = `/meta2d-vue2/public/js/1.js`;
  819. break;
  820. case Frame.vue3:
  821. jsPath = '/meta2d-vue3/public/js/2d-components.js';
  822. jsPensPath = `/meta2d-vue3/public/js/1.js`;
  823. break;
  824. case Frame.react:
  825. jsPath = '/meta2d-react/public/js/2d-components.js';
  826. jsPensPath = `/meta2d-react/public/js/1.js`;
  827. break;
  828. }
  829. // if (isDownload) {
  830. // 安装包
  831. list.push({
  832. url: '/view/js/2d-components.js', //需要购买
  833. path: jsPath,
  834. });
  835. /*
  836. } else {
  837. const js = await get2dComponentJs([...prePayList.iotPens]);
  838. list.push({
  839. data: js,
  840. path: jsPath,
  841. });
  842. ///png图形库
  843. let pngs: any = {};
  844. //TODO token
  845. let token = '';
  846. if (token) {
  847. pngs = await getDeployPngs([...prePayList.pngs], token);
  848. } else {
  849. pngs = await getTemPngs([...prePayList.pngs]);
  850. }
  851. list.forEach((item) => {
  852. if (item.url) {
  853. let url = item.url.replace(img_cdn, '').replace(img_upCdn, '');
  854. if (pngs[url]) {
  855. item.url = pngs[url];
  856. }
  857. }
  858. });
  859. //js线性图元
  860. let arr = [];
  861. if (token) {
  862. arr = [...prePayList.jsPens];
  863. } else {
  864. const res: any = await axios.post(
  865. '/api/paid/2d/component?pageSize=1000',
  866. {
  867. type: 'JS线性图元',
  868. collection: 'v',
  869. id: meta2d.store.data.id,
  870. }
  871. );
  872. let purchased = [];
  873. if (res?.list && res.list.length) {
  874. purchased = res.list.map((item) => item.name);
  875. }
  876. [...prePayList.jsPens].forEach((item) => {
  877. if (purchased.includes(item)) {
  878. arr.push(item);
  879. }
  880. });
  881. }
  882. const res_list: any = await axios.post('/api/2d/tools', {
  883. list: arr.map((item) => {
  884. return {
  885. type: 'JS线性图元',
  886. name: item,
  887. };
  888. }),
  889. });
  890. const json =
  891. `!window.meta2dToolId&&(window.meta2dToolId="${res_list?.id}");var tmpTools=` +
  892. JSON.stringify(res_list?.list) +
  893. `;!window.meta2dTools&&(window.meta2dTools=[]);window.meta2dTools.push.apply(window.meta2dTools,tmpTools);`;
  894. list.push({
  895. data: json,
  896. path: jsPensPath,
  897. });
  898. //SVG线性图元
  899. if ([...prePayList.svgPens].length) {
  900. // let purchased = data.purchasedList?.filter(
  901. // (_item) => _item.type === 'SVG线性图元'
  902. // );
  903. let purchased = [];
  904. if (!token) {
  905. const res: any = await axios.post(
  906. '/api/paid/2d/component?pageSize=1000',
  907. {
  908. type: 'SVG线性图元',
  909. collection: 'v',
  910. id: meta2d.store.data.id,
  911. }
  912. );
  913. purchased = res?.list || [];
  914. }
  915. //TODO
  916. let count = 0; // data.goods.find((item) => item.type === 'SVG线性图元')?.count;
  917. if (purchased.length === count || token) {
  918. // if (purchased.length === 1 && !purchased[0].name) {
  919. //已经购买全部
  920. list.forEach((item) => {
  921. if (
  922. item.data &&
  923. (item.path.indexOf('/projects/2d') !== -1 ||
  924. item.path.indexOf('/projects/v') !== -1 ||
  925. item.path.indexOf('/public/json') !== -1) &&
  926. item.path.indexOf('/projects/v/png/') === -1 &&
  927. item.path.indexOf('/projects/2d/png/') === -1
  928. ) {
  929. //清空所有svgpath
  930. let meta2dData = JSON.parse(item.data);
  931. for (let key of Object.keys(meta2dData.paths)) {
  932. let path = meta2dData.paths[key];
  933. if (
  934. path.indexOf('-1.18Zm4-1') !== -1 ||
  935. path.indexOf('-1.19Zm4-1') !== -1 ||
  936. path.indexOf('2.85ZM') !== -1 ||
  937. path.indexOf('-1-2.39.3') !== -1
  938. ) {
  939. meta2dData.paths[key] = '';
  940. }
  941. }
  942. item.data = JSON.stringify(meta2dData);
  943. }
  944. });
  945. } else {
  946. let svgnames = purchased.map((i) => i.name);
  947. list.forEach((item) => {
  948. if (
  949. item.data &&
  950. (item.path.indexOf('/projects/2d') !== -1 ||
  951. item.path.indexOf('/projects/v') !== -1 ||
  952. item.path.indexOf('/public/json') !== -1) &&
  953. item.path.indexOf('/projects/v/png/') === -1 &&
  954. item.path.indexOf('/projects/2d/png/') === -1
  955. ) {
  956. //2d 图纸数据
  957. let meta2dData = JSON.parse(item.data);
  958. meta2dData.pens.forEach((pen) => {
  959. if (pen.name === 'svgPath' && pen.svgUrl) {
  960. if (svgnames.includes(pen.svgUrl.replace(img_cdn, ''))) {
  961. pen.pathId = null;
  962. }
  963. }
  964. });
  965. item.data = JSON.stringify(meta2dData);
  966. }
  967. });
  968. }
  969. }
  970. }*/
  971. //开始下载list
  972. let result = await saveZip(list);
  973. if (result === 'error') {
  974. taskDialog.tasks[1].status = 'error';
  975. taskDialog.reload = true;
  976. taskDialog.downloadList = list;
  977. return false;
  978. }
  979. MessagePlugin.closeAll();
  980. MessagePlugin.success('下载成功,请在浏览器下载列表中查看');
  981. return true;
  982. };
  983. const saveZip = async (list: any[], fileName: string = '工程下载') => {
  984. //开始下载list
  985. const [{ default: JSZip }, { saveAs }] = await Promise.all([
  986. import('jszip'),
  987. import('file-saver'),
  988. ]);
  989. const zip = new JSZip();
  990. const _zip = zip.folder(`${fileName}`);
  991. const results = await Promise.all(
  992. list.map(async (item: any) => {
  993. if (item.url) {
  994. //接口请求
  995. try {
  996. let url = item.url.startsWith('/') ? cdn + item.url : item.url;
  997. if (url.indexOf('/view/index.html') !== -1) {
  998. url = url.replace('/view/index.html', '/v/view/index.html'); //线上不包含cdn的inde.html
  999. }
  1000. if (url.includes('?')) {
  1001. url = url + `&r=${Date.now()}`;
  1002. } else {
  1003. url = url + `?r=${Date.now()}`;
  1004. }
  1005. let res: Blob = null;
  1006. let localBlob: any = await localforage.getItem(item.path);
  1007. if (localBlob) {
  1008. res = localBlob;
  1009. } else {
  1010. res = await axios.get(url, {
  1011. responseType: 'blob',
  1012. });
  1013. }
  1014. if (!res) {
  1015. throw new Error('请求失败');
  1016. }
  1017. localforage.setItem(item.path, res); //缓存
  1018. let path = item.path.split('?')[0];
  1019. if (path.startsWith('/')) {
  1020. path = path.slice(1);
  1021. }
  1022. _zip.file(path, res, { createFolders: true });
  1023. } catch (error) {
  1024. return { error: error.message,url: item.url}; // 返回错误信息
  1025. }
  1026. } else if (item.data) {
  1027. //直接写数据
  1028. let path = item.path;
  1029. if (path.startsWith('/')) {
  1030. path = path.slice(1);
  1031. }
  1032. _zip.file(path, item.data, { createFolders: true });
  1033. }
  1034. })
  1035. );
  1036. console.log("results",results);
  1037. let errorLen = results.map((item) => item && item.error);
  1038. // if (errorLen.length > 5) {
  1039. // MessagePlugin.error('下载失败,请确保网络畅通');
  1040. // return 'error';
  1041. // }
  1042. //清除本地存储
  1043. list.forEach((item) => {
  1044. localforage.removeItem(item.path);
  1045. });
  1046. const blob = await zip.generateAsync({ type: 'blob' });
  1047. saveAs(blob, `${fileName}.zip`);
  1048. };
  1049. //遍历树
  1050. const treeToList = (tree) => {
  1051. const list = [];
  1052. for (let i = 0; i < tree.length; i++) {
  1053. const item = tree[i];
  1054. list.push(item);
  1055. if (item.children) {
  1056. list.push(...treeToList(item.children));
  1057. }
  1058. }
  1059. return list;
  1060. };
  1061. //下载zip资源
  1062. export const downloadProjectSource = async () => {
  1063. // if (!isVip()) {
  1064. // return; //非vip用户不能下载
  1065. // }
  1066. await getDatas(false);
  1067. // if (isDownload) {
  1068. //安装包
  1069. await doDownloadProjectSource();
  1070. // return;
  1071. // }
  1072. // await getEnterprisePens(); //获取企业图库
  1073. // await prePay();
  1074. };
  1075. export const doDownloadProjectSource = async () => {
  1076. // prePayList.pngs.forEach
  1077. taskDialog.reload = false;
  1078. taskDialog.visible = true;
  1079. taskDialog.tasks = [
  1080. {
  1081. status: 'prepare',
  1082. title: '获取工程数据资源',
  1083. },
  1084. {
  1085. status: 'prepare',
  1086. title: '下载资源',
  1087. },
  1088. {
  1089. status: 'prepare',
  1090. title: '完成',
  1091. },
  1092. ];
  1093. taskDialog.tasks[0].status = 'process';
  1094. let dList = [];
  1095. let imgList = [];
  1096. for (let key in pageDatas) {
  1097. imgList.push(...(await getImgList(pageDatas[key])));
  1098. }
  1099. for (let key in page2dDatas) {
  1100. imgList.push(...(await getImgList(page2dDatas[key])));
  1101. }
  1102. imgList = uniqueObjArrayFast(imgList, 'path');
  1103. //获取去水印企业图库
  1104. /*if ([...prePayList.pngs].length && !isDownload) {
  1105. let pngs: any = {};
  1106. if (payDialog.token) {
  1107. pngs = await getDeployPngs(
  1108. [...prePayList.pngs],
  1109. undefined
  1110. );
  1111. } else {
  1112. pngs = await getTemPngs([...prePayList.pngs]);
  1113. }
  1114. if (!pngs) {
  1115. pngs = {};
  1116. }
  1117. imgList.forEach((item) => {
  1118. if (item.url) {
  1119. let url = item.url.replace(img_cdn, '').replace(img_upCdn, '');
  1120. if (pngs[url]) {
  1121. item.url = pngs[url];
  1122. }
  1123. }
  1124. });
  1125. }*/
  1126. dList.push(...imgList);
  1127. for (let key in pageDatas) {
  1128. dList.push({
  1129. data: JSON.stringify(pageDatas[key]),
  1130. path: `${key}.json`,
  1131. });
  1132. }
  1133. for (let key in page2dDatas) {
  1134. dList.push({
  1135. data: JSON.stringify(page2dDatas[key]),
  1136. path: `${key}.json`,
  1137. });
  1138. }
  1139. //TODO 获取zip包的内容
  1140. for (let key in page3dDatas) {
  1141. let source3dList = await getResource(
  1142. page3dDatas[key].data,
  1143. '3d-' + key,
  1144. 'deployAsZip'
  1145. );
  1146. dList.push(...source3dList);
  1147. }
  1148. dList.push({
  1149. data: JSON.stringify(data.tree),
  1150. path: 'project.json',
  1151. });
  1152. dList = uniqueObjArrayFast(dList, 'path'); //去重
  1153. taskDialog.tasks[0].status = 'success';
  1154. taskDialog.tasks[1].status = 'process';
  1155. //下载
  1156. //开始下载list
  1157. let result = await saveZip(dList);
  1158. if (result === 'error') {
  1159. taskDialog.tasks[1].status = 'error';
  1160. taskDialog.reload = true;
  1161. taskDialog.downloadList = dList;
  1162. return;
  1163. }
  1164. taskDialog.tasks[1].status = 'success';
  1165. MessagePlugin.closeAll();
  1166. taskDialog.tasks[2].status = 'success';
  1167. MessagePlugin.success('下载成功,请在浏览器下载列表中查看');
  1168. taskDialog.visible = false;
  1169. };
  1170. //TODO 任务取消 是否需要删除已经上传的内容
  1171. export const uploadProjectSource = async (file) => {
  1172. taskDialog.visible = true;
  1173. taskDialog.tasks = [
  1174. {
  1175. status: 'prepare',
  1176. title: '解析ZIP文件',
  1177. },
  1178. {
  1179. status: 'prepare',
  1180. title: '上传资源文件',
  1181. },
  1182. {
  1183. status: 'prepare',
  1184. title: '生成项目',
  1185. },
  1186. {
  1187. status: 'prepare',
  1188. title: '完成',
  1189. },
  1190. ];
  1191. // return;
  1192. //TODO 上传zip包
  1193. const { default: JSZip } = await import('jszip');
  1194. const zip = new JSZip();
  1195. await zip.loadAsync(file, { base64: true });
  1196. taskDialog.tasks[0].status = 'success';
  1197. taskDialog.tasks[1].status = 'process';
  1198. let fileName = file.name.slice(0, -4);
  1199. let treeData = '';
  1200. for (const key in zip.files) {
  1201. if (zip.files[key].dir) {
  1202. fileName = key.split('/')[0]; // 取第一个文件夹名称
  1203. continue;
  1204. }
  1205. if (key.endsWith('project.json')) {
  1206. // 工程json 文件
  1207. treeData = await zip.file(key).async('string');
  1208. break;
  1209. }
  1210. }
  1211. if (!treeData) {
  1212. MessagePlugin.error('这不是一个工程包,请重新选择');
  1213. return false;
  1214. }
  1215. const imgMap = {}; //新老图纸映射
  1216. const _2dDataMap = {}; //2d数据映射
  1217. const _3dIDMap = {}; //3d id映射
  1218. const _2dIDMap = {}; //2d id映射
  1219. //上传所有图片资源
  1220. for (const key in zip.files) {
  1221. if (taskDialog.cancel) {
  1222. return;
  1223. }
  1224. if (zip.files[key].dir) {
  1225. continue;
  1226. }
  1227. let _keyLower = key.toLowerCase();
  1228. if (
  1229. _keyLower.endsWith('.png') ||
  1230. _keyLower.endsWith('.svg') ||
  1231. _keyLower.endsWith('.gif') ||
  1232. _keyLower.endsWith('.jpg') ||
  1233. _keyLower.endsWith('.jpeg')
  1234. ) {
  1235. let _filename = key.substr(key.lastIndexOf('/') + 1);
  1236. const form = new FormData();
  1237. form.append('name', _filename);
  1238. form.append('directory', '/大屏/图片/默认');
  1239. form.append('shared', true + '');
  1240. form.append('file', await zip.file(key).async('blob'));
  1241. form.append('conflict', 'new');
  1242. const result: any = await axios.post('/api/image/upload', form);
  1243. let arr = key.split('/');
  1244. // arr.shift();
  1245. if (arr[0] === fileName) {
  1246. arr.shift();
  1247. }
  1248. if (arr[0] === fileName) {
  1249. arr.shift();
  1250. }
  1251. let _key = '/' + arr.join('/');
  1252. if (result) {
  1253. imgMap[_key] = result.url;
  1254. }
  1255. } else if (_keyLower.endsWith('.json')) {
  1256. let arr = key.split('/');
  1257. if (arr[0] === fileName) {
  1258. arr.shift();
  1259. }
  1260. if (arr[0] === fileName) {
  1261. arr.shift();
  1262. }
  1263. let data = await zip.file(key).async('string');
  1264. let id = arr[0].split('.')[0];
  1265. // if(!arr[0].endsWith('.json')){
  1266. if (!key.endsWith('project.json')) {
  1267. _2dDataMap[id] = data;
  1268. }
  1269. // }
  1270. } else {
  1271. //TODO 多个3d场景问题
  1272. if (key.indexOf('3d') !== -1 && key.indexOf('files/') === -1) {
  1273. let id_3d = await load3d(zip, key);
  1274. if (id_3d) {
  1275. let originId = key.split('3d-')[1];
  1276. _3dIDMap[originId] = id_3d;
  1277. }
  1278. }
  1279. }
  1280. }
  1281. taskDialog.tasks[1].status = 'success';
  1282. taskDialog.tasks[2].status = 'process';
  1283. if (taskDialog.cancel) {
  1284. return;
  1285. }
  1286. //将 图纸里面的地址替换成最新的地址
  1287. for (let old in imgMap) {
  1288. let newImg = imgMap[old];
  1289. for (let key in _2dDataMap) {
  1290. _2dDataMap[key] = _2dDataMap[key].replaceAll(old, newImg);
  1291. }
  1292. }
  1293. //上传所有图纸
  1294. //生成 老图纸和新图纸对应的map
  1295. let arr = Object.keys(_2dDataMap);
  1296. // for(let key in _2dDataMap){
  1297. for (let i = 0; i < arr.length; i++) {
  1298. if (taskDialog.cancel) {
  1299. return;
  1300. }
  1301. let idata = JSON.parse(_2dDataMap[arr[i]]);
  1302. const ret: any = await addCollection('v', {
  1303. data: idata,
  1304. image: idata.image || 'xxx',
  1305. name: idata.name || '新建项目',
  1306. folder: idata.folder,
  1307. system: false,
  1308. case: idata.case,
  1309. });
  1310. _2dIDMap[arr[i]] = ret.id;
  1311. }
  1312. treeData = JSON.parse(treeData);
  1313. arr = treeToList(treeData)
  1314. .filter((item) => item.pageId)
  1315. .map((item) => item.pageId);
  1316. deepUpdateID(treeData, _2dIDMap);
  1317. //上传 生成的新的工程树
  1318. const projectData = {
  1319. id: data.id,
  1320. data: treeData,
  1321. name: 'test',
  1322. image: '',
  1323. };
  1324. const ret: any = await addCollection('web', projectData);
  1325. const projectId = ret.id;
  1326. //更新图纸里面工程树id内容
  1327. // for(let key in _2dDataMap){
  1328. for (let i = 0; i < arr.length; i++) {
  1329. if (taskDialog.cancel) {
  1330. return;
  1331. }
  1332. let idata = await update2dData(_2dDataMap[arr[i]], _2dIDMap, _3dIDMap);
  1333. const ret: any = await updateCollection('v', {
  1334. data: idata,
  1335. id: _2dIDMap[arr[i]],
  1336. otherData: { projectId },
  1337. });
  1338. _2dIDMap[arr[i]] = ret.id;
  1339. }
  1340. taskDialog.tasks[2].status = 'success';
  1341. taskDialog.tasks[3].status = 'process';
  1342. taskDialog.tasks[3].status = 'success';
  1343. taskDialog.visible = false;
  1344. return ret;
  1345. };
  1346. //将工程树里面的图纸id替换成新的id
  1347. const deepUpdateID = (treeData, _2dIDMap) => {
  1348. treeData.forEach((item) => {
  1349. if (item.children) {
  1350. deepUpdateID(item.children, _2dIDMap);
  1351. } else {
  1352. if (item.type === 'page') {
  1353. item.pageId = _2dIDMap[item.pageId];
  1354. }
  1355. }
  1356. });
  1357. };
  1358. const update2dData = async (_data, _2dIDMap, _3dIDMap) => {
  1359. let domain = 'https://view.le5le.com';
  1360. // if (isDownload || location.origin.indexOf('le5le.com') === -1) {
  1361. domain = location.origin + '/view';
  1362. // }
  1363. let data = JSON.parse(_data);
  1364. if (data.pens?.length) {
  1365. // 内嵌iframe网页
  1366. const pens = data.pens.filter(
  1367. (pen) =>
  1368. pen.name === 'iframe' &&
  1369. (isV(pen.iframe) || is3D(pen.iframe) || is2D(pen.iframe))
  1370. );
  1371. for (let i = 0; i < pens.length; i++) {
  1372. let pen = pens[i];
  1373. let id = queryURLParams(pen.iframe.split('?')[1])?.id;
  1374. if (is3D(pen.iframe)) {
  1375. pen.iframe = `${domain}/3d/?id=${_3dIDMap[id]}`;
  1376. } else {
  1377. pen.iframe = `${domain}/v/?id=${_2dIDMap[id]}`;
  1378. }
  1379. }
  1380. for (let i = 0; i < data.pens.length; i++) {
  1381. let pen = data.pens[i];
  1382. if (pen.events?.length) {
  1383. for (let j = 0; j < pen.events.length; j++) {
  1384. //打开弹框
  1385. const actions = pen.events[j].actions;
  1386. for (let k = 0; k < actions.length; k++) {
  1387. let action = actions[k];
  1388. if (action.action === 14) {
  1389. //打开弹框
  1390. if (
  1391. is2D(action.params) ||
  1392. is3D(action.params) ||
  1393. isV(action.params)
  1394. ) {
  1395. let id = queryURLParams(action.params.split('?')[1])?.id;
  1396. action.params = `${domain}/v/?id=${_2dIDMap[id]}`;
  1397. }
  1398. } else if (action.action === 1) {
  1399. //更改iframe属性
  1400. if (action.value?.iframe) {
  1401. if (is2D(action.value.iframe) || isV(action.value.iframe)) {
  1402. let id = queryURLParams(
  1403. action.value.iframe.split('?')[1]
  1404. )?.id;
  1405. action.value.iframe = `${domain}/v/?id=${_2dIDMap[id]}`;
  1406. } else if (is3D(action.value.iframe)) {
  1407. let id = queryURLParams(
  1408. action.value.iframe.split('?')[1]
  1409. )?.id;
  1410. action.value.iframe = `${domain}/3d/?id=${_3dIDMap[id]}`;
  1411. }
  1412. }
  1413. } else if (action.action === 13) {
  1414. //打开视图
  1415. action.value = _2dIDMap[action.value];
  1416. }
  1417. }
  1418. }
  1419. }
  1420. if (pen.triggers?.length) {
  1421. for (let j = 0; j < pen.triggers.length; j++) {
  1422. const trigger = pen.triggers[j];
  1423. for (let k = 0; k < trigger.status.length; k++) {
  1424. let status = trigger.status[k];
  1425. for (let l = 0; l < status.actions.length; l++) {
  1426. let action = status.actions[l];
  1427. if (action.action === 14) {
  1428. //打开弹框
  1429. if (
  1430. is2D(action.params) ||
  1431. is3D(action.params) ||
  1432. isV(action.params)
  1433. ) {
  1434. let id = queryURLParams(action.params.split('?')[1])?.id;
  1435. action.params = `${domain}/v/?id=${_2dIDMap[id]}`;
  1436. }
  1437. } else if (action.action === 1) {
  1438. //更改iframe属性
  1439. if (action.value?.iframe) {
  1440. if (is2D(action.value.iframe) || isV(action.value.iframe)) {
  1441. let id = queryURLParams(
  1442. action.value.iframe.split('?')[1]
  1443. )?.id;
  1444. action.value.iframe = `${domain}/v/?id=${_2dIDMap[id]}`;
  1445. } else if (is3D(action.value.iframe)) {
  1446. let id = queryURLParams(
  1447. action.value.iframe.split('?')[1]
  1448. )?.id;
  1449. action.value.iframe = `${domain}/3d/?id=${_3dIDMap[id]}`;
  1450. }
  1451. }
  1452. } else if (action.action === 13) {
  1453. //打开视图
  1454. action.value = _2dIDMap[action.value];
  1455. }
  1456. }
  1457. }
  1458. }
  1459. }
  1460. }
  1461. }
  1462. return data;
  1463. };
  1464. //去重
  1465. function uniqueObjArrayFast(arr, key) {
  1466. const seen = {};
  1467. return arr.filter((item) => {
  1468. const val = item[key];
  1469. return seen.hasOwnProperty(val) ? false : (seen[val] = true);
  1470. });
  1471. }
  1472. const uploadProject = async (file) => {};
  1473. const getImgList = async (meta2dData) => {
  1474. let lists = [];
  1475. let img = meta2dData.bkImage;
  1476. if (img) {
  1477. if (
  1478. img.startsWith('/') ||
  1479. img.startsWith(img_cdn) ||
  1480. img.startsWith(img_upCdn)
  1481. ) {
  1482. let _img = img.replace(img_cdn, '').replace(img_upCdn, '');
  1483. if (_img.startsWith('/v/')) {
  1484. _img = _img.slice(2);
  1485. }
  1486. _img = decodeURIComponent(_img);
  1487. lists.push({
  1488. url: img,
  1489. path: _img,
  1490. });
  1491. meta2dData.bkImage = _img;
  1492. }
  1493. }
  1494. //图片图元(image strokeImage backgroundImage)
  1495. const imageKeys = ['image', 'strokeImage', 'backgroundImage'];
  1496. const images: string[] = [];
  1497. for (const pen of meta2dData.pens) {
  1498. for (const i of imageKeys) {
  1499. const image = pen[i];
  1500. if (image) {
  1501. if (
  1502. image.startsWith('/') ||
  1503. image.startsWith(img_cdn) ||
  1504. image.startsWith(img_upCdn)
  1505. ) {
  1506. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  1507. let _img = image.replace(img_cdn, '').replace(img_upCdn, '');
  1508. if (_img.startsWith('/v/')) {
  1509. _img = _img.slice(2);
  1510. }
  1511. _img = decodeURIComponent(_img);
  1512. if (!images.includes(image)) {
  1513. // let _img = image.replace(cdn, '').replace(upCdn, '');
  1514. lists.push({
  1515. url: image,
  1516. path: _img,
  1517. });
  1518. }
  1519. pen[i] = _img;
  1520. }
  1521. }
  1522. }
  1523. pen.events?.forEach((event) => {
  1524. if (event.actions?.length) {
  1525. event.actions.forEach((action) => {
  1526. if (action.action === 1) {
  1527. //更改属性
  1528. if (action.value?.image) {
  1529. let image = action.value.image;
  1530. if (
  1531. image.startsWith('/') ||
  1532. image.startsWith(img_cdn) ||
  1533. image.startsWith(img_upCdn)
  1534. ) {
  1535. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  1536. let _img = image.replace(img_cdn, '').replace(img_upCdn, '');
  1537. if (_img.startsWith('/v/')) {
  1538. _img = _img.slice(2);
  1539. }
  1540. _img = decodeURIComponent(_img);
  1541. if (!images.includes(image)) {
  1542. lists.push({
  1543. url: image,
  1544. path: _img,
  1545. });
  1546. }
  1547. action.value.image = _img;
  1548. }
  1549. }
  1550. }
  1551. });
  1552. }
  1553. });
  1554. pen.triggers?.forEach((trigger) => {
  1555. trigger?.status?.forEach((state) => {
  1556. if (state.actions?.length) {
  1557. state.actions.forEach((action) => {
  1558. if (action.action === 1) {
  1559. //更改属性
  1560. if (action.value?.image) {
  1561. let image = action.value.image;
  1562. if (
  1563. image.startsWith('/') ||
  1564. image.startsWith(img_cdn) ||
  1565. image.startsWith(img_upCdn)
  1566. ) {
  1567. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  1568. let _img = image.replace(img_cdn, '').replace(img_upCdn, '');
  1569. if (_img.startsWith('/v/')) {
  1570. _img = _img.slice(2);
  1571. }
  1572. _img = decodeURIComponent(_img);
  1573. if (!images.includes(image)) {
  1574. lists.push({
  1575. url: image,
  1576. path: _img,
  1577. });
  1578. }
  1579. action.value.image = _img;
  1580. }
  1581. }
  1582. }
  1583. });
  1584. }
  1585. });
  1586. });
  1587. }
  1588. return lists;
  1589. };