download.ts 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. import { cdn, upCdn } from '@/services/api';
  2. import { checkData } from '@/services/utils';
  3. import axios from 'axios';
  4. // import { MessagePlugin } from 'tdesign-vue-next';
  5. import { useUser } from '@/services/user';
  6. import JSZip from 'jszip';
  7. import { Pen, getGlobalColor, isShowChild } from '@meta2d/core';
  8. export const img_cdn = 'https://assets.le5lecdn.com';
  9. export const img_upCdn = 'https://drive.le5lecdn.com';
  10. const { user, signout } = useUser();
  11. const components = [
  12. 'inputDom',
  13. 'selectDom',
  14. 'menuDom',
  15. 'headMenuDom',
  16. 'sliderVerifyDom',
  17. 'dropdownDom',
  18. 'flvPlayerDom',
  19. 'countdown',
  20. 'swiperDom',
  21. 'threeDSence',
  22. 'rtspPlayerDom',
  23. 'timeline',
  24. 'swiperline',
  25. 'tab',
  26. 'radio',
  27. 'checkbox',
  28. 'calendar',
  29. 'indicator',
  30. 'progress',
  31. 'pagination',
  32. 'steps',
  33. 'notification',
  34. 'list',
  35. 'tree',
  36. 'rockerSwitch',
  37. 'roundSwitch',
  38. 'breadcrumb',
  39. 'transferSwitch',
  40. 'pie3D',
  41. 'hikVideo',
  42. 'thermometer',
  43. 'watermeter',
  44. 'indicatorLight',
  45. 'toggleSwitch',
  46. 'knifeSwitch',
  47. 'compass',
  48. 'thermometer1',
  49. 'airSwitch',
  50. 'waterTank',
  51. 'tablePlus',
  52. 'tank',
  53. 'treeFilterDom',
  54. 'datePickerDom',
  55. 'dateRangePickerDom',
  56. 'cascadeFilterDom',
  57. ];
  58. export const getDownloadList = (meta2dData: any, path: string = 'v') => {
  59. const lists = new Set();
  60. //TODO 加一个type区分是数据/还是接口
  61. //背景图片
  62. // const meta2dData = meta2d.data();
  63. if(meta2dData){
  64. let img = meta2dData.bkImage;
  65. if (img) {
  66. if (
  67. img.startsWith('/') ||
  68. img.startsWith(img_cdn) ||
  69. img.startsWith(img_upCdn)
  70. ) {
  71. let _img = img.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  72. if (_img.startsWith('/v/')) {
  73. _img = _img.slice(2);
  74. }
  75. _img = decodeURIComponent(_img);
  76. lists.add({
  77. url: img,
  78. path: `/view/projects/assets` + _img,
  79. });
  80. meta2dData.bkImage = `projects/assets` + _img;
  81. }
  82. }
  83. //图片图元(image strokeImage backgroundImage)
  84. const imageKeys = ['image', 'strokeImage', 'backgroundImage','activeBgImage','bgImage'];
  85. const images: string[] = [];
  86. for (const pen of meta2dData.pens) {
  87. for (const i of imageKeys) {
  88. const image = pen[i];
  89. if (image) {
  90. if (
  91. image.startsWith('/') ||
  92. image.startsWith(img_cdn) ||
  93. image.startsWith(img_upCdn)
  94. ) {
  95. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  96. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  97. if (_img.startsWith('/v/')) {
  98. _img = _img.slice(2);
  99. }
  100. _img = decodeURIComponent(_img);
  101. if (!images.includes(image)) {
  102. // let _img = image.replace(cdn, '').replace(upCdn, '');
  103. lists.add({
  104. url: image,
  105. path: `/view/projects/assets` + _img,
  106. });
  107. }
  108. pen[i] = `projects/assets` + _img;
  109. }
  110. }
  111. }
  112. pen.events?.forEach((event) => {
  113. if (event.actions?.length) {
  114. event.actions.forEach((action) => {
  115. if (action.action === 1) {
  116. //更改属性
  117. if (action.value?.image) {
  118. let image = action.value.image;
  119. if (
  120. image.startsWith('/') ||
  121. image.startsWith(img_cdn) ||
  122. image.startsWith(img_upCdn)
  123. ) {
  124. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  125. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  126. if (_img.startsWith('/v/')) {
  127. _img = _img.slice(2);
  128. }
  129. _img = decodeURIComponent(_img);
  130. if (!images.includes(image)) {
  131. lists.add({
  132. url: image,
  133. path: `/view/projects/assets` + _img,
  134. });
  135. }
  136. action.value.image = `projects/assets` + _img;
  137. }
  138. }
  139. }
  140. });
  141. }
  142. });
  143. pen.triggers?.forEach((trigger) => {
  144. trigger?.status?.forEach((state) => {
  145. if (state.actions?.length) {
  146. state.actions.forEach((action) => {
  147. if (action.action === 1) {
  148. //更改属性
  149. if (action.value?.image) {
  150. let image = action.value.image;
  151. if (
  152. image.startsWith('/') ||
  153. image.startsWith(img_cdn) ||
  154. image.startsWith(img_upCdn)
  155. ) {
  156. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  157. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  158. if (_img.startsWith('/v/')) {
  159. _img = _img.slice(2);
  160. }
  161. _img = decodeURIComponent(_img);
  162. if (!images.includes(image)) {
  163. lists.add({
  164. url: image,
  165. path: `/view/projects/assets` + _img,
  166. });
  167. }
  168. action.value.image = `projects/assets` + _img;
  169. }
  170. }
  171. }
  172. });
  173. }
  174. });
  175. });
  176. if(pen.name === 'echarts'){
  177. if(pen.echarts?.geoUrl){
  178. let geoUrl = pen.echarts.geoUrl.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  179. if (geoUrl.startsWith('/v/')) {
  180. geoUrl = geoUrl.slice(2);
  181. }
  182. lists.add({
  183. url: pen.echarts.geoUrl,
  184. path: `/view/projects/assets` + geoUrl
  185. });
  186. pen.echarts.geoUrl = `projects/assets` + geoUrl;
  187. }
  188. if(pen.echarts?.geoName){
  189. pen.echarts.option.series?.forEach((item:any) => {
  190. if(item.symbol&&item.symbol.startsWith('image://')){
  191. let _img = item.symbol.replace('image://','').replace(img_cdn, '').replace(img_upCdn, '');
  192. if (_img.startsWith('/v/')) {
  193. _img = _img.slice(2);
  194. }
  195. _img = decodeURIComponent(_img);
  196. lists.add({
  197. url: item.symbol.replace('image://',''),
  198. path: `/view/projects/assets` + _img,
  199. });
  200. item.symbol = `image://projects/assets` + _img;
  201. }
  202. });
  203. }
  204. }
  205. }
  206. }
  207. if(path === 'v'){ //iframe嵌入的页面无需再次下载
  208. //其他文件
  209. const files = [
  210. '/view/assets/index.js',
  211. '/view/assets/index.css',
  212. '/view/css/index.css',
  213. '/view/css/t/font_2395018_nng9x1qhat.css',
  214. '/view/css/t/font_2073009_teagntehxt.css',
  215. '/view/css/v/iconfont.css',
  216. '/view/css/v/iconfont.ttf',
  217. '/view/css/v/iconfont.woff',
  218. '/view/css/v/iconfont.woff2',
  219. '/view/css/v/iconfont.svg',
  220. //字体
  221. '/view/css/fonts/DS-DIGI-1.ttf',
  222. '/view/css/fonts/DS-DIGIB-2.ttf',
  223. '/view/css/fonts/DS-DIGII-3.ttf',
  224. '/view/css/fonts/DS-DIGIT-4.ttf',
  225. '/view/css/fonts/fonts.css',
  226. '/view/css/fonts/TG-TYPE-Bold.otf',
  227. '/view/css/fonts/TG-TYPE-Regular.otf',
  228. '/view/css/fonts/庞门正道标题体.ttf',
  229. '/view/css/fonts/斗鱼追光体.ttf',
  230. '/view/js/marked.min.js',
  231. '/view/js/echarts.min.js',
  232. '/view/js/lcjs.iife.js',
  233. '/view/js/highcharts.js',
  234. '/view/js/highcharts-more.js',
  235. '/view/js/r.js',
  236. '/view/index.html',
  237. '/view/config.js', //3D配置文件
  238. '/view/favicon.ico',
  239. '/view/view.conf',
  240. '/view/离线部署包使用说明.pdf',
  241. '/view/assets/cloudy.env',
  242. '/view/assets/default.env',
  243. '/view/assets/dusk.env',
  244. '/view/assets/night.env',
  245. '/view/assets/sunny.env',
  246. '/view/assets/cloudy.jpg',
  247. '/view/assets/dusk.jpg',
  248. '/view/assets/night.jpg',
  249. '/view/assets/sunny.jpg',
  250. '/view/assets/luopan.png',
  251. '/view/assets/Rain.png',
  252. '/view/assets/zhizhen.png',
  253. '/view/assets/默认环境光.png',
  254. '/view/assets/draco_decoder_gltf.js',
  255. '/view/assets/draco_wasm_wrapper_gltf.js',
  256. '/view/assets/draco_decoder_gltf.wasm',
  257. //echarts 主题
  258. '/view/theme/dark.json',
  259. '/view/theme/light.json',
  260. ];
  261. files.forEach((file) => {
  262. // lists.add({
  263. // url: (cdn ? cdn : '') + file,
  264. // path: file,
  265. // });
  266. let _file = file;
  267. // if(file === '/view/assets/index.js' && !flag_3d){
  268. // _file = '/v/view/index.js';
  269. // }
  270. if(_file.startsWith('/view/css/v')){
  271. lists.add({
  272. url: (cdn ? cdn + '/v' : import.meta.env.BASE_URL.slice(0, -1)) + _file,
  273. path: file,
  274. });
  275. }else{
  276. lists.add({
  277. url: (cdn ? cdn : '') + _file,
  278. path: file,
  279. });
  280. }
  281. });
  282. }
  283. if(meta2dData){
  284. //数据
  285. // const data: any = meta2d.data();
  286. if (meta2dData._id) delete meta2dData._id;
  287. if (meta2dData.id) delete meta2dData.id;
  288. if ((meta2dData as any).image) delete (meta2dData as any).image;
  289. checkData(meta2dData);
  290. lists.add({
  291. data: JSON.stringify(meta2dData)
  292. .replaceAll(img_cdn, '')
  293. .replaceAll(img_upCdn, ''),
  294. path: `/view/projects/${path}`,
  295. });
  296. }
  297. return lists;
  298. };
  299. export const getPayList = (meta2dData: any) => {
  300. const pngs = new Set<string>();
  301. const jsPens = new Set<string>();
  302. const iotPens = new Set<string>();
  303. const svgPens = new Set<string>();
  304. for (const pen of meta2dData.pens) {
  305. if (pen.image) {
  306. if (
  307. pen.image.startsWith(`${img_cdn}/png/`) ||
  308. pen.image.startsWith('/png/')
  309. ) {
  310. pngs.add(pen.image.replace(img_cdn, ''));
  311. }
  312. } else if (pen.subClassName && pen.fullname) {
  313. if(!['箭头','拓扑图未分类','工具'].includes(pen.subClassName)){
  314. jsPens.add(pen.name);
  315. }
  316. } else if (components.includes(pen.name)) {
  317. iotPens.add(pen.name);
  318. } else if (pen.svgUrl) {
  319. if (
  320. pen.svgUrl.startsWith(`${img_cdn}/svg/`) ||
  321. pen.svgUrl.startsWith('/svg/')
  322. ) {
  323. svgPens.add(pen.svgUrl.replace(img_cdn, ''));
  324. }
  325. }
  326. }
  327. if (![...svgPens].length) {
  328. //判断是否为老数据
  329. if (meta2dData.paths) {
  330. let keys = [];
  331. for (let key of Object.keys(meta2dData.paths)) {
  332. let path = meta2dData.paths[key];
  333. if (
  334. path.indexOf('-1.18Zm4-1') !== -1 ||
  335. path.indexOf('-1.19Zm4-1') !== -1 ||
  336. path.indexOf('2.85ZM') !== -1 ||
  337. path.indexOf('-1-2.39.3') !== -1
  338. ) {
  339. keys.push(key);
  340. }
  341. }
  342. let flag = meta2dData.pens.some(
  343. (pen) => pen.name === 'svgPath' && keys.includes(pen.pathId)
  344. );
  345. if (flag) {
  346. svgPens.add('*'); //需要购买所有
  347. }
  348. }
  349. }
  350. return {
  351. pngs: [...pngs],
  352. jsPens: [...jsPens],
  353. iotPens: [...iotPens],
  354. svgPens: [...svgPens],
  355. };
  356. };
  357. //获取已购买
  358. export const getComponentPurchased = async (list: any) => {
  359. let _list = [];
  360. list.pngs.forEach((item) => {
  361. _list.push({
  362. type: '图片图元',
  363. name: item,
  364. });
  365. });
  366. list.jsPens.forEach((item) => {
  367. _list.push({
  368. type: 'JS线性图元',
  369. name: item,
  370. });
  371. });
  372. list.iotPens.forEach((item) => {
  373. _list.push({
  374. type: '控件',
  375. name: item,
  376. });
  377. });
  378. if ([...list.svgPens].includes('*')) {
  379. _list.push({
  380. type: 'SVG线性图元',
  381. });
  382. } else {
  383. list.svgPens.forEach((item) => {
  384. _list.push({
  385. type: 'SVG线性图元',
  386. name: item,
  387. });
  388. });
  389. }
  390. if(!_list.length){
  391. return [];
  392. }
  393. const res: any = await axios.post('/api/paid/2d/component?pageSize=1000', {
  394. list: _list,
  395. // collection:'v',
  396. // id:meta2d.store.data.id
  397. });
  398. if (res?.error) {
  399. return [];
  400. }
  401. // let purchasedPngs = res.list.filter((item) => list.pngs.has(item));
  402. // let purchasedJs = res.list.filter((item) => list.jsPens.has(item));
  403. // let purchasedIot = res.list.filter((item) => list.iotPens.has(item));
  404. // let purchasedSvg = res.list.filter((item) => list.svgPens.has(item));
  405. // let price =
  406. // ([...list.pngs].length - purchasedPngs.length) * 50 +
  407. // ([...list.jsPens].length - purchasedJs.length) * 10 +
  408. // ([...list.iotPens].length - purchasedIot.length) * 70+
  409. // ([...list.svgPens].length - purchasedSvg.length) * 10;
  410. return res?.list||[];
  411. };
  412. export const get2dComponentJs = async (names: string[] = components) => {
  413. let list = [];
  414. names.forEach((item) => {
  415. list.push({
  416. type: '控件',
  417. name: item,
  418. });
  419. });
  420. const res: any = await axios.post(
  421. '/api/2d-component.js',
  422. {
  423. // list,
  424. // collection:'v',
  425. // id:meta2d.store.data.id
  426. },
  427. {
  428. responseType: 'blob',
  429. }
  430. );
  431. return res;
  432. };
  433. export const getTemPngs = async (names: string[]) => {
  434. const res: any = await axios.post('/api/file/presign', {
  435. names,
  436. // collection:'v',
  437. // id:meta2d.store.data.id
  438. });
  439. return res;
  440. };
  441. export const getGoods = async () => {
  442. const res: any = await axios.get('/api/goods/2d/component/types');
  443. // console.log("res",res);
  444. return res;
  445. };
  446. export const getDeployGoods = async () => {
  447. const ret:any = await axios.post('/api/goods/list',{
  448. type:'私有部署'
  449. });
  450. return ret.list;
  451. }
  452. export enum Frame {
  453. vue2,
  454. vue3,
  455. react,
  456. html,
  457. zip
  458. }
  459. // export const _preFrameDownload = async (type: Frame) => {
  460. // frameFlag = type;
  461. // // MessagePlugin.info('正在下载打包中,可能需要几分钟,请耐心等待...');
  462. // zip3D(
  463. // type === Frame.vue3 ? 'toVue3' : type === Frame.vue2 ? 'toVue2' : 'toReact'
  464. // );
  465. // zip2D(
  466. // type === Frame.vue3
  467. // ? 'downloadVue3'
  468. // : type === Frame.vue2
  469. // ? 'downloadVue2'
  470. // : 'downloadReact'
  471. // );
  472. // const data: any = meta2d.data();
  473. // if (data._id) delete data._id;
  474. // if (data.id) delete data.id;
  475. // if (data.image) delete data.image;
  476. // data.userId = user.id;
  477. // checkData(data);
  478. // const [{ default: JSZip }, { saveAs }] = await Promise.all([
  479. // import('jszip'),
  480. // import('file-saver'),
  481. // ]);
  482. // const zip = new JSZip();
  483. // let _fileName =
  484. // (data.name && data.name.replace(/\//g, '_').replace(/:/g, '_')) ||
  485. // 'le5le.meta2d';
  486. // //处理付费svg
  487. // if (Object.keys(data.paths).length >= 3) {
  488. // //简单判断有无svg图元
  489. // const res: any = await axios.post('/api/paid/2d/component?pageSize=1000', {
  490. // type: 'SVG线性图元',
  491. // });
  492. // if (res.list.length === 1 && !res.list[0].name) {
  493. // //已经购买全部
  494. // for (let key of Object.keys(data.paths)) {
  495. // let path = data.paths[key];
  496. // if (
  497. // path.indexOf('-1.18Zm4-1') !== -1 ||
  498. // path.indexOf('-1.19Zm4-1') !== -1 ||
  499. // path.indexOf('2.85ZM') !== -1 ||
  500. // path.indexOf('-1-2.39.3') !== -1
  501. // ) {
  502. // data.paths[key] = '';
  503. // }
  504. // }
  505. // } else {
  506. // //购买部分
  507. // let purchasedList = res.list.map((i) => i.name);
  508. // data.pens.forEach((pen) => {
  509. // if (pen.name === 'svgPath' && pen.svgUrl) {
  510. // if (purchasedList.includes(pen.svgUrl.replace(img_cdn, ''))) {
  511. // pen.pathId = null;
  512. // }
  513. // }
  514. // });
  515. // }
  516. // }
  517. // const _zip: any = zip.folder(`${_fileName}`);
  518. // _zip.file(
  519. // `${
  520. // type === Frame.vue3
  521. // ? 'meta2d-vue3'
  522. // : type === Frame.vue2
  523. // ? 'meta2d-vue2'
  524. // : 'meta2d-react'
  525. // }/public/json/data.json`,
  526. // JSON.stringify(data).replaceAll(img_cdn, '').replaceAll(img_upCdn, '')
  527. // );
  528. // await Promise.all([
  529. // zipJs(_zip),
  530. // zipBkImg(_zip),
  531. // zipImages(_zip, meta2d.store.data.pens),
  532. // type === Frame.vue3
  533. // ? zipVue3Files(_zip)
  534. // : type === Frame.vue2
  535. // ? zipVue2Files(_zip)
  536. // : zipReactFiles(_zip),
  537. // zipIotPens(_zip),
  538. // ]);
  539. // const blob = await zip.generateAsync({ type: 'blob' });
  540. // saveAs(blob, `${_fileName}.zip`);
  541. // frameFlag = -1;
  542. // };
  543. // async function zipIotPens(zip: JSZip) {
  544. // //处理控件
  545. // const js = await get2dComponentJs();
  546. // zip.file(
  547. // `${
  548. // frameFlag === Frame.vue3
  549. // ? 'meta2d-vue3'
  550. // : frameFlag === Frame.vue2
  551. // ? 'meta2d-vue2'
  552. // : 'meta2d-react'
  553. // }/public/js/2d-components.js`,
  554. // js,
  555. // { createFolders: true }
  556. // );
  557. // const res: Blob = await axios.get( cdn+'/view/js/r.js', {
  558. // responseType: 'blob',
  559. // });
  560. // zip.file(
  561. // `${
  562. // frameFlag === Frame.vue3
  563. // ? 'meta2d-vue3'
  564. // : frameFlag === Frame.vue2
  565. // ? 'meta2d-vue2'
  566. // : 'meta2d-react'
  567. // }/public/js/r.js`,
  568. // res,
  569. // { createFolders: true }
  570. // );
  571. // }
  572. // async function zipJs(zip: JSZip) {
  573. // const files = ['/view/js/marked.min.js', '/view/js/lcjs.iife.js'];
  574. // await Promise.all(
  575. // files.map(async (filePath) => {
  576. // const res: Blob = await axios.get(cdn+filePath, {
  577. // responseType: 'blob',
  578. // });
  579. // zip.file(
  580. // `${
  581. // frameFlag === Frame.vue3
  582. // ? 'meta2d-vue3'
  583. // : frameFlag === Frame.vue2
  584. // ? 'meta2d-vue2'
  585. // : 'meta2d-react'
  586. // }/public` + filePath.replace('/view', ''),
  587. // res,
  588. // { createFolders: true }
  589. // );
  590. // })
  591. // );
  592. // }
  593. export async function zipBkImg(zip: JSZip) {
  594. let img = meta2d.store.data.bkImage;
  595. if (img) {
  596. if (img.startsWith('/') || img.startsWith(img_cdn) || img.startsWith(img_upCdn)) {
  597. const pngs = await getTemPngs([img.replace(img_cdn, '').replace(img_upCdn, '')]);
  598. await zipImage(zip, img, pngs[img.replace(img_cdn, '').replace(img_upCdn, '')]);
  599. }
  600. }
  601. }
  602. async function zipImage(zip: JSZip, image: string, temImage?: string) {
  603. const res: Blob = await axios.get(temImage || image, {
  604. responseType: 'blob',
  605. // params: {
  606. // isZip: true,
  607. // },
  608. });
  609. zip.file(
  610. (cdn ? image.replace(cdn, '').replace(upCdn, '') : image),
  611. res,
  612. {
  613. createFolders: true,
  614. }
  615. );
  616. }
  617. // const zip3D = (name: string) => {
  618. // const pen_3d = meta2d.store.data.pens.filter(
  619. // (pen) =>
  620. // pen.name === 'iframe' &&
  621. // (pen.tags.includes('meta3d') || pen.iframe.indexOf('/3d') !== -1)
  622. // );
  623. // if (pen_3d && pen_3d.length) {
  624. // //存在3d场景
  625. // pen_3d.forEach((pen) => {
  626. // //发送消息
  627. // // let params = queryURLParams(pen.iframe.split('?')[1]);
  628. // (
  629. // pen.calculative.singleton.div.children[0] as HTMLIFrameElement
  630. // ).contentWindow.postMessage(
  631. // JSON.stringify({
  632. // type: 1,
  633. // name,
  634. // // id: params.id,
  635. // }),
  636. // '*'
  637. // );
  638. // });
  639. // }
  640. // };
  641. // const zip2D = (name: string) => {
  642. // const pen_2d = meta2d.store.data.pens.filter(
  643. // (pen) =>
  644. // pen.name === 'iframe' &&
  645. // pen.iframe.indexOf('/2d') !== -1 || pen.iframe.indexOf('data=2d') !== -1 ||
  646. // pen.iframe.indexOf('/view/v') !== -1 ||pen.iframe.indexOf('data=v') !== -1||
  647. // pen.iframe.indexOf('/preview') !== -1)
  648. // );
  649. // if (pen_2d && pen_2d.length) {
  650. // //存在3d场景
  651. // pen_2d.forEach((pen) => {
  652. // //发送消息
  653. // // let params = queryURLParams(pen.iframe.split('?')[1]);
  654. // (
  655. // pen.calculative.singleton.div.children[0] as HTMLIFrameElement
  656. // ).contentWindow.postMessage(
  657. // JSON.stringify({
  658. // name,
  659. // type: 1,
  660. // }),
  661. // '*'
  662. // );
  663. // });
  664. // }
  665. // };
  666. /**
  667. * 图片放到 zip 里
  668. * @param pens 可以是非具有 calculative 的 pen
  669. */
  670. export async function zipImages(zip: JSZip, pens: Pen[]) {
  671. if (!pens) {
  672. return;
  673. }
  674. // 不止 image 上有图片, strokeImage ,backgroundImage 也有图片
  675. const imageKeys = [
  676. {
  677. string: 'image',
  678. },
  679. { string: 'strokeImage' },
  680. { string: 'backgroundImage' },
  681. { string: 'activeBgImage' },
  682. { string: 'bgImage' },
  683. ] as const;
  684. const images: string[] = [];
  685. for (const pen of pens) {
  686. for (const i of imageKeys) {
  687. const image = pen[i.string];
  688. if (image) {
  689. // HTMLImageElement 无法精确控制图片格式
  690. if (
  691. image.startsWith('/') ||
  692. image.startsWith(cdn) ||
  693. image.startsWith(upCdn)
  694. ) {
  695. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  696. if (!images.includes(image)) {
  697. images.push(image);
  698. }
  699. }
  700. }
  701. }
  702. // 无需递归遍历子节点,现在所有的节点都在外层
  703. }
  704. //付费pngs
  705. const pngs = await getTemPngs(
  706. images.map((i) => i.replace(img_cdn, '').replace(img_upCdn, ''))
  707. );
  708. await Promise.all(
  709. images.map((image) =>
  710. zipImage(zip, image, pngs[image.replace(img_cdn, '').replace(img_upCdn, '')])
  711. )
  712. );
  713. }
  714. //新
  715. // async function zipVue3Files(zip: JSZip) {
  716. // const files = [
  717. // '/view/meta2d-vue3/src/components/Meta2d.vue',
  718. // '/view/meta2d-vue3/src/App.vue',
  719. // '/view/meta2d-vue3/src/main.js',
  720. // '/view/meta2d-vue3/src/style.css',
  721. // '/view/meta2d-vue3/index.html',
  722. // '/view/meta2d-vue3/package.json',
  723. // '/view/meta2d-vue3/README.md',
  724. // '/view/meta2d-vue3/vite.config.js',
  725. // ] as const;
  726. // // 文件同时加载
  727. // await Promise.all(files.map((filePath) => zipFile(zip, filePath)));
  728. // }
  729. // async function zipVue2Files(zip: JSZip) {
  730. // const files = [
  731. // '/view/meta2d-vue2/src/components/Meta2d.vue',
  732. // '/view/meta2d-vue2/src/App.vue',
  733. // '/view/meta2d-vue2/src/main.js',
  734. // // '/view/meta2d-vue2/src/style.css',
  735. // '/view/meta2d-vue2/public/index.html',
  736. // '/view/meta2d-vue2/package.json',
  737. // '/view/meta2d-vue2/README.md',
  738. // // '/view/meta2d-vue3/vite.config.js',
  739. // ] as const;
  740. // // 文件同时加载
  741. // await Promise.all(files.map((filePath) => zipFile(zip, filePath)));
  742. // }
  743. // async function zipReactFiles(zip: JSZip) {
  744. // const files = [
  745. // '/view/meta2d-react/src/index.css',
  746. // '/view/meta2d-react/src/index.js',
  747. // '/view/meta2d-react/src/Meta2d.css',
  748. // '/view/meta2d-react/src/Meta2d.jsx',
  749. // '/view/meta2d-react/package.json',
  750. // '/view/meta2d-react/README.md',
  751. // '/view/meta2d-react/public/index.html',
  752. // ] as const;
  753. // // 文件同时加载
  754. // await Promise.all(files.map((filePath) => zipFile(zip, filePath)));
  755. // }
  756. // async function zipFile(zip: JSZip, filePath: string) {
  757. // const res: Blob = await axios.get(
  758. // (cdn ? cdn + '/v' : import.meta.env.BASE_URL.slice(0, -1)) + filePath,
  759. // {
  760. // responseType: 'blob',
  761. // }
  762. // );
  763. // zip.file(filePath.replace('/view', ''), res, { createFolders: true });
  764. // }
  765. export const getFrameDownloadList =(meta2dData: any, path: string = 'v',type:Frame, flag_3d=false) => {
  766. const lists = new Set();
  767. if(meta2dData){
  768. let img = meta2dData.bkImage;
  769. if (img) {
  770. if (
  771. img.startsWith('/') ||
  772. img.startsWith(img_cdn) ||
  773. img.startsWith(img_upCdn)
  774. ) {
  775. let _img = img.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  776. if (_img.startsWith('/v/')) {
  777. _img = _img.slice(2);
  778. }
  779. _img = decodeURIComponent(_img);
  780. lists.add({
  781. url: img,
  782. path: (`${
  783. type === Frame.vue3
  784. ? 'meta2d-vue3'
  785. : type === Frame.vue2
  786. ? 'meta2d-vue2'
  787. : 'meta2d-react'
  788. }/public`) + _img,
  789. });
  790. meta2dData.bkImage = _img;
  791. }
  792. }
  793. //图片图元(image strokeImage backgroundImage)
  794. const imageKeys = ['image', 'strokeImage', 'backgroundImage','activeBgImage','bgImage'];
  795. const images: string[] = [];
  796. for (const pen of meta2dData.pens) {
  797. for (const i of imageKeys) {
  798. const image = pen[i];
  799. if (image) {
  800. if (
  801. image.startsWith('/') ||
  802. image.startsWith(img_cdn) ||
  803. image.startsWith(img_upCdn)
  804. ) {
  805. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  806. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  807. if (_img.startsWith('/v/')) {
  808. _img = _img.slice(2);
  809. }
  810. _img = decodeURIComponent(_img);
  811. let path = (`${
  812. type === Frame.vue3
  813. ? 'meta2d-vue3'
  814. : type === Frame.vue2
  815. ? 'meta2d-vue2'
  816. : 'meta2d-react'
  817. }/public`) + _img
  818. if (!images.includes(image)) {
  819. // let _img = image.replace(cdn, '').replace(upCdn, '');
  820. lists.add({
  821. url: image,
  822. path,
  823. });
  824. }
  825. pen[i] = _img;
  826. }
  827. }
  828. }
  829. pen.events?.forEach((event) => {
  830. if (event.actions?.length) {
  831. event.actions.forEach((action) => {
  832. if (action.action === 1) {
  833. //更改属性
  834. if (action.value?.image) {
  835. let image = action.value.image;
  836. if (
  837. image.startsWith('/') ||
  838. image.startsWith(img_cdn) ||
  839. image.startsWith(img_upCdn)
  840. ) {
  841. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  842. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  843. if (_img.startsWith('/v/')) {
  844. _img = _img.slice(2);
  845. }
  846. _img = decodeURIComponent(_img);
  847. let path = (`${
  848. type === Frame.vue3
  849. ? 'meta2d-vue3'
  850. : type === Frame.vue2
  851. ? 'meta2d-vue2'
  852. : 'meta2d-react'
  853. }/public`) + _img
  854. if (!images.includes(image)) {
  855. // let _img = image.replace(cdn, '').replace(upCdn, '');
  856. lists.add({
  857. url: image,
  858. path,
  859. });
  860. }
  861. action.value.image = _img;
  862. }
  863. }
  864. }
  865. });
  866. }
  867. });
  868. pen.triggers?.forEach((trigger) => {
  869. trigger?.status?.forEach((state) => {
  870. if (state.actions?.length) {
  871. state.actions.forEach((action) => {
  872. if (action.action === 1) {
  873. //更改属性
  874. if (action.value?.image) {
  875. let image = action.value.image;
  876. if (
  877. image.startsWith('/') ||
  878. image.startsWith(img_cdn) ||
  879. image.startsWith(img_upCdn)
  880. ) {
  881. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  882. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  883. if (_img.startsWith('/v/')) {
  884. _img = _img.slice(2);
  885. }
  886. _img = decodeURIComponent(_img);
  887. let path = (`${
  888. type === Frame.vue3
  889. ? 'meta2d-vue3'
  890. : type === Frame.vue2
  891. ? 'meta2d-vue2'
  892. : 'meta2d-react'
  893. }/public`) + _img
  894. if (!images.includes(image)) {
  895. // let _img = image.replace(cdn, '').replace(upCdn, '');
  896. lists.add({
  897. url: image,
  898. path,
  899. });
  900. }
  901. action.value.image = _img;
  902. }
  903. }
  904. }
  905. });
  906. }
  907. });
  908. });
  909. }
  910. }
  911. let folderName =type===Frame.vue3?'meta2d-vue3':type===Frame.vue2?'meta2d-vue2': 'meta2d-react';
  912. if(path === 'v'){ //iframe嵌入的页面无需再次下载
  913. //其他文件
  914. let files = [];
  915. let files_3d = [
  916. '/view/index.html',
  917. '/view/favicon.ico',
  918. '/view/view.conf',
  919. '/view/离线部署包使用说明.pdf',
  920. '/view/css/index.css',
  921. //字体
  922. '/view/css/fonts/DS-DIGI-1.ttf',
  923. '/view/css/fonts/DS-DIGIB-2.ttf',
  924. '/view/css/fonts/DS-DIGII-3.ttf',
  925. '/view/css/fonts/DS-DIGIT-4.ttf',
  926. '/view/css/fonts/fonts.css',
  927. '/view/css/fonts/TG-TYPE-Bold.otf',
  928. '/view/css/fonts/TG-TYPE-Regular.otf',
  929. '/view/css/fonts/庞门正道标题体.ttf',
  930. '/view/css/fonts/斗鱼追光体.ttf',
  931. '/view/assets/index.js',
  932. '/view/config.js', //3D配置文件
  933. '/view/assets/index.css',
  934. '/view/assets/cloudy.env',
  935. '/view/assets/default.env',
  936. '/view/assets/dusk.env',
  937. '/view/assets/night.env',
  938. '/view/assets/sunny.env',
  939. '/view/assets/cloudy.jpg',
  940. '/view/assets/dusk.jpg',
  941. '/view/assets/night.jpg',
  942. '/view/assets/sunny.jpg',
  943. '/view/assets/luopan.png',
  944. '/view/assets/Rain.png',
  945. '/view/assets/zhizhen.png',
  946. '/view/assets/默认环境光.png',
  947. '/view/assets/draco_decoder_gltf.js',
  948. '/view/assets/draco_wasm_wrapper_gltf.js',
  949. '/view/assets/draco_decoder_gltf.wasm',
  950. ];
  951. switch (type) {
  952. case Frame.vue3:
  953. files =[
  954. '/view/meta2d-vue3/src/router/index.ts',
  955. '/view/meta2d-vue3/src/views/2d/Meta2d.vue',
  956. '/view/meta2d-vue3/src/App.vue',
  957. '/view/meta2d-vue3/src/main.ts',
  958. '/view/meta2d-vue3/src/style.css',
  959. '/view/meta2d-vue3/index.html',
  960. '/view/meta2d-vue3/package.json',
  961. '/view/meta2d-vue3/README.md',
  962. '/view/meta2d-vue3/tsconfig.json',
  963. '/view/meta2d-vue3/tsconfig.node.json',
  964. '/view/meta2d-vue3/vite.config.ts',
  965. ];
  966. // if(flag_3d){
  967. // //存在3d场景
  968. // files_3d.push(...[
  969. // '/meta2d-vue3/src/plugins/meta3d/index.ts',
  970. // '/meta2d-vue3/src/plugins/meta3d/meta3d.css',
  971. // '/meta2d-vue3/src/plugins/meta3d/meta3d.js',
  972. // // '/view/meta2d-vue3/src/views/3d/Meta3d.vue',
  973. // // '/meta2d-vue3/public/meta3d/js/draco_decoder_gltf.js',
  974. // // '/meta2d-vue3/public/meta3d/js/draco_decoder_gltf.wasm',
  975. // // '/meta2d-vue3/public/meta3d/js/draco_wasm_wrapper_gltf.js',
  976. // ]);
  977. // files.push( '/view/meta2d-vue3/src/views/3d/Meta3d.vue',)
  978. // }
  979. break;
  980. case Frame.vue2:
  981. files =[
  982. '/view/meta2d-vue2/src/router/index.js',
  983. '/view/meta2d-vue2/src/views/2d/Meta2d.vue',
  984. '/view/meta2d-vue2/src/App.vue',
  985. '/view/meta2d-vue2/src/main.js',
  986. '/view/meta2d-vue2/index.html',
  987. '/view/meta2d-vue2/package.json',
  988. '/view/meta2d-vue2/README.md',
  989. '/view/meta2d-vue2/vite.config.js'
  990. ];
  991. // if(flag_3d){
  992. // files_3d.push(...[
  993. // '/meta2d-vue2/src/plugins/meta3d/index.js',
  994. // '/meta2d-vue2/src/plugins/meta3d/meta3d.css',
  995. // '/meta2d-vue2/src/plugins/meta3d/meta3d.js',
  996. // // '/meta2d-vue2/src/views/3d/Meta3d.vue',
  997. // // '/meta2d-vue2/public/meta3d/js/draco_decoder_gltf.js',
  998. // // '/meta2d-vue2/public/meta3d/js/draco_decoder_gltf.wasm',
  999. // // '/meta2d-vue2/public/meta3d/js/draco_wasm_wrapper_gltf.js',
  1000. // ]);
  1001. // files.push( '/view/meta2d-vue2/src/views/3d/Meta3d.vue',)
  1002. // }
  1003. // break;
  1004. case Frame.react:
  1005. files =[
  1006. '/view/meta2d-react/src/router/index.tsx',
  1007. '/view/meta2d-react/src/views/2d/Meta2d.tsx',
  1008. '/view/meta2d-react/src/App.tsx',
  1009. '/view/meta2d-react/src/index.css',
  1010. '/view/meta2d-react/src/main.tsx',
  1011. '/view/meta2d-react/index.html',
  1012. '/view/meta2d-react/package.json',
  1013. '/view/meta2d-react/README.md',
  1014. '/view/meta2d-react/tsconfig.json',
  1015. '/view/meta2d-react/tsconfig.node.json',
  1016. '/view/meta2d-react/vite.config.ts',
  1017. ];
  1018. // if(flag_3d){
  1019. // files_3d.push(...[
  1020. // '/meta2d-react/src/plugins/meta3d/index.ts',
  1021. // '/meta2d-react/src/plugins/meta3d/meta3d.css',
  1022. // '/meta2d-react/src/plugins/meta3d/meta3d.js',
  1023. // // '/meta2d-react/src/views/3d/Meta3d.tsx',
  1024. // // '/meta2d-react/public/meta3d/js/draco_decoder_gltf.js',
  1025. // // '/meta2d-react/public/meta3d/js/draco_decoder_gltf.wasm',
  1026. // // '/meta2d-react/public/meta3d/js/draco_wasm_wrapper_gltf.js',
  1027. // ]);
  1028. // files.push('/view/meta2d-react/src/views/3d/Meta3d.tsx',)
  1029. // }
  1030. // break;
  1031. default:
  1032. break;
  1033. }
  1034. files.forEach((file) => {
  1035. lists.add({
  1036. url: (cdn ? cdn + '/v' : import.meta.env.BASE_URL.slice(0, -1)) + file,
  1037. path: file.replace('/view', ''),
  1038. });
  1039. });
  1040. if(flag_3d){
  1041. files_3d.forEach((file) => {
  1042. lists.add({
  1043. // url: (cdn ? cdn + '/v' : import.meta.env.BASE_URL.slice(0, -1)) + '/view/meta3d/'+file.split('/meta3d/')[1],
  1044. // path: file,
  1045. url: (cdn ? cdn : '') + file,
  1046. path: `/${folderName}/public${file}`,
  1047. });
  1048. })
  1049. }
  1050. let jsFiles = [
  1051. '/view/js/marked.min.js',
  1052. // '/view/js/echarts.min.js',
  1053. '/view/js/lcjs.iife.js',
  1054. // '/view/js/highcharts.js',
  1055. // '/view/js/highcharts-more.js',
  1056. '/view/js/r.js',
  1057. '/view/icon/font_2395018_nng9x1qhat.css',
  1058. '/view/icon/font_2073009_teagntehxt.css',
  1059. //字体
  1060. '/view/css/fonts/DS-DIGI-1.ttf',
  1061. '/view/css/fonts/DS-DIGIB-2.ttf',
  1062. '/view/css/fonts/DS-DIGII-3.ttf',
  1063. '/view/css/fonts/DS-DIGIT-4.ttf',
  1064. '/view/css/fonts/fonts.css',
  1065. '/view/css/fonts/TG-TYPE-Bold.otf',
  1066. '/view/css/fonts/TG-TYPE-Regular.otf',
  1067. '/view/css/fonts/庞门正道标题体.ttf',
  1068. '/view/css/fonts/斗鱼追光体.ttf',
  1069. // '/view/assets/cloudy.env',
  1070. // '/view/assets/default.env',
  1071. // '/view/assets/dusk.env',
  1072. // '/view/assets/night.env',
  1073. // '/view/assets/sunny.env',
  1074. // '/view/assets/cloudy.jpg',
  1075. // '/view/assets/dusk.jpg',
  1076. // '/view/assets/night.jpg',
  1077. // '/view/assets/sunny.jpg',
  1078. // '/view/assets/luopan.png',
  1079. // '/view/assets/Rain.png',
  1080. // '/view/assets/zhizhen.png',
  1081. // '/view/assets/默认环境光.png',
  1082. // '/view/assets/draco_decoder_gltf.js',
  1083. // '/view/assets/draco_wasm_wrapper_gltf.js',
  1084. // '/view/assets/draco_decoder_gltf.wasm',
  1085. '/view/css/v/iconfont.css',
  1086. '/view/css/v/iconfont.ttf',
  1087. '/view/css/v/iconfont.woff',
  1088. '/view/css/v/iconfont.woff2',
  1089. '/view/css/v/iconfont.svg',
  1090. //echarts 主题
  1091. '/theme/dark.json',
  1092. '/theme/light.json',
  1093. ]
  1094. jsFiles.forEach((file) => {
  1095. lists.add({
  1096. url: (cdn ? cdn + '/v' : import.meta.env.BASE_URL.slice(0, -1))+ file,
  1097. path:`/${folderName}/public${file.replace('/view', '')}`,
  1098. });
  1099. });
  1100. }
  1101. if(meta2dData){
  1102. //图纸数据
  1103. if (meta2dData._id) delete meta2dData._id;
  1104. if (meta2dData.id) delete meta2dData.id;
  1105. if ((meta2dData as any).image) delete (meta2dData as any).image;
  1106. lists.add({
  1107. data: JSON.stringify(meta2dData)
  1108. .replaceAll(img_cdn, '')
  1109. .replaceAll(img_upCdn, ''),
  1110. path: `/${folderName}/public/json/${path}.json`,
  1111. });
  1112. }
  1113. return lists;
  1114. };
  1115. export const getDownloadZipList = (meta2dData: any, zips:any) => {
  1116. const lists = new Set();
  1117. // const pngs = new Set<string>();
  1118. if (meta2dData._id) delete meta2dData._id;
  1119. if (meta2dData.id) delete meta2dData.id;
  1120. let _fileName =
  1121. (meta2dData.name && meta2dData.name.replace(/\//g, '_').replace(/:/g, '_')) ||
  1122. 'le5le.meta2d';
  1123. getDataPngs(meta2dData).forEach(item => lists.add(item));
  1124. lists.add({
  1125. data:JSON.stringify(meta2dData).replaceAll(img_cdn, '').replaceAll(img_upCdn, ''),
  1126. path: `${_fileName}.json`
  1127. });
  1128. for (let key in zips) {
  1129. // zips[key].pngs.forEach(item => pngs.add(item));
  1130. getDataPngs(zips[key].data).forEach(item => lists.add(item));
  1131. lists.add({
  1132. data:JSON.stringify(zips[key].data)?.replaceAll(img_cdn, '').replaceAll(img_upCdn, ''),
  1133. path: `${key}/${zips[key].data.name?.replace(/\//g, '_')?.replace(/:/g, '_')}.json`
  1134. });
  1135. }
  1136. return lists;
  1137. }
  1138. export const getDataPngs = (meta2dData: any)=>{
  1139. const lists = new Set();
  1140. let img = meta2dData.bkImage;
  1141. if (img) {
  1142. if (
  1143. img.startsWith('/') ||
  1144. img.startsWith(img_cdn) ||
  1145. img.startsWith(img_upCdn)
  1146. ) {
  1147. let _img = img.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  1148. _img = decodeURIComponent(_img);
  1149. // if (_img.startsWith('/v/')) {
  1150. // _img = _img.slice(2);
  1151. // }
  1152. meta2dData.bkImage = _img;
  1153. lists.add({
  1154. url: img,
  1155. path: _img.split('?')[0],
  1156. });
  1157. }
  1158. }
  1159. //图片图元(image strokeImage backgroundImage)
  1160. const imageKeys = ['image', 'strokeImage', 'backgroundImage','activeBgImage','bgImage'];
  1161. const images: string[] = [];
  1162. for (const pen of meta2dData.pens) {
  1163. for (const i of imageKeys) {
  1164. const image = pen[i];
  1165. if (image) {
  1166. if (
  1167. image.startsWith('/') ||
  1168. image.startsWith(img_cdn) ||
  1169. image.startsWith(img_upCdn)
  1170. ) {
  1171. // 只考虑相对路径下的 image ,绝对路径图片无需下载
  1172. let _img = image.replace(img_cdn, '').replace(img_upCdn, '').split('?')[0];
  1173. pen[i] = _img;
  1174. if (!images.includes(image)) {
  1175. // let _img = image.replace(cdn, '').replace(upCdn, '');
  1176. lists.add({
  1177. url: image,
  1178. path:_img.split('?')[0],
  1179. });
  1180. }
  1181. }
  1182. }
  1183. }
  1184. }
  1185. return lists;
  1186. }