index.php 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. <script src="/resources/js/html2canvas.min.js"></script>
  2. <!-- 装修所需的数据 -->
  3. <script type="text/javascript" src="/resources/js/diy-util.js"></script>
  4. <script type="text/javascript" src="/resources/js/hotzone.js"></script>
  5. <script>
  6. function getNavData() {
  7. const result = [{
  8. // 顶部导航
  9. "id": getRandomId(),
  10. "data": {
  11. backSrc: "",
  12. contentType: "1",
  13. isShowName: "1",
  14. logoSrc: "",
  15. mainPage: { // 主页面设置
  16. defColor: "#fff",
  17. name: "O2o商家",
  18. type: "纯色",
  19. imgUrl: ""
  20. },
  21. name: "推荐商家",
  22. positionChoose: "1",
  23. hideSearch: false,
  24. },
  25. "computedStyle": {
  26. "mode": 1,
  27. "style": 1,
  28. "titleSwitch": true,
  29. "titleMode": 1,
  30. "imageUrl": [],
  31. "position": 1,
  32. "searchSwitch": true,
  33. "searchBgColor": "",
  34. "statusBarColor": "#000000",
  35. "defaultForm": {
  36. "defColor": "transparent"
  37. },
  38. "titleDistance": {
  39. "fontSize": 16,
  40. "height": 30,
  41. "width": 57,
  42. "marginLeft": 20
  43. },
  44. "statusBar": "1",
  45. "searchMarPad": {
  46. "marginLeft": 20,
  47. "paddingLeft": 14
  48. }
  49. },
  50. "funcListItem": {
  51. "type": "nav",
  52. "title": "顶部导航",
  53. "is_top": 1
  54. },
  55. "isShow": true,
  56. "is_show_permission": false,
  57. "is_drag": false,
  58. "disabled": true,
  59. "is_delete": false,
  60. "is_up": false,
  61. "is_down": false,
  62. "is_copy": false
  63. }, {
  64. // 轮播图
  65. "id": getRandomId(),
  66. "data": {
  67. buttonData: {
  68. typeIndex: 0,
  69. typeItem: null
  70. },
  71. buttonPointData: {
  72. open: true,
  73. pointIndex: 1,
  74. pointItem: {
  75. label: "resources/img/decorate/point-two.png",
  76. value: "two"
  77. },
  78. position: 1
  79. },
  80. carouselImgArr: [{
  81. hotZone: [],
  82. imgUrl: "resources/img/decorate/group-goods/banner.png",
  83. url: "",
  84. urlName: "",
  85. urlType: "",
  86. visible: false
  87. }],
  88. spaceInfo: [{
  89. disabled: false,
  90. hidden: true,
  91. maxValue: 20,
  92. name: "图片间距",
  93. unit: "px",
  94. value: 5
  95. },
  96. {
  97. disabled: false,
  98. hidden: false,
  99. maxValue: 50,
  100. name: "上边距",
  101. unit: "px",
  102. value: 0,
  103. },
  104. {
  105. disabled: false,
  106. hidden: false,
  107. maxValue: 50,
  108. name: "下边距",
  109. unit: "px",
  110. value: 0
  111. },
  112. {
  113. disabled: false,
  114. hidden: false,
  115. maxValue: 50,
  116. name: "左右边距",
  117. unit: "px",
  118. value: 12
  119. }
  120. ]
  121. },
  122. "computedStyle": {
  123. "searchBox": "",
  124. "spaceStyle": {
  125. marginBottom: "0px",
  126. marginLeft: "12px",
  127. marginRight: "12px",
  128. marginTop: "0px",
  129. height: '160px',
  130. },
  131. "searchIpts": {
  132. 'border-bottom-left-radius': "10px",
  133. 'border-bottom-right-radius': "10px",
  134. 'border-top-left-radius': "10px",
  135. 'border-top-right-radius': "10px"
  136. }
  137. },
  138. "permission": [],
  139. "funcListItem": {
  140. is_top: 0,
  141. title: "轮播广告",
  142. type: "carousel-img"
  143. },
  144. "isShow": true,
  145. "is_show_permission": false,
  146. "is_drag": false,
  147. "disabled": true,
  148. "is_delete": false,
  149. "is_up": false,
  150. "is_down": false,
  151. "is_copy": false
  152. }, {
  153. // 按钮组
  154. "id": getRandomId(),
  155. "data": {
  156. "buttonData": {
  157. "line_num": 1,
  158. "pattern": "fixed",
  159. "patternItem": null,
  160. "shape": "square",
  161. "single_line": 3,
  162. "style": 1,
  163. "type": 1,
  164. },
  165. "colorInfos": [{
  166. color: "",
  167. name: "底部背景",
  168. showAlpha: false,
  169. value: "transparent"
  170. },
  171. {
  172. color: "",
  173. name: "组件背景",
  174. showAlpha: false,
  175. value: "transparent"
  176. },
  177. {
  178. color: "#333333",
  179. name: "文字颜色",
  180. showAlpha: false,
  181. value: "#333333",
  182. }
  183. ],
  184. "iconList": [
  185. {
  186. img: 'resources/img/decorate/default_btn1.png',
  187. icon: 'el-icon-setting',
  188. is_show_tag: true,
  189. tags: '热门',
  190. tagsBgColor: '#f83287',
  191. tagsTextColor: '#ffffff',
  192. btnText: '按钮文字',
  193. link_params: null,
  194. },
  195. ],
  196. "sizeInfos": [{
  197. disabled: false,
  198. hidden: false,
  199. maxValue: 50,
  200. name: "上边距",
  201. unit: "px",
  202. value: 8
  203. },
  204. {
  205. disabled: false,
  206. hidden: false,
  207. maxValue: 50,
  208. name: "下边距",
  209. unit: "px",
  210. value: 8
  211. },
  212. {
  213. disabled: false,
  214. hidden: false,
  215. maxValue: 50,
  216. name: "左右边距",
  217. unit: "px",
  218. value: 0
  219. }
  220. ],
  221. defaultTabs: [{name: 'marketing',children:['store_cate']}],
  222. },
  223. "computedStyle": {
  224. "iptBg": "",
  225. "searchBox": "",
  226. "searchIpts": {
  227. "marginBottom": "8px",
  228. "marginLeft": "0px",
  229. "marginRight": "0px",
  230. "marginTop": "8px",
  231. },
  232. "textStyle": "#333333"
  233. },
  234. "permission": [],
  235. "funcListItem": {
  236. is_top: 0,
  237. title: "按钮组",
  238. type: "button-group"
  239. },
  240. "isShow": true,
  241. "is_show_permission": false,
  242. "is_drag": false,
  243. "disabled": true,
  244. "is_delete": false,
  245. "is_up": false,
  246. "is_down": false,
  247. "is_copy": false
  248. }, {
  249. // 商品列表
  250. "id": getRandomId(),
  251. "data": {
  252. titleRadio: 1,
  253. listType: 1,
  254. listShow: true,
  255. dataType: 0,
  256. btnData: {
  257. style: 0,
  258. name: '推荐商家'
  259. },
  260. colorInfos: [
  261. {
  262. name: "底部颜色", //名字
  263. color: "#FAFAFA", //颜色
  264. showAlpha: false, //是否开启透明度
  265. value: "#FAFAFA", //展示的值
  266. },
  267. {
  268. name: "组件颜色", //名字
  269. color: "#FFFFFF", //颜色
  270. showAlpha: false, //是否开启透明度
  271. value: "#FFFFFF", //展示的值
  272. }
  273. ],
  274. sizeInfos: [
  275. {
  276. disabled: false,
  277. hidden: false,
  278. maxValue: 20,
  279. name: "商品间距",
  280. unit: "px",
  281. value: 0,
  282. },
  283. {
  284. disabled: false,
  285. hidden: false,
  286. maxValue: 50,
  287. name: "上边距",
  288. unit: "px",
  289. value: 0,
  290. },
  291. {
  292. disabled: false,
  293. hidden: false,
  294. maxValue: 50,
  295. name: "下边距",
  296. unit: "px",
  297. value: 0,
  298. },
  299. {
  300. disabled: false,
  301. hidden: false,
  302. maxValue: 50,
  303. name: "左右边距",
  304. unit: "px",
  305. value: 0,
  306. }
  307. ],
  308. },
  309. "computedStyle": {
  310. aroundMargin: "0px",
  311. boxBg: "#FAFAFA",
  312. goodsBg: "#FFFFFF",
  313. marginBottom: "0px",
  314. marginTop: "0px",
  315. spacing: "0px"
  316. },
  317. "permission": [],
  318. "funcListItem": {
  319. is_top: 0,
  320. title: "Store门店",
  321. type: "store"
  322. },
  323. "isShow": true,
  324. "is_show_permission": false,
  325. "is_drag": false,
  326. "disabled": true,
  327. "is_delete": false,
  328. "is_up": false,
  329. "is_down": false,
  330. "is_copy": false
  331. },
  332. {
  333. // 商品列表
  334. "id": getRandomId(),
  335. "data": {
  336. titleRadio: 1,
  337. listType: 1,
  338. listShow: true,
  339. dataType: 0,
  340. btnData: {
  341. style: 0,
  342. name: '推荐商家'
  343. },
  344. colorInfos: [
  345. {
  346. name: "底部颜色", //名字
  347. color: "#FAFAFA", //颜色
  348. showAlpha: false, //是否开启透明度
  349. value: "#FAFAFA", //展示的值
  350. },
  351. {
  352. name: "组件颜色", //名字
  353. color: "#FFFFFF", //颜色
  354. showAlpha: false, //是否开启透明度
  355. value: "#FFFFFF", //展示的值
  356. }
  357. ],
  358. sizeInfos: [
  359. {
  360. disabled: false,
  361. hidden: false,
  362. maxValue: 20,
  363. name: "商品间距",
  364. unit: "px",
  365. value: 0,
  366. },
  367. {
  368. disabled: false,
  369. hidden: false,
  370. maxValue: 50,
  371. name: "上边距",
  372. unit: "px",
  373. value: 0,
  374. },
  375. {
  376. disabled: false,
  377. hidden: false,
  378. maxValue: 50,
  379. name: "下边距",
  380. unit: "px",
  381. value: 0,
  382. },
  383. {
  384. disabled: false,
  385. hidden: false,
  386. maxValue: 50,
  387. name: "左右边距",
  388. unit: "px",
  389. value: 0,
  390. }
  391. ],
  392. },
  393. "computedStyle": {
  394. aroundMargin: "0px",
  395. boxBg: "#FAFAFA",
  396. goodsBg: "#FFFFFF",
  397. marginBottom: "0px",
  398. marginTop: "0px",
  399. spacing: "0px"
  400. },
  401. "permission": [],
  402. "funcListItem": {
  403. is_top: 0,
  404. title: "Store门店",
  405. type: "store-prioritizing"
  406. },
  407. "isShow": true,
  408. "is_show_permission": false,
  409. "is_drag": false,
  410. "disabled": true,
  411. "is_delete": false,
  412. "is_up": false,
  413. "is_down": false,
  414. "is_copy": false
  415. }
  416. ]
  417. return result
  418. }
  419. </script>
  420. <?php
  421. use common\helpers\ComponentHelper;
  422. use common\models\diy\DiyComponents;
  423. use common\helpers\AddonHelper;
  424. $diyPath = Yii::$app->viewPath . '/components/common/diy/common';
  425. $stylePath = Yii::$app->viewPath . '/components/common/diy/style-components';
  426. $components = DiyComponents::getDir($diyPath, $diyPath);
  427. $styleComponents = DiyComponents::getDir($stylePath, $stylePath);
  428. // dd($diyPath, $stylePath, $components, $styleComponents);
  429. ComponentHelper::loadComponentView('diy/diy-preview');
  430. ComponentHelper::loadComponentView('diy/diy-style-preview');
  431. foreach ($components as $item) {
  432. ComponentHelper::loadComponentView("diy/common/{$item}");
  433. }
  434. foreach ($styleComponents as $item) {
  435. ComponentHelper::loadComponentView("diy/style-components/{$item}");
  436. }
  437. // 推荐商家
  438. ComponentHelper::loadComponentView('style', AddonHelper::getAddonRootPath('Store') . 'backend/views/components/diy/store');
  439. ComponentHelper::loadComponentView('preview', AddonHelper::getAddonRootPath('Store') . 'backend/views/components/diy/store');
  440. // 为您优选
  441. ComponentHelper::loadComponentView('style', AddonHelper::getAddonRootPath('Store') . 'backend/views/components/diy/store-prioritizing');
  442. ComponentHelper::loadComponentView('preview', AddonHelper::getAddonRootPath('Store') . 'backend/views/components/diy/store-prioritizing');
  443. $currentRoute = Yii::$app->controller->route;
  444. ?>
  445. <div id="app">
  446. <el-card shadow="never" style="border:0;min-width: 1000px;" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  447. <div slot="header">
  448. <span>门店装修</span>
  449. <el-button type="primary" size="small" style="padding: 9px 15px !important; float: right; position: relative; bottom: 8px;" @click="save">保存</el-button>
  450. </div>
  451. </el-card>
  452. <div class="diy-contain flex" v-loading="loading">
  453. <!-- 装修预览 -->
  454. <diy-preview :active-index="activeIndex" :list="previewList" @select-item="selectItme" @change-move="changeMove"></diy-preview>
  455. <!-- 装修配置 -->
  456. <transition name="fade">
  457. <diy-style-preview :active-item="activeItem" :active-index="activeIndex" :permission="permission" @update="changeDiyItem" v-if="showUpdate"></diy-style-preview>
  458. </transition>
  459. </div>
  460. <!-- 预览弹窗 -->
  461. <el-dialog title="预览弹窗" :modal-append-to-body="false" :visible.sync="dialogFormVisible">
  462. <div class="flex flex-x-center" style="height: 600px;overflow:auto">
  463. <img id="diy-test-preview" :src="previewSrc"></img>
  464. </div>
  465. <div slot="footer" class="dialog-footer">
  466. <el-button @click="dialogFormVisible = false">取 消</el-button>
  467. <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
  468. </div>
  469. </el-dialog>
  470. </div>
  471. <script>
  472. Vue.prototype.$capitals = []; // 用户信息对象
  473. Vue.prototype.$eventBus = new Vue();
  474. var PageShareData = {
  475. pageIndex: false // 点击页面设置标识 => nav/style
  476. }; // 全局共享数据 - 没有响应式
  477. new Vue({
  478. el: '#app',
  479. data() {
  480. return {
  481. capital: [],
  482. dialogFormVisible: false,
  483. /**
  484. * @descriptions 浮动()、普通()、置顶(isTop)、弹窗(alert)四种显示组件
  485. * @param {string} type // diy组件类型
  486. * @param {string} title // 二级标题
  487. * @param {string} img // diy组件图片
  488. * @param {number} count // 可添加diy组件数量
  489. * @param {boolean} is_top // diy组件是否置顶组件 - 待添加 - 分添加等级 1 2 3 数字靠前权限越高
  490. * @param {object} permission // 组件的不可操作权限 {"is_delete": false,"is_drag": false,"disabled": true, // 禁用操作}
  491. */
  492. pageComponentsList: [],
  493. /**
  494. * @param {boolean} is_show_permission // 显示权限
  495. * @param {boolean} is_delete // 是否可删除
  496. * @param {boolean} is_up // 是否可上移
  497. * @param {boolean} is_down // 是否可下移
  498. * @param {boolean} is_drag // 是否可拖拽
  499. * @param {boolean} is_copy // 是否可复制
  500. * @param {boolean} disabled // 全部禁用操作
  501. */
  502. previewList: [], // 预览数组对象
  503. activeIndex: -1, // 预览激活索引
  504. activeItem: null, // 预览激活对象
  505. type: "add", // add新增 - edit编辑
  506. test: ["a", "b", "c"],
  507. showUpdate: true,
  508. responentData: null, // 详情响应的总数据
  509. permission: [], // 权限数组
  510. isClickPage: false, // 是否点击分页设置
  511. loading: false, // 数据加载
  512. saveLoading: false, // 保存数据
  513. fields: {
  514. upload_type: 'images'
  515. },
  516. previewSrc: "",
  517. }
  518. },
  519. provide() {
  520. return {
  521. capitals: this.capital
  522. }
  523. },
  524. watch: {
  525. activeIndex() {
  526. this.showUpdate = false
  527. setTimeout(() => {
  528. this.showUpdate = true
  529. }, 0)
  530. },
  531. },
  532. created() {
  533. // console.log(this.dynamicImgSrc('/abc/ss'));
  534. this.init()
  535. this.detail()
  536. },
  537. methods: {
  538. savePreview() {
  539. this.activeIndex = -1
  540. this.activeItem = null
  541. this.$nextTick(() => {
  542. const contain = document.getElementById("diy-preview-contain");
  543. this.deepNode(contain);
  544. setTimeout(() => {
  545. this.dialogFormVisible = true
  546. html2canvas(contain, {
  547. useCORS: true
  548. }).then(canvas => {
  549. const src = canvas.toDataURL("image/png")
  550. this.upload(this.dataURLtoFile(src)).then(res => {
  551. if (res.code == 0) {
  552. this.previewSrc = res.data.url
  553. this.save(false)
  554. } else {
  555. this.$message({
  556. message: res.msg,
  557. type: 'warning'
  558. });
  559. }
  560. })
  561. })
  562. }, 0)
  563. })
  564. },
  565. dataURLtoFile(dataurl) { // 生成Blob
  566. var arr = dataurl.split(',');
  567. var mime = arr[0].match(/:(.*?);/)[1];
  568. var bstr = atob(arr[1]);
  569. var n = bstr.length;
  570. var u8arr = new Uint8Array(n);
  571. while (n--) {
  572. u8arr[n] = bstr.charCodeAt(n);
  573. }
  574. return new Blob([u8arr], {
  575. type: mime
  576. });
  577. },
  578. upload(file) {
  579. let formData = new FormData();
  580. const params = {
  581. upload_type: 'images'
  582. };
  583. params['r'] = 'common/file/upload';
  584. for (let i in this.fields) {
  585. formData.append(i, this.fields[i]);
  586. }
  587. formData.append('file', file, "image.png");
  588. return new Promise(successCallback => {
  589. this.$request({
  590. headers: {
  591. 'Content-Type': 'multipart/form-data'
  592. },
  593. params: params,
  594. method: 'post',
  595. data: formData,
  596. }).then(e => {
  597. successCallback(e.data)
  598. }).catch(e => {
  599. file._complete = true;
  600. });
  601. })
  602. },
  603. deepNode(contain) {
  604. if (contain.tagName === "IMG") {
  605. contain.src = contain.src + '?t=' + Date.now()
  606. contain.setAttribute('crossorigin', 'anonymous')
  607. }
  608. if (contain.children && contain.children.length) {
  609. [].forEach.call(contain.children, (item => {
  610. this.deepNode(item)
  611. }))
  612. }
  613. },
  614. pageSet() {
  615. PageShareData.pageIndex = true
  616. this.$eventBus.$emit("onPageClick")
  617. var index = 0;
  618. this.activeIndex = index
  619. this.activeItem = this.previewList[index]
  620. // this.changeDiyItem()
  621. },
  622. // 获取装修数据
  623. detail() {
  624. this.loading = true
  625. let previewList = [];
  626. previewList.push(...getNavData())
  627. request({
  628. params: {
  629. r: 'store/diy/index'
  630. },
  631. method: 'get',
  632. }).then(res => {
  633. if (res.data.code === 0) {
  634. const { content } = res.data.data
  635. let storePreviewList = []
  636. if (content) {
  637. storePreviewList = JSON.parse(content)
  638. }
  639. console.log("storePreviewList", storePreviewList)
  640. if (storePreviewList.length > 0) {
  641. const hasStorePrioritizing = storePreviewList.some(v => v.funcListItem.type.includes('store-prioritizing'))
  642. if (!hasStorePrioritizing) {
  643. storePreviewList.push(...previewList[4])
  644. }
  645. previewList = storePreviewList
  646. }
  647. } else {
  648. this.$message({
  649. message: res.data.msg,
  650. type: 'error'
  651. });
  652. }
  653. }).finally(res => {
  654. this.loading = false
  655. this.previewList = previewList
  656. })
  657. },
  658. save: debounce(function(isLoading = true) {
  659. // 对接保存数据接口
  660. if (this.saveFlag) {
  661. console.log("重复提交");
  662. return
  663. }
  664. const title = this.previewList[0].data.name
  665. // if (!title) {
  666. // this.$message({
  667. // message: '请输入标题',
  668. // type: 'warning'
  669. // });
  670. // return
  671. // }
  672. isLoading && (this.saveLoading = true)
  673. this.saveFlag = true // 防止重复提交限制
  674. request({
  675. params: {
  676. r: 'store/diy/index'
  677. },
  678. method: 'post',
  679. data: {
  680. content: JSON.stringify(this.previewList),
  681. }
  682. }).then(res => {
  683. if (res.data.code != 0) {
  684. this.$message({
  685. message: res.data.msg,
  686. type: 'error'
  687. });
  688. } else {
  689. this.$message({
  690. message: res.data.msg,
  691. type: 'success'
  692. });
  693. }
  694. }).finally(res => {
  695. this.saveFlag = false
  696. this.saveLoading = false
  697. })
  698. },400),
  699. init() {
  700. this.$eventBus.$on("diy-preview-copy", (item = {}) => {
  701. this.copy(item)
  702. })
  703. this.$eventBus.$on("diy-preview-operateFn", (item = {}) => {
  704. this.operateFn(item)
  705. })
  706. this.$eventBus.$on("diy-back-set", () => {
  707. this.updateView(null, -1)
  708. })
  709. },
  710. validateCount(e) {
  711. // 校验组件能添加几个
  712. var msg = "";
  713. var list = this.previewList.filter(item => {
  714. return item.funcListItem.type === e.type
  715. });
  716. if (e && e.count && list.length >= e.count) {
  717. msg = `该组件只能添加${e.count}个哦`
  718. }
  719. if (msg) {
  720. this.$message({
  721. message: msg,
  722. type: 'warning'
  723. });
  724. }
  725. return msg
  726. },
  727. getIsTopArrLength() {
  728. return this.previewList.filter(item => {
  729. const e1 = item.funcListItem || {}
  730. return e1.is_top
  731. }).length
  732. },
  733. changeDiyItem(item, index, params = {}) {
  734. // console.log("changeDiyItem", item, index, params);
  735. var {
  736. type
  737. } = params
  738. var list = deepClone(this.previewList) // 克隆一下
  739. if (type !== "isShow") {
  740. // 显示问题 -- 样式组件不让修改
  741. item.isShow = list[this.activeIndex].isShow;
  742. }
  743. // 直接全部覆盖
  744. list[this.activeIndex] = deepClone(item)
  745. this.activeItem = deepClone(item)
  746. this.previewList = list
  747. },
  748. selectItme(item, index) {
  749. // console.info("selectItme", item, index);
  750. if (this.activeIndex === index) {
  751. this.activeIndex = -1
  752. this.activeItem = null
  753. } else {
  754. this.activeIndex = index
  755. this.activeItem = item
  756. }
  757. this.$forceUpdate()
  758. },
  759. pushItem(list = [], target = {}) {
  760. var result = deepClone(list)
  761. result.push(target)
  762. return result
  763. },
  764. /**
  765. * 两种形式,一种push,追加index
  766. */
  767. addIndexItem(list = [], target = {}, index) { // 往指定的index添加item
  768. var result = deepClone(list)
  769. if (this.activeIndex < 0) {
  770. result.push(target)
  771. } else {
  772. var handleArr = [deepClone(result[index]), target]
  773. result.splice(index, 1, ...handleArr)
  774. }
  775. return result
  776. },
  777. // 操作相关
  778. copy() {
  779. if (!this.activeItem || this.activeItem.disabled || this.activeItem.is_copy === false) {
  780. return
  781. }
  782. var item = deepClone(this.activeItem)
  783. item.id = getRandomId()
  784. this.previewList = this.addIndexItem(this.previewList, item, this.activeIndex)
  785. },
  786. /**
  787. * @params {string} obj.type up - down - show
  788. */
  789. operateFn(obj) {
  790. const methods = {
  791. show: 'showItem',
  792. up: 'upItem',
  793. down: 'downItem',
  794. delete: 'deleteItem'
  795. }
  796. this[methods[obj.type]](obj.index)
  797. },
  798. showItem(index) {
  799. var item = deepClone(this.activeItem);
  800. item.isShow = !item.isShow
  801. this.changeDiyItem(item, index, {
  802. type: "isShow"
  803. })
  804. },
  805. updateView(item, index) {
  806. this.activeItem = item
  807. this.activeIndex = index
  808. },
  809. deleteItem(index) {
  810. if (this.activeItem.disabled || this.activeItem.is_delete === false) {
  811. return false
  812. }
  813. this.previewList.splice(index, 1);
  814. // 删除后失去焦点
  815. this.activeIndex = -1;
  816. this.activeItem = null;
  817. },
  818. upItem(index) {
  819. const topArr = this.previewList.filter(item => {
  820. const e1 = item.funcListItem || {}
  821. return e1.is_top
  822. }) // 操作上限
  823. const topIndex = Math.max(0, topArr.length)
  824. if (index <= 0 || this.activeItem.disabled || this.activeItem.is_up === false) {
  825. return false
  826. } else if (index <= topIndex) {
  827. alert("不可以再操作了噢");
  828. return false
  829. }
  830. var previewList = deepClone(this.previewList);
  831. this.previewList = this.swapItems(previewList, index, index - 1);
  832. this.updateView(this.previewList[index - 1], index - 1);
  833. },
  834. downItem(index) {
  835. if (this.activeItem.disabled || this.activeItem.is_down === false) {
  836. return false
  837. } else if (index === this.previewList.length - 1) {
  838. alert("不可以再操作了噢");
  839. return false
  840. }
  841. var previewList = deepClone(this.previewList);
  842. this.previewList = this.swapItems(previewList, index, index + 1);
  843. this.updateView(this.previewList[index + 1], index + 1);
  844. },
  845. swapItems(arr, index1, index2) {
  846. var item = deepClone(arr[index1]);
  847. arr[index1] = arr[index2]
  848. arr[index2] = item
  849. return arr
  850. },
  851. changeMove(e) {
  852. const {
  853. newIndex,
  854. list
  855. } = e
  856. // console.log('changeMove', newIndex, list);
  857. // 移动拖拽改变索引
  858. this.previewList = deepClone(list);
  859. this.updateView(this.previewList[newIndex], newIndex);
  860. },
  861. // 更新主页面
  862. updateMainPage(item) {
  863. this.mainPage = deepClone(item);
  864. },
  865. // 处理兼容老数据
  866. addIsTop(list, type) {
  867. const obj = {
  868. ['nav']: 1,
  869. ['member-info']: 2
  870. }
  871. const top = obj[type]
  872. list.forEach(item => {
  873. if (item.funcListItem.type === type && !item.funcListItem.is_top) {
  874. item.funcListItem.is_top = top
  875. }
  876. });
  877. return list
  878. }
  879. }
  880. })
  881. // 拦截页面卸载
  882. /* window.onbeforeunload = function(e) {
  883. var e = window.event || e;
  884. e.returnValue = ("确定离开当前页面吗?");
  885. } */
  886. </script>
  887. <style>
  888. #app {
  889. display: flex;
  890. flex-direction: column;
  891. min-width: 1250px;
  892. }
  893. .diy-store-header{
  894. display: flex;
  895. justify-content: space-between;
  896. align-items: center;
  897. background: #fff;
  898. padding: 18px 20px;
  899. border-bottom: 1px solid #EBEEF5;
  900. box-sizing: border-box;
  901. }
  902. #diy-test-preview {
  903. margin: auto;
  904. }
  905. .diy-header-backs {
  906. cursor: pointer;
  907. }
  908. .fixed {
  909. position: fixed;
  910. left: 0;
  911. top: 0;
  912. width: 100%;
  913. height: 100%;
  914. z-index: 999;
  915. }
  916. .diy-header {
  917. height: 60px;
  918. background: #313131;
  919. opacity: 1;
  920. border-radius: 0px;
  921. justify-content: space-between;
  922. font-size: 13px;
  923. font-family: PingFang SC;
  924. font-weight: bold;
  925. color: #FFFFFF;
  926. padding: 0 30px;
  927. }
  928. .diy-contain {
  929. flex: 1;
  930. overflow: auto;
  931. background: #F4F6F8;
  932. justify-content: space-between;
  933. }
  934. .diy-func-list {
  935. box-sizing: border-box;
  936. width: 354px;
  937. background: #FFFFFF;
  938. border-radius: 0px;
  939. }
  940. .diy-preview {
  941. flex: 1;
  942. background: #F4F6F8;
  943. justify-content: space-around;
  944. }
  945. .fill-box {
  946. position: relative;
  947. width: 467px;
  948. height: 100%;
  949. }
  950. .flex {
  951. display: flex;
  952. }
  953. .flex-x-center {
  954. justify-content: center;
  955. }
  956. .flex-y-center {
  957. align-items: center;
  958. }
  959. /* */
  960. .fade-enter-active,
  961. .fade-leave-active {
  962. transition: opacity 1s;
  963. }
  964. .fade-enter,
  965. .fade-leave-to {
  966. opacity: 0;
  967. }
  968. .diy-text-font {
  969. font-size: 13px;
  970. font-weight: 700;
  971. color: #999999;
  972. }
  973. .fill-border-top {
  974. border-top: 10px solid #F4F6F8;
  975. }
  976. .fill-border-bottom {
  977. border-bottom: 10px solid #F4F6F8;
  978. }
  979. /* 导航栏 */
  980. .custom-page {
  981. width: 181px;
  982. height: 60px;
  983. line-height: 60px;
  984. background: var(--diy-theme);
  985. font-weight: 700;
  986. border-radius: 0px;
  987. text-align: center;
  988. }
  989. .save {
  990. font-size: 24px;
  991. vertical-align: middle;
  992. }
  993. .save+span {
  994. vertical-align: middle;
  995. }
  996. .sava_btn .el-button--primary {
  997. background: var(--diy-theme);
  998. border-color: var(--diy-theme);
  999. padding: 8px 14px;
  1000. }
  1001. .diy_nav_right>div {
  1002. padding: 8px 14px;
  1003. }
  1004. .diy_nav_right .sava_btn {
  1005. padding: 0;
  1006. }
  1007. .page_set>i {
  1008. font-size: 24px;
  1009. vertical-align: middle;
  1010. }
  1011. .page_set>span {
  1012. vertical-align: middle;
  1013. }
  1014. .xiaoshou {
  1015. cursor: pointer;
  1016. }
  1017. :root {
  1018. /* 主题色 */
  1019. --diy-theme: #F10009;
  1020. /* 主要字体颜色 */
  1021. --diy-color: #F10009;
  1022. }
  1023. /* 修改ele默认样式 */
  1024. /* slider组件 */
  1025. .el-slider__bar {
  1026. background-color: var(--diy-theme);
  1027. }
  1028. .el-slider__button {
  1029. border-color: var(--diy-theme);
  1030. }
  1031. /* input组件 */
  1032. .el-input .el-input__inner:focus {
  1033. border: 1px solid var(--diy-theme);
  1034. }
  1035. /* textarea */
  1036. .el-textarea .el-textarea__inner:focus {
  1037. border: 1px solid var(--diy-theme);
  1038. }
  1039. /* radio单选组件 */
  1040. .el-radio__input.is-checked+.el-radio__label {
  1041. color: var(--diy-color);
  1042. }
  1043. .el-radio__input.is-checked .el-radio__inner {
  1044. border-color: var(--diy-theme);
  1045. background: var(--diy-theme);
  1046. }
  1047. .el-radio-button__orig-radio:checked+.el-radio-button__inner {
  1048. border-color: var(--diy-theme);
  1049. box-shadow: -1px 0 0 0 var(--diy-theme);
  1050. }
  1051. /* 多选 */
  1052. .el-checkbox__input.is-checked+.el-checkbox__label {
  1053. color: var(--diy-color);
  1054. }
  1055. .el-checkbox__input.is-checked .el-checkbox__inner,
  1056. .el-checkbox__input.is-indeterminate .el-checkbox__inner {
  1057. border-color: var(--diy-theme);
  1058. background: var(--diy-theme);
  1059. }
  1060. </style>