components.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /**
  2. * 系统内置属性组件
  3. */
  4. var resourceHtml = '<div v-show="false"><slot></slot></div>';
  5. //CSS·组件
  6. Vue.component("css", {
  7. props: ["src"],
  8. template: resourceHtml,
  9. created: function () {
  10. var self = this;
  11. //内联样式
  12. if (this.$slots.default) {
  13. var css = "<style>" + this.$slots.default[0].text + '</style>';
  14. //防止重复加载资源
  15. if ($("head").html().indexOf(css) == -1) {
  16. $("head").append(css);
  17. }
  18. //延迟
  19. setTimeout(function () {
  20. self.$parent.data.lazyLoadCss = true;
  21. }, 10);
  22. }
  23. //外联样式
  24. if (this.src) {
  25. //防止重复加载资源
  26. if ($("head").html().indexOf(this.src) == -1) {
  27. var styleNode = createLink(this.src);
  28. styleOnload(styleNode, function () {
  29. self.$parent.data.lazyLoadCss = true;
  30. });
  31. } else {
  32. //延迟
  33. setTimeout(function () {
  34. self.$parent.data.lazyLoadCss = true;
  35. }, 10);
  36. }
  37. }
  38. }
  39. });
  40. //JavaScript脚本·组件
  41. Vue.component("js", {
  42. props: ["src"],
  43. template: resourceHtml,
  44. created: function () {
  45. var self = this;
  46. //如果JS全部是内部代码,则延迟10毫秒
  47. //如果JS有内部代码、也有外部JS,则以外部JS加载完成时间为准,同时延迟10毫秒,让外部JS中的组件进行加载
  48. //如果JS全部是外部代码,则以外部JS加载完成时间为准,同时延迟10毫秒,让外部JS中的组件进行加载
  49. //内联js
  50. if (this.$slots.default) {
  51. var script = "<script>" + this.$slots.default[0].text + "</script>";
  52. $("body").append(script);
  53. //如果有外部JS,则以外部JS加载完成时间为准
  54. if (this.$parent.data.outerCountJs == 0) {
  55. setTimeout(function () {
  56. self.$parent.data.lazyLoad = true;
  57. }, 10);
  58. }
  59. }
  60. //外联js
  61. if (this.src) {
  62. $.getScript(this.src, function (res) {
  63. setTimeout(function () {
  64. self.$parent.data.lazyLoad = true;
  65. }, 10);
  66. });
  67. }
  68. }
  69. });
  70. /**
  71. * 系统内置属性组件
  72. */
  73. var imageHtml = `<div :style="style"></div>`;
  74. //图片组件
  75. Vue.component("nc-image", {
  76. props: {
  77. src: {
  78. type: String,
  79. default: ''
  80. },
  81. mode: {
  82. type: String,
  83. default: 'scaleToFill'
  84. },
  85. width: {
  86. type: String,
  87. default: '100%'
  88. },
  89. height: {
  90. type: String,
  91. default: '100%'
  92. }
  93. },
  94. data: function () {
  95. return {
  96. style: {
  97. 'background-image': 'url('+ this.src +')',
  98. 'background-repeat': 'no-repeat',
  99. 'width': this.width,
  100. 'height': this.height,
  101. 'background-position': 'center',
  102. 'background-size': ''
  103. },
  104. modeList: {
  105. aspectFit: {'background-size': 'contain'}, // 缩放
  106. scaleToFill: {'background-size': '100% 100%'}, // 拉伸
  107. aspectFill: {'background-size': 'cover'}, // 填充
  108. center: {'background-size': 'auto auto'} // 居中裁剪
  109. }
  110. }
  111. },
  112. template: imageHtml,
  113. created: function () {
  114. if (this.modeList[ this.mode ]) Object.assign(this.style, this.modeList[ this.mode ]);
  115. },
  116. watch: {
  117. mode: function (val) {
  118. this.$set(this.style, 'background-size', this.modeList[ this.mode ]['background-size'])
  119. },
  120. src: function (val) {
  121. this.$set(this.style, 'background-image', 'url('+ this.src +')')
  122. }
  123. }
  124. });
  125. /**
  126. * 图片显示模式组件
  127. */
  128. var imageModeHtml = `
  129. <div class="layui-form-item component-links">
  130. <label class="layui-form-label sm">缩放模式</label>
  131. <div class="layui-input-block">
  132. <span class="sm text-color" @click="selected()">
  133. <span :title="modeList[ data.imageMode ].name">{{ modeList[ data.imageMode ].name }}</span>
  134. <i class="layui-icon layui-icon-right"></i>
  135. </span>
  136. </div>
  137. </div>
  138. `;
  139. Vue.component("nc-image-mode", {
  140. props: {
  141. data: {
  142. type: Object,
  143. default: function () {
  144. return {
  145. imageMode: "scaleToFill"
  146. };
  147. }
  148. },
  149. },
  150. template: imageModeHtml,
  151. data: function () {
  152. return {
  153. modeList:{
  154. scaleToFill: {mode: 'scaleToFill', name: '拉伸'},
  155. aspectFit: {mode: 'aspectFit', name: '缩放'},
  156. aspectFill: {mode: 'aspectFill', name: '填充'},
  157. // center: {mode: 'center', name: '中心裁剪'}
  158. }
  159. };
  160. },
  161. created: function () {
  162. if (!this.data.imageMode) this.$set(this.data, 'imageMode', 'scaleToFill');
  163. },
  164. methods: {
  165. selected: function () {
  166. var $self = this;
  167. var h = `<div class="layui-form"><div class="layui-form-item component-links"><label class="layui-form-label sm">缩放模式:</label><div class="layui-input-block">`;
  168. Object.keys(this.modeList).forEach(function (key) {
  169. let item = $self.modeList[key];
  170. h += '<input type="radio" name="image_mode" value="'+ item.mode +'" title="'+ item.name +'" '+ (key == $self.data.imageMode ? ' checked' : '') +'>';
  171. })
  172. h += '</div></div></div>'
  173. layer.open({
  174. title: "图片缩放模式设置",
  175. type: 1,
  176. area: ['450px', '190px'],
  177. fixed: false, //不固定
  178. content: h,
  179. success: function(){
  180. layui.use('form', function(){
  181. layui.form.render();
  182. })
  183. },
  184. btn: ['保存', '取消'],
  185. yes: function () {
  186. let mode = $('[name="image_mode"]:checked').val();
  187. $self.data.imageMode = mode;
  188. layer.closeAll();
  189. }
  190. })
  191. }
  192. }
  193. });
  194. //[对齐方式]属性组件
  195. var textAlignHtml = '<div class="layui-form-item">';
  196. textAlignHtml += '<label class="layui-form-label sm">{{data.label}}</label>';
  197. textAlignHtml += '<div class="layui-input-block">';
  198. textAlignHtml += '<template v-for="(item,index) in list">';
  199. textAlignHtml += '<div @click="parent[data.field]=item.value" :class="{ \'layui-unselect layui-form-radio\' : true,\'layui-form-radioed\' : (parent[data.field]==item.value) }"><i class="layui-anim layui-icon">{{ parent[data.field] == item.value ? \'&#xe643;\':\'&#xe63f;\' }}</i><div>{{item.label}}</div></div>';
  200. textAlignHtml += '</template>';
  201. textAlignHtml += '</div>';
  202. textAlignHtml += '</div>';
  203. Vue.component("text-align", {
  204. props: {
  205. data: {
  206. type: Object,
  207. default: function () {
  208. return {
  209. field: "textAlign",
  210. label: "对齐方式"
  211. };
  212. }
  213. }
  214. },
  215. created: function () {
  216. if (this.data.label === undefined) this.data.label = "对齐方式";
  217. if (this.data.field === undefined) this.data.field = "textAlign";
  218. },
  219. template: textAlignHtml,
  220. data: function () {
  221. return {
  222. list: [
  223. {label: "居左", value: "left"},
  224. {label: "居中", value: "center"},
  225. {label: "居右", value: "right"}
  226. ],
  227. parent: this.$parent.data,
  228. };
  229. }
  230. });
  231. //[滑块]属性组件
  232. var sliderHtml = '<div class="layui-form-item slide-component">';
  233. sliderHtml += '<label class="layui-form-label sm">{{compData.label}}</label>';
  234. sliderHtml += '<div class="layui-input-block">';
  235. sliderHtml += '<div :id="id" class="side-process"></div>';
  236. // sliderHtml += '<span class="slide-prompt-text">{{parent[compData.field]}}</span>';
  237. sliderHtml += '</div>';
  238. sliderHtml += '</div>';
  239. Vue.component("slide", {
  240. template: sliderHtml,
  241. props: {
  242. data: {
  243. type: Object,
  244. default: function () {
  245. return {
  246. field: "height",
  247. label: "空白高度",
  248. min: 0,
  249. max: 100,
  250. callback: null
  251. };
  252. }
  253. }
  254. },
  255. data: function () {
  256. return {
  257. id: "slide_" + ns.gen_non_duplicate(10),
  258. parent: this.$parent.data,
  259. compData:null
  260. };
  261. },
  262. created: function () {
  263. this.compData = this.data;// vue组件中不能直接改变props,定义内部变量处理
  264. if (this.compData.label === undefined) this.compData.label = "空白高度";
  265. if (this.compData.field === undefined) this.compData.field = "height";
  266. if (this.compData.min === undefined) this.compData.min = 0;
  267. if (this.compData.max === undefined) this.compData.max = 100;
  268. if (this.compData.parent === 'global') this.parent = this.$parent.global;
  269. else if (this.compData.parent === 'template') this.parent = this.$parent.global.template;
  270. else if (this.compData.parent !== undefined) this.parent = this.$parent.data[this.compData.parent];
  271. var fieldArr = this.compData.field.split('.');
  272. this.compData.field = fieldArr[fieldArr.length - 1];
  273. for (var i = 0; i < fieldArr.length - 1; i++) {
  274. this.parent = this.parent[fieldArr[i]];
  275. }
  276. var _self = this;
  277. setTimeout(function () {
  278. layui.use('slider', function () {
  279. var slider = layui.slider;
  280. slider.render({
  281. elem: '#' + _self.id,
  282. min: _self.compData.min,
  283. max: _self.compData.max,
  284. tips: false,
  285. input: true,
  286. value: _self.parent[_self.compData.field],
  287. change: function (value) {
  288. _self.parent[_self.compData.field] = value;
  289. // 如果修改页面属性,那么组件属性也要变化
  290. if (_self.compData.parent === 'template') {
  291. for (var i = 0; i < vue.data.length; i++) {
  292. if (fieldArr.length > 1) {
  293. for (var j = 0; j < fieldArr.length - 1; j++) {
  294. vue.data[i][fieldArr[j]][_self.compData.field] = value;
  295. }
  296. } else {
  297. vue.data[i][_self.compData.field] = value;
  298. }
  299. }
  300. }
  301. if (_self.compData.callback) _self.compData.callback.call(this);
  302. }
  303. });
  304. });
  305. }, 10);
  306. }
  307. });
  308. //[链接地址]属性组件
  309. var linkHtml = '<div class="layui-form-item component-links">';
  310. linkHtml += '<label class="layui-form-label sm">{{myData[0].label}}</label>';
  311. linkHtml += '<div class="layui-input-block">';
  312. linkHtml += '<span class="sm" :class="{ \'text-color\': myData[0].field.title}" @click="selected()"><span :title="myData[0].field.title">{{myData[0].field.title ? myData[0].field.title : "请选择链接"}}</span><i class="layui-icon layui-icon-right"></i></span>';
  313. linkHtml += '</div>';
  314. linkHtml += '</div>';
  315. /**
  316. * 链接组件:
  317. * 参数说明:data:链接对象,callback:回调
  318. */
  319. Vue.component("nc-link", {
  320. props: {
  321. data: {
  322. type: Object,
  323. default: function () {
  324. return {
  325. field: null,// 链接对象
  326. label: "链接地址",// 文本
  327. };
  328. }
  329. },
  330. callback: null,
  331. },
  332. template: linkHtml,
  333. data: function () {
  334. return {
  335. myData: [this.data], // 此处用数组的目的是触发变异方法,进行视图更新
  336. };
  337. },
  338. created: function () {
  339. if (this.data.label == undefined) this.data.label = "链接地址";
  340. },
  341. methods: {
  342. //设置链接地址
  343. set: function (link) {
  344. //由于Vue2.0是单向绑定的:子组件无法修改父组件,但是可以修改单个属性,循环遍历属性赋值
  345. if (this.myData[0].field) {
  346. for (var k in this.myData[0].field) delete this.myData[0].field[k];
  347. for (var k in link) this.myData[0].field[k] = link[k];
  348. }
  349. //触发变异方法,进行视图更新
  350. this.myData.push({});
  351. this.myData.pop();
  352. },
  353. selected: function () {
  354. var $self = this;
  355. ns.select_link($self.myData[0].field, function (data) {
  356. $self.set(data);
  357. if ($self.callback) $self.callback.call(this, data);
  358. });
  359. }
  360. }
  361. });
  362. //[颜色]属性组件
  363. var colorHtml = '<div class="layui-form-item flex">';
  364. colorHtml += '<div class="flex_left">';
  365. colorHtml += '<label class="layui-form-label sm">{{compData.label}}</label>';
  366. colorHtml += '<slot></slot>';
  367. colorHtml += '<div class="curr-color">';
  368. colorHtml += '<span v-for="(item,index) in field">{{ parent[item] ? parent[item].toUpperCase() : "透明" }}</span>';
  369. colorHtml += '</div>';
  370. colorHtml += '<slot name="right"></slot>';
  371. colorHtml += '</div>';
  372. colorHtml += '<div class="layui-input-block flex_fill">';
  373. colorHtml += '<div :id="item" v-for="(item,index) in ids" class="picker colorSelector"><div :style="{ background : parent[field[index]] }"></div></div>';
  374. colorHtml += '<span class="color-selector-reset text-color" @click="reset()">重置</span>';
  375. colorHtml += '</div>';
  376. colorHtml += '</div>';
  377. /**
  378. * 颜色组件:
  379. * 参数说明:
  380. * data:{ field : 字段名, value : 值(默认:#303133), 'label' : 文本标签(默认:文字颜色) }
  381. */
  382. Vue.component("color", {
  383. props: {
  384. data: {
  385. type: Object,
  386. default: function () {
  387. return {
  388. field: "textColor",
  389. label: "文字颜色",
  390. defaultColor: "",
  391. value: "",
  392. callback: null
  393. };
  394. }
  395. },
  396. },
  397. template: colorHtml,
  398. data: function () {
  399. return {
  400. compData: this.data,
  401. field: [], // 支持多个颜色
  402. defaultColor: [], // 支持多个颜色值
  403. ids: [],
  404. parent: this.$parent.data ? ((Object.keys(this.$parent.data).length) ? this.$parent.data : this.$parent.global) : this.$parent.global,
  405. };
  406. },
  407. created: function () {
  408. this.bindColor();
  409. },
  410. methods: {
  411. init: function () {
  412. this.compData = this.data;
  413. if (this.compData.field === undefined) this.compData.field = "textColor";
  414. if (this.compData.label === undefined) this.compData.label = "文字颜色";
  415. if (this.compData.value === undefined) this.compData.value = "#303133";
  416. if (this.compData.defaultColor === undefined) this.compData.defaultColor = "";
  417. // 检查是否有多个颜色
  418. if (this.compData.field.indexOf(',') !== -1) this.field = this.compData.field.split(',');
  419. else this.field = [this.compData.field];
  420. // 检查是否有多个颜色
  421. if (this.compData.defaultColor.indexOf(',') !== -1) this.defaultColor = this.compData.defaultColor.split(',');
  422. else this.defaultColor = [this.compData.defaultColor];
  423. // 找寻父级
  424. if (this.compData.parent === 'global') this.parent = this.$parent.global;
  425. else if (this.compData.parent === 'template') this.parent = this.$parent.global.template;
  426. else if (this.compData.parent !== undefined) {
  427. if (typeof this.compData.parent == 'string') this.parent = this.$parent.data[this.compData.parent];
  428. if (typeof this.compData.parent == 'object') this.parent = this.compData.parent;
  429. }
  430. //如果当前字段没有值数据,则给予默认值,反之用该字段的值,用于优化调用该组件
  431. for (var i = 0; i < this.field.length; i++) {
  432. if (this.parent[this.field[i]] === undefined) this.$set(this.parent, this.field[i], this.compData.value);
  433. else this.compData.value = this.parent[this.field[i]];
  434. this.parent[this.field[i]] = this.compData.value;
  435. }
  436. },
  437. reset: function () {
  438. try {
  439. for (var i = 0; i < this.field.length; i++) {
  440. this.parent[this.field[i]] = this.defaultColor[i];
  441. }
  442. } catch (e) {
  443. console.log("color reset() ERROR:", e);
  444. }
  445. },
  446. bindColor() {
  447. this.init();
  448. for (var i = 0; i < this.field.length; i++) {
  449. var name = "colorSelector_" + this.field[i] + '_' + (this.compData.id || ns.gen_non_duplicate(5));
  450. this.ids.push(name);
  451. var $self = this;
  452. setColorPicker(this.parent[this.field[i]], name, function (hex, elem) {
  453. try {
  454. // data数据可能不全,所以要用compData,通过对象的引用关系绑定数据
  455. // 这里要更新$self,不然如果删除了,就会出问题
  456. var field = elem.attr('id').split('_')[1];
  457. if (hex) {
  458. $self.parent[field] = hex;
  459. } else {
  460. $self.parent[field] = "";
  461. }
  462. } catch (e) {
  463. console.log("color ERROR:" + e.message);
  464. }
  465. });
  466. }
  467. }
  468. }
  469. });
  470. /**
  471. * 生成颜色选择器
  472. * @param defaultColor
  473. * @param name
  474. * @param callBack
  475. */
  476. function setColorPicker(defaultColor, name, callBack) {
  477. setTimeout(function () {
  478. Colorpicker.create({
  479. el: name,
  480. color: defaultColor,
  481. change: function (elem, hex) {
  482. $(elem).find("div").css('background', hex);
  483. if (callBack) callBack(hex,$(elem));
  484. }
  485. });
  486. if (defaultColor) $("#" + name).find("div").css('background', defaultColor);
  487. }, 500);
  488. }
  489. //[文字大小]属性组件
  490. var fontSizeHtml = '<div class="layui-form-item">';
  491. fontSizeHtml += '<label class="layui-form-label sm">{{d.label}}</label>';
  492. fontSizeHtml += '<div class="layui-input-block">';
  493. fontSizeHtml += '<div :class="{ \'layui-unselect layui-form-select\' : true, \'layui-form-selected\' : isShowFontSize }" @click="isShowFontSize=!isShowFontSize;">';
  494. fontSizeHtml += '<div class="layui-select-title">';
  495. fontSizeHtml += '<input type="text" placeholder="请选择" :value="list[selectIndex].text" readonly="readonly" class="layui-input layui-unselect">';
  496. fontSizeHtml += '<i class="layui-edge"></i>';
  497. fontSizeHtml += '</div>';
  498. fontSizeHtml += '<dl class="layui-anim layui-anim-upbit">';
  499. fontSizeHtml += '<dd v-for="(item,index) in list" :value="item.value" :class="{ \'layui-this\' : (parent[d.field]==item.value) }" @click.stop="parent[d.field]=item.value;isShowFontSize=false;selectIndex=index;">{{item.text}}</dd>';
  500. fontSizeHtml += '</dl>';
  501. fontSizeHtml += '</div>';
  502. fontSizeHtml += '</div>';
  503. fontSizeHtml += '</div>';
  504. /**
  505. * 文字大小
  506. * 参数说明:
  507. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) }
  508. */
  509. Vue.component("font-size", {
  510. template: fontSizeHtml,
  511. props: {
  512. data: {
  513. type: Object,
  514. default: function () {
  515. return {
  516. field: "fontSize",
  517. label: "文字大小",
  518. value: 14
  519. };
  520. }
  521. },
  522. },
  523. data: function () {
  524. return {
  525. d: this.data,
  526. isShowFontSize: false,
  527. selectIndex: 2, //当前选中的下标
  528. list: [],
  529. parent: (Object.keys(this.$parent.data).length) ? this.$parent.data : this.$parent.global,
  530. };
  531. },
  532. created: function () {
  533. if (this.data.field == undefined) this.data.field = "fontSize";
  534. if (this.data.label == undefined) this.data.label = "文字大小";
  535. if (this.data.value == undefined) this.data.value = 14;
  536. if (this.parent[this.data.field] == undefined) this.$set(this.parent, this.data.field, this.data.value);
  537. this.parent[this.data.field] = this.data.value;
  538. for (var i = 12; i <= 30; i++) this.list.push({value: i, text: i + "px"});
  539. for (var i = 0; i < this.list.length; i++) {
  540. if (this.list[i].value == this.data.value) {
  541. this.selectIndex = i;
  542. break;
  543. }
  544. }
  545. },
  546. });
  547. //[图片上传]组件
  548. var imageHtml = '<div v-show="condition" class="img-block layui-form text-color" :id="id" :class="{ \'has-choose-image\' : (myData.data[myData.field]) }">';
  549. imageHtml += '<div>';
  550. imageHtml += '<template v-if="myData.data[myData.field]">';
  551. imageHtml += '<img :layer-src="changeImgUrl(myData.data[myData.field])" :src="changeImgUrl(myData.data[myData.field])" :id="id+\'-img\'"/>';
  552. imageHtml += '<div class="operation">';
  553. imageHtml += '<div class="operation-warp">';
  554. imageHtml += '<i title="图片预览" class="iconfont iconreview js-preview" @click="previewImg(id)"></i>';
  555. imageHtml += '<i title="删除图片" class="layui-icon layui-icon-delete js-delete" @click="del()"></i>';
  556. imageHtml += '</div>';
  557. imageHtml += '<div class="replace_img js-replace" @click="uploadImg()">点击替换</div>';
  558. imageHtml += '</div>';
  559. imageHtml += '</template>';
  560. imageHtml += '<template v-else>';
  561. imageHtml += '<i class="add" @click="uploadImg()">+</i>';
  562. imageHtml += '<i class="del" @click.stop="del()" data-disabled="1" v-if="myData.isShow">x</i>';
  563. imageHtml += '</template>';
  564. imageHtml += '</div>';
  565. imageHtml += '</div>';
  566. /**
  567. * 图片上传
  568. * 参数说明:
  569. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) ,isShow: 控制右上角显隐,注意使用场景(一张图片且需要删除时使用,参考拼团、限时折扣等背景)}
  570. */
  571. Vue.component("img-upload", {
  572. template: imageHtml,
  573. props: {
  574. data: {
  575. type: Object,
  576. default: function () {
  577. return {
  578. data: {},
  579. field: "imageUrl",
  580. callback: null
  581. };
  582. }
  583. },
  584. condition: {
  585. type: Boolean,
  586. default: true
  587. }
  588. },
  589. data: function () {
  590. return {
  591. myData: this.data,
  592. upload: null,
  593. id: ns.gen_non_duplicate(10),
  594. // parent: (Object.keys(this.$parent.data).length) ? this.$parent.data : this.data,
  595. };
  596. },
  597. created: function () {
  598. if (this.myData.field === undefined) this.myData.field = "imageUrl";
  599. this.id = ns.gen_non_duplicate(10);
  600. },
  601. methods: {
  602. del: function () {
  603. this.myData.data[this.myData.field] = "";
  604. },
  605. //转换图片路径
  606. changeImgUrl: function (url) {
  607. if (url == null || url === "") return '';
  608. if (url.indexOf("static/img/") > -1) return ns.img(ns_url.staticImg + "/" + url.replace("public/static/img/", ""));
  609. else return ns.img(url);
  610. },
  611. uploadImg: function () {
  612. var self = this;
  613. openAlbum(function (obj) {
  614. for (var i = 0; i < obj.length; i++) {
  615. self.myData.data[self.myData.field] = obj[i].pic_path;
  616. self.myData.data.imgWidth = obj[i].pic_spec.split("*")[0];
  617. self.myData.data.imgHeight = obj[i].pic_spec.split("*")[1];
  618. if (self.myData.callback) self.myData.callback.call(this);
  619. loadImgMagnify();
  620. }
  621. }, 1);
  622. },
  623. previewImg(id){
  624. $('#'+id).find('div>img').click();
  625. },
  626. }
  627. });
  628. //[视频上传]组件
  629. var videoHtml = '<div style="position: relative" class="video-add-box" @click="uploadImg()">';
  630. videoHtml += '<div class="img-block layui-form text-color">';
  631. videoHtml += '<template v-if="myData.data[myData.field]">';
  632. videoHtml += '<video :src="changeImgUrl(myData.data[myData.field])" controls/></video>';
  633. videoHtml += '<span>更换视频</span>';
  634. videoHtml += '</template>';
  635. videoHtml += '<template v-else>';
  636. videoHtml += '<div>';
  637. videoHtml += '<i class="add add-video">+</i>';
  638. videoHtml += '</div>';
  639. videoHtml += '</template>';
  640. videoHtml += '</div>';
  641. videoHtml += '</div>';
  642. /**
  643. * 视频上传
  644. * 参数说明:
  645. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) }
  646. */
  647. Vue.component("video-upload", {
  648. template: videoHtml,
  649. props: {
  650. data: {
  651. type: Object,
  652. default: function () {
  653. return {
  654. data: {},
  655. field: "videoUrl",
  656. callback: null
  657. };
  658. }
  659. }
  660. },
  661. data: function () {
  662. return {
  663. myData: this.data,
  664. };
  665. },
  666. created: function () {
  667. if (this.myData.field === undefined) this.myData.field = "videoUrl";
  668. },
  669. methods: {
  670. //转换图片路径
  671. changeImgUrl: function (url) {
  672. if (url == null || url === "") return '';
  673. else return ns.img(url);
  674. },
  675. uploadImg: function () {
  676. var self = this;
  677. openAlbum(function (obj) {
  678. self.myData.data[self.myData.field] = obj[0].pic_path;
  679. if (self.myData.callback) self.myData.callback.call(this);
  680. }, 1,0,'video');
  681. }
  682. }
  683. });
  684. var imgIconHtml = `
  685. <div>
  686. <div class="img-upload icon-img-upload" v-if="!myData.data.iconType || myData.data.iconType == 'img'" :id="id">
  687. <template v-if="myData.data[myData.field]">
  688. <img :src="changeImgUrl(myData.data[myData.field])" :layer-src="changeImgUrl(myData.data[myData.field])"/>
  689. <div class="operation">
  690. <div class="operation-warp">
  691. <i title="图片预览" class="iconfont iconreview js-preview" @click="previewImg()"></i>
  692. <i title="删除图片" class="layui-icon layui-icon-delete" @click="del"></i>
  693. </div>
  694. <div class="js-replace" @click="uploadImg">点击替换</div>
  695. </div>
  696. </template>
  697. <template v-else>
  698. <i class="add" @click="uploadImg">+</i>
  699. </template>
  700. </div>
  701. <div class="icon-upload icon-img-upload icon-box" v-if="myData.data.iconType && myData.data.iconType == 'icon'">
  702. <template v-if="myData.data[myData.iconField]">
  703. <iconfont :icon="myData.data[myData.iconField]" :value="myData.data.style ? myData.data.style : null"></iconfont>
  704. <div class="operation">
  705. <div class="operation-warp">
  706. <i title="图标预览" class="iconfont iconreview js-preview"></i>
  707. <i title="删除图标" class="layui-icon layui-icon-delete" @click="del"></i>
  708. </div>
  709. <div class="js-replace" @click="uploadImg">点击替换</div>
  710. </div>
  711. </template>
  712. <template v-else>
  713. <i class="add" @click="uploadImg">+</i>
  714. </template>
  715. </div>
  716. </div>
  717. `;
  718. /**
  719. * 图片或图标选择
  720. * 参数说明:
  721. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) ,isShow: 控制右上角显隐,注意使用场景(一张图片且需要删除时使用,参考拼团、限时折扣等背景)}
  722. */
  723. Vue.component("img-icon-upload", {
  724. template: imgIconHtml,
  725. props: {
  726. data: {
  727. type: Object,
  728. default: function () {
  729. return {
  730. data: {},
  731. field: "imageUrl",
  732. iconField: "icon",
  733. displayType : 'img,icon',
  734. callback: null
  735. };
  736. }
  737. }
  738. },
  739. data: function () {
  740. return {
  741. myData: this.data,
  742. upload: null,
  743. id: ns.gen_non_duplicate(10),
  744. };
  745. },
  746. created: function () {
  747. if (this.myData.field === undefined) this.myData.field = "imageUrl";
  748. if (this.myData.iconField === undefined) this.myData.iconField = "icon";
  749. this.id = ns.gen_non_duplicate(10);
  750. },
  751. methods: {
  752. del: function () {
  753. if (this.myData.data.iconType && this.myData.data.iconType == 'icon') this.myData.data[this.myData.iconField] = '';
  754. else this.myData.data[this.myData.field] = "";
  755. this.$forceUpdate();
  756. },
  757. //转换图片路径
  758. changeImgUrl: function (url) {
  759. if (url == null || url === "") return '';
  760. if (url.indexOf("static/img/") > -1) return ns.img(ns_url.staticImg + "/" + url.replace("public/static/img/", ""));
  761. else return ns.img(url);
  762. },
  763. uploadImg: function () {
  764. var self = this;
  765. if(self.data.displayType === undefined) self.data.displayType ='img,icon';
  766. openAlbum(function (obj) {
  767. if (typeof obj == 'object') {
  768. self.myData.data[self.myData.field] = obj[0].pic_path;
  769. self.myData.data.imgWidth = obj[0].pic_spec.split("*")[0];
  770. self.myData.data.imgHeight = obj[0].pic_spec.split("*")[1];
  771. self.myData.data.iconType = 'img';
  772. loadImgMagnify();
  773. } else {
  774. self.myData.data[self.myData.iconField] = obj;
  775. self.myData.data.iconType = 'icon';
  776. if (!self.myData.data.style) {
  777. self.$set(self.myData.data, 'style', {
  778. fontSize: 60,
  779. iconBgColor: ["#7b00ff"],
  780. iconBgColorDeg: 180,
  781. iconBgImg: 'public/static/ext/diyview/img/icon_bg/bg_05.png',
  782. bgRadius: 38,
  783. iconColor: ['#fff'],
  784. iconColorDeg: 0,
  785. })
  786. }
  787. }
  788. self.$forceUpdate();
  789. }, 1, 0, 'img', self.data.displayType);
  790. },
  791. previewImg(){
  792. $('#'+this.id).find('img').click();
  793. }
  794. }
  795. });
  796. var commonSetHtml = '<div class="common-set" v-if="ignore.indexOf(\'pageBgColor\') == -1 || ignore.indexOf(\'componentBgColor\') == -1 || (ignore.indexOf(\'marginTop\') == -1 || ignore.indexOf(\'marginBottom\') == -1 || ignore.indexOf(\'marginBoth\') == -1) || ignore.indexOf(\'componentAngle\') == -1">';
  797. commonSetHtml += '<div class="template-edit-title">';
  798. commonSetHtml += '<h3>组件样式</h3>';
  799. commonSetHtml += '<template v-if="ignore.indexOf(\'pageBgColor\') == -1 || ignore.indexOf(\'componentBgColor\') == -1">';
  800. commonSetHtml += '<color v-if="ignore.indexOf(\'pageBgColor\') == -1" :data="{ field : \'pageBgColor\', \'label\' : \'底部背景\' }"></color>';
  801. commonSetHtml += '<p class="word-aux">底部背景包含边距和圆角</p>';
  802. commonSetHtml += '<color v-if="ignore.indexOf(\'componentBgColor\') == -1" :data="{ field : \'componentBgColor\', \'label\' : \'组件背景\' }"></color>';
  803. commonSetHtml += '</template>';
  804. commonSetHtml += '<template v-if="ignore.indexOf(\'marginTop\') == -1 || ignore.indexOf(\'marginBottom\') == -1 || ignore.indexOf(\'marginBoth\') == -1">';
  805. commonSetHtml += '<slide v-if="ignore.indexOf(\'marginTop\') == -1" :data="{ field : \'margin.top\', label : \'上边距\' }"></slide>';
  806. commonSetHtml += '<slide v-if="ignore.indexOf(\'marginBottom\') == -1" :data="{ field : \'margin.bottom\', label : \'下边距\' }"></slide>';
  807. commonSetHtml += '<slide v-if="ignore.indexOf(\'marginBoth\') == -1" :data="{ field : \'margin.both\', label : \'左右边距\', max : 20 }"></slide>';
  808. commonSetHtml += '</template>';
  809. commonSetHtml += '<template v-if="ignore.indexOf(\'componentAngle\') == -1">';
  810. commonSetHtml += '<slide v-show="data.componentAngle == \'round\'" :data="{ field : \'topAroundRadius\', label : \'上圆角\', max : 50 }"></slide>';
  811. commonSetHtml += '<slide v-show="data.componentAngle == \'round\'" :data="{ field : \'bottomAroundRadius\', label : \'下圆角\', max : 50 }"></slide>';
  812. commonSetHtml += '</template>';
  813. commonSetHtml += '</div>';
  814. commonSetHtml += '</div>';
  815. /**
  816. * 公共属性设置
  817. */
  818. Vue.component("common-set", {
  819. template: commonSetHtml,
  820. props: {
  821. // 忽略属性【textColor(文本颜色)、backgroundColor(背景色)、marginTop(上边距)、marginBottom(下边距)、marginBoth(左右边距)、componentAngle(圆角展示)】
  822. ignore: {
  823. type: Array,
  824. default: function () {
  825. return [];
  826. }
  827. },
  828. callback: {
  829. type: Function,
  830. default: function () {
  831. }
  832. }
  833. },
  834. data: function () {
  835. return {
  836. data: this.$parent.data,
  837. angleList: [
  838. {
  839. text: "直角",
  840. value: "right",
  841. src: 'icongl-square'
  842. },
  843. {
  844. text: "圆角",
  845. value: "round",
  846. src: 'iconyuanjiao'
  847. }
  848. ],
  849. }
  850. },
  851. created: function () {
  852. },
  853. methods: {
  854. triggerCallback(){
  855. if(this.callback) this.callback(this);
  856. }
  857. },
  858. });
  859. var popWindowHtml = '<div class="pop-window-wrap" :class="{selected : currentIndex==-98}" :data-sort="-98" v-show="currentIndex==-98">';
  860. popWindowHtml += '<div class="edit-attribute">';
  861. popWindowHtml += '<div class="attr-wrap">';
  862. popWindowHtml += '<div class="restore-wrap">';
  863. popWindowHtml += '<h2 class="attr-title">弹窗广告</h2>';
  864. popWindowHtml += '<div class="layui-form-item checkbox-wrap custom-popup">';
  865. popWindowHtml += '<label class="layui-form-label sm">是否开启</label>';
  866. popWindowHtml += '<div class="layui-input-block">';
  867. popWindowHtml += '<span v-if="global.popWindow.count == -1">关闭</span>';
  868. popWindowHtml += '<span v-else>开启</span>';
  869. popWindowHtml += '<div v-if="global.popWindow.count != -1" @click="global.popWindow.count = -1" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  870. popWindowHtml += '<div v-else @click="global.popWindow.count = 1" class="layui-unselect layui-form-checkbox" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  871. popWindowHtml += '</div>';
  872. popWindowHtml += '</div>';
  873. popWindowHtml += '<template v-if="global.popWindow.count != -1">';
  874. // popWindowHtml += '<div class="template-edit-title">';
  875. // popWindowHtml += '<h3>弹出形式</h3>';
  876. // popWindowHtml += '</div>';
  877. popWindowHtml += '<div class="layui-form-item">';
  878. popWindowHtml += '<label class="layui-form-label sm"></label>';
  879. popWindowHtml += '<div class="layui-input-block">';
  880. popWindowHtml += '<div @click="global.popWindow.count=1" :class="{ \'layui-unselect layui-form-radio\' : true,\'layui-form-radioed\' : (global.popWindow.count==1) }">';
  881. popWindowHtml += '<i class="layui-anim layui-icon">{{ global.popWindow.count == 1 ? \'&#xe643;\':\'&#xe63f;\' }}</i>';
  882. popWindowHtml += '<div>首次弹出</div>';
  883. popWindowHtml += '</div>';
  884. popWindowHtml += '<div @click="global.popWindow.count=0" :class="{ \'layui-unselect layui-form-radio\' : true,\'layui-form-radioed\' : (global.popWindow.count==0) }">';
  885. popWindowHtml += '<i class="layui-anim layui-icon">{{ global.popWindow.count == 0 ? \'&#xe643;\':\'&#xe63f;\' }}</i>';
  886. popWindowHtml += '<div>每次弹出</div>';
  887. popWindowHtml += '</div>';
  888. popWindowHtml += '</div>';
  889. popWindowHtml += '</div>';
  890. popWindowHtml += '</template>';
  891. popWindowHtml += '<div class="layui-form-item">';
  892. popWindowHtml += '<label class="layui-form-label sm">广告图</label>';
  893. popWindowHtml += '<div class="layui-input-block img-upload">';
  894. popWindowHtml += '<template v-if="globalLazyLoad">';
  895. popWindowHtml += '<img-upload :data="{ data : global.popWindow, field : \'imageUrl\', text: \'\', isShow:true }"></img-upload>';
  896. popWindowHtml += '</template>';
  897. popWindowHtml += '</div>';
  898. popWindowHtml += '<div class="word-aux diy-word-aux">建议上传图片大小:290px * 410px</div>';
  899. popWindowHtml += '</div>';
  900. popWindowHtml += '<template v-if="globalLazyLoad">';
  901. popWindowHtml += '<nc-link :data="{ field : global.popWindow.link, parent : \'global\' , label : \'广告链接\' }"></nc-link>';
  902. popWindowHtml += '</template>';
  903. popWindowHtml += '</div>';
  904. popWindowHtml += '</div>';
  905. popWindowHtml += '</div>';
  906. popWindowHtml += '</div>';
  907. /**
  908. * 弹出广告组件
  909. */
  910. Vue.component("pop-window", {
  911. template: popWindowHtml,
  912. props: ['currentIndex', 'global','globalLazyLoad'],
  913. data: function () {
  914. return {}
  915. },
  916. created: function () {
  917. // console.log('popWindow', this.currentIndex, this.global);
  918. },
  919. methods: {}
  920. });
  921. var pageSetHtml = '<div class="edit-attribute">';
  922. pageSetHtml += '<div class="attr-wrap">';
  923. pageSetHtml += '<div class="restore-wrap">';
  924. pageSetHtml += '<div class="attr-title">';
  925. pageSetHtml += '<span class="title">页面设置</span>';
  926. pageSetHtml += '<div class="tab-wrap" style="display: flex;">';
  927. pageSetHtml += '<span class="active bg-color" data-type="content">内容</span>';
  928. pageSetHtml += '<span data-type="style">样式</span>';
  929. pageSetHtml += '</div>';
  930. pageSetHtml += '</div>';
  931. pageSetHtml += '<div class="edit-content-wrap">';
  932. pageSetHtml += '<div class="template-edit-title">';
  933. pageSetHtml += '<h3>页面内容</h3>';
  934. pageSetHtml += '<div class="layui-form-item">';
  935. pageSetHtml += '<label class="layui-form-label sm">页面名称</label>';
  936. pageSetHtml += '<div class="layui-input-block">';
  937. pageSetHtml += '<input type="text" v-model="global.title" placeholder="请输入页面名称" class="layui-input" maxlength="15">';
  938. pageSetHtml += '</div>';
  939. pageSetHtml += '</div>';
  940. pageSetHtml += '<div class="layui-form-item">';
  941. pageSetHtml += '<label class="layui-form-label sm">选择风格</label>';
  942. pageSetHtml += '<div class="layui-input-block">';
  943. pageSetHtml += '<div v-if="global.navStyle" class="text-color selected-style" @click="selectPageStyle()">风格{{global.navStyle}} <i class="layui-icon layui-icon-right"></i></div>';
  944. pageSetHtml += '<div v-else class="text-color selected-style" @click="selectPageStyle()">选择 <i class="layui-icon layui-icon-right"></i></div>';
  945. pageSetHtml += '</div>';
  946. pageSetHtml += '</div>';
  947. pageSetHtml += '<div class="layui-form-item" v-if="global.navStyle == 3 || global.navStyle == 2">';
  948. pageSetHtml += '<label class="layui-form-label sm">图片</label>';
  949. pageSetHtml += '<div class="layui-input-block img-upload" v-if="globalLazyLoad">';
  950. pageSetHtml += '<img-upload :data="{ data : global, field : \'topNavImg\', text: \'\',isShow:true }"></img-upload>';
  951. pageSetHtml += '</div>';
  952. pageSetHtml += '</div>';
  953. pageSetHtml += '<div class="word-aux diy-word-aux" v-if="global.navStyle == 2">宽度自适应(最大150px),高度28px</div>';
  954. pageSetHtml += '<div class="word-aux diy-word-aux" v-if="global.navStyle == 3">宽度自适应(85px),高度30px</div>';
  955. pageSetHtml += '<template v-if="globalLazyLoad">';
  956. pageSetHtml += '<nc-link :data="{ field : global.moreLink }"></nc-link>';
  957. pageSetHtml += '</template>';
  958. pageSetHtml += '<div class="layui-form-item icon-radio" v-if="global.navStyle == 1">';
  959. pageSetHtml += '<label class="layui-form-label sm">展示位置</label>';
  960. pageSetHtml += '<div class="layui-input-block">';
  961. pageSetHtml += '<template v-for="(item, index) in textImgPositionList">';
  962. pageSetHtml += '<span :class="{\'layui-hide\':item.value != global.textImgPosLink}">{{item.text}}</span>';
  963. pageSetHtml += '</template>';
  964. pageSetHtml += '<ul class="icon-wrap">';
  965. pageSetHtml += '<li v-for="(item, index) in textImgPositionList" :class="{\'text-color border-color\':item.value == global.textImgPosLink}" @click="global.textImgPosLink = item.value">';
  966. pageSetHtml += '<i class="iconfont" :class="[item.src]"></i>';
  967. pageSetHtml += '</li>';
  968. pageSetHtml += '</ul>';
  969. pageSetHtml += '</div>';
  970. pageSetHtml += '</div>';
  971. pageSetHtml += '<div class="layui-form-item checkbox-wrap">';
  972. pageSetHtml += '<label class="layui-form-label sm">导航栏</label>';
  973. pageSetHtml += '<div class="layui-input-block">';
  974. pageSetHtml += '<span v-if="global.navBarSwitch == true">显示</span>';
  975. pageSetHtml += '<span v-else>隐藏</span>';
  976. pageSetHtml += '<div v-if="global.navBarSwitch == true" @click="global.navBarSwitch = false" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  977. pageSetHtml += '<div v-else @click="global.navBarSwitch = true" class="layui-unselect layui-form-checkbox" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  978. pageSetHtml += '</div>';
  979. pageSetHtml += '<div class="word-aux diy-word-aux">此处控制当前页面导航栏是否显示</div>';
  980. pageSetHtml += '</div>';
  981. pageSetHtml += '</div>';
  982. pageSetHtml += '<div class="template-edit-title">';
  983. pageSetHtml += '<h3>底部导航</h3>';
  984. pageSetHtml += '<div class="layui-form-item checkbox-wrap">';
  985. pageSetHtml += '<label class="layui-form-label sm">底部导航</label>';
  986. pageSetHtml += '<div class="layui-input-block">';
  987. pageSetHtml += '<span v-if="global.openBottomNav == true">显示</span>';
  988. pageSetHtml += '<span v-else>隐藏</span>';
  989. pageSetHtml += '<div v-if="global.openBottomNav == true" @click="global.openBottomNav = false" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  990. pageSetHtml += '<div v-else @click="global.openBottomNav = true" class="layui-unselect layui-form-checkbox" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  991. pageSetHtml += '</div>';
  992. pageSetHtml += '<div class="word-aux diy-word-aux">此处控制当前页面底部导航菜单是否显示</div>';
  993. pageSetHtml += '</div>';
  994. pageSetHtml += '</div>';
  995. pageSetHtml += '</div>';
  996. pageSetHtml += '<div class="edit-style-wrap" style="display: none;">';
  997. pageSetHtml += '<div class="template-edit-title">';
  998. pageSetHtml += '<h3>显示样式</h3>';
  999. pageSetHtml += '<template v-if="globalLazyLoad">';
  1000. pageSetHtml += '<color :data="{ field : \'pageBgColor\', label : \'页面颜色\', value : global.pageBgColor, defaultColor : \'#FFFFFF\', parent: \'global\' }"></color>';
  1001. pageSetHtml += '<color :data="{ field : \'topNavColor\', label : \'顶部颜色\', value : global.topNavColor, defaultColor : \'#FFFFFF\', parent: \'global\' }"></color>';
  1002. pageSetHtml += '<color :data="{ field : \'textNavColor\', label : \'标题颜色\', value : global.textNavColor, defaultColor : \'#303133\', parent: \'global\' }"></color>';
  1003. pageSetHtml += '</template>';
  1004. pageSetHtml += '<div class="layui-form-item checkbox-wrap">';
  1005. pageSetHtml += '<label class="layui-form-label sm">顶部透明</label>';
  1006. pageSetHtml += '<div class="layui-input-block">';
  1007. pageSetHtml += '<span v-if="global.topNavBg == true">是</span>';
  1008. pageSetHtml += '<span v-else>否</span>';
  1009. pageSetHtml += '<div v-if="global.topNavBg == true" @click="global.topNavBg = false" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  1010. pageSetHtml += '<div v-else @click="global.topNavBg = true" class="layui-unselect layui-form-checkbox" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  1011. pageSetHtml += '</div>';
  1012. pageSetHtml += '</div>';
  1013. pageSetHtml += '<div class="layui-form-item">';
  1014. pageSetHtml += '<label class="layui-form-label sm">背景图片</label>';
  1015. pageSetHtml += '<div class="layui-input-block img-upload" v-if="globalLazyLoad">';
  1016. pageSetHtml += '<img-upload :data="{ data : global, field : \'bgUrl\', text: \'\', isShow:true }"></img-upload>';
  1017. pageSetHtml += '</div>';
  1018. pageSetHtml += '</div>';
  1019. pageSetHtml += '</div>';
  1020. pageSetHtml += '<div class="template-edit-title">';
  1021. pageSetHtml += '<h3>边距设置</h3>';
  1022. pageSetHtml += '<template v-if="globalLazyLoad">';
  1023. pageSetHtml += '<slide :data="{ field : \'margin.both\', label : \'左右边距\', parent: \'template\', max : 20 }"></slide>';
  1024. pageSetHtml += '</template>';
  1025. pageSetHtml += '</div>';
  1026. pageSetHtml += '</div>';
  1027. // pageSetHtml += '<div class="template-edit-title">';
  1028. // pageSetHtml += '<h3>小程序收藏</h3>';
  1029. // pageSetHtml += '</div>';
  1030. //
  1031. // pageSetHtml += '<div class="template-edit-wrap">';
  1032. // pageSetHtml += '<div class="layui-form-item checkbox-wrap">';
  1033. // pageSetHtml += '<label class="layui-form-label sm">显示状态</label>';
  1034. // pageSetHtml += '<div class="layui-input-block">';
  1035. // pageSetHtml += '<span v-if="global.mpCollect == true">显示</span>';
  1036. // pageSetHtml += '<span v-else>隐藏</span>';
  1037. // pageSetHtml += '<div v-if="global.mpCollect == true" @click="global.mpCollect = false" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  1038. // pageSetHtml += '<div v-else @click="global.mpCollect = true" class="layui-unselect layui-form-checkbox" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>';
  1039. // pageSetHtml += '</div>';
  1040. // pageSetHtml += '<div class="word-aux diy-word-aux">首次进入小程序是否显示添加小程序提示</div>';
  1041. // pageSetHtml += '</div>';
  1042. // pageSetHtml += '</div>';
  1043. pageSetHtml += '</div>';
  1044. pageSetHtml += '</div>';
  1045. pageSetHtml += '</div>';
  1046. /**
  1047. * 页面设置组件
  1048. */
  1049. Vue.component("page-set", {
  1050. template: pageSetHtml,
  1051. props: ['currentIndex', 'global','globalLazyLoad'],
  1052. data: function () {
  1053. return {
  1054. data: this.$parent.data,
  1055. appModule: ns.appModule,
  1056. templateType: $("#template_type").val(),
  1057. textImgPositionList: [
  1058. {
  1059. text: "居左",
  1060. value: "left",
  1061. src: "iconzuoduiqi"
  1062. },
  1063. {
  1064. text: "居中",
  1065. value: "center",
  1066. src: "iconjuzhongduiqi"
  1067. }
  1068. ],
  1069. angleList: [
  1070. {
  1071. text: "直角",
  1072. value: "right",
  1073. src: 'icongl-square'
  1074. },
  1075. {
  1076. text: "圆角",
  1077. value: "round",
  1078. src: 'iconyuanjiao'
  1079. }
  1080. ],
  1081. }
  1082. },
  1083. created: function () {
  1084. },
  1085. methods: {
  1086. //选择页面顶部风格,默认文字、图片+文字、图片+搜索框、定位门店
  1087. selectPageStyle: function () {
  1088. var html = '<div class="nav-style">';
  1089. for (var i = 0; i < 3; i++) {
  1090. html += '<div class="text-title' + ((this.global.navStyle == (i + 1)) ? ' border-color' : '') + '" data-style="' + (i + 1) + '">';
  1091. html += '<img src="' + ns_url.staticExt + '/diyview/img/nav_style/nav_style' + i + '.png"/>';
  1092. html += '</div>';
  1093. }
  1094. // 门店插件存在则显示
  1095. if(storeIsExit == 1) {
  1096. html += '<div class="text-title' + ((this.global.navStyle == 4) ? ' border-color' : '') + '" data-style="4">';
  1097. html += '<img src="' + ns_url.staticExt + '/diyview/img/nav_style/nav_style_store.png"/>';
  1098. html += '</div>';
  1099. }
  1100. html += '</div>';
  1101. layer.open({
  1102. type: 1,
  1103. title: '风格选择',
  1104. area: ['800px', '380px'],
  1105. btn: ['确定', '返回'],
  1106. content: html,
  1107. success: function (layero, index) {
  1108. $('.nav-style .text-title').click(function () {
  1109. $(this).addClass('border-color').siblings().removeClass('border-color');
  1110. });
  1111. },
  1112. yes: function (index, layero) {
  1113. changeStyle($('.nav-style .text-title.border-color').attr('data-style'));
  1114. layer.closeAll();
  1115. }
  1116. });
  1117. }
  1118. }
  1119. });
  1120. //导航样式切换
  1121. function changeStyle(val) {
  1122. $('.text-title:nth-child(' + (val) + ')').addClass('border-color').siblings().removeClass('border-color');
  1123. vue.global.navStyle = val;
  1124. // if (val == 4) vue.global.topNavColor = '#FF6A00';
  1125. // vue.$forceUpdate()
  1126. }
  1127. var tabbarHtml = '<div :class="[\'nav-tabbar\',\'style-\' + global.navStyle,global.textImgPosLink]">';
  1128. tabbarHtml += '<div v-if="global.navStyle == 1" class="preview-head-div" :style="{ backgroundColor : global.topNavColor,color:global.textNavColor,textAlign:global.textImgPosLink}">';
  1129. tabbarHtml += '<span>{{global.title}}</span>';
  1130. tabbarHtml += '</div>';
  1131. tabbarHtml += '<div v-if="global.navStyle == 2" class="preview-head-div" :style="{ backgroundColor : global.topNavColor,color:global.textNavColor}">';
  1132. tabbarHtml += '<img :src="changeImgUrl(global.topNavImg)">';
  1133. tabbarHtml += '<span>{{global.title}}</span>';
  1134. tabbarHtml += '</div>';
  1135. tabbarHtml += '<div v-if="global.navStyle == 3" class="preview-head-div" :style="{ backgroundColor : global.topNavColor,color:global.textNavColor}">';
  1136. tabbarHtml += '<div class="img-text-search">';
  1137. tabbarHtml += '<img :src="changeImgUrl(global.topNavImg)">';
  1138. tabbarHtml += '<div class="top-search-box">';
  1139. tabbarHtml += '<i class="iconfont iconsousuo"></i><span style="line-height: 1">请输入商品名称</span>';
  1140. tabbarHtml += '</div>';
  1141. tabbarHtml += '</div>';
  1142. tabbarHtml += '</div>';
  1143. tabbarHtml += '<div v-if="global.navStyle == 4" class="preview-head-div" :style="{ backgroundColor : global.topNavColor,color:global.textNavColor}">';
  1144. tabbarHtml += '<i class="iconfont icondingwei"></i>';
  1145. tabbarHtml += '<span class="store-name">门店名称</span>';
  1146. tabbarHtml += '<i class="iconfont iconyoujiantou"></i>';
  1147. tabbarHtml += '<div class="nearby-store-name"><span>附近门店</span></div>';
  1148. tabbarHtml += '</div>';
  1149. tabbarHtml += '</div>';
  1150. /**
  1151. * 顶部tabbar组件
  1152. */
  1153. Vue.component("tabbar", {
  1154. template: tabbarHtml,
  1155. props: ['global'],
  1156. data: function () {
  1157. return {}
  1158. },
  1159. created: function () {},
  1160. methods: {
  1161. //转换图片路径
  1162. changeImgUrl: function (url) {
  1163. if (url == null || url === "") return '';
  1164. if (url.indexOf("static/img/") > -1) return ns.img(ns_url.staticImg + "/" + url.replace("public/static/img/", ""));
  1165. else return ns.img(url);
  1166. },
  1167. }
  1168. });
  1169. //[Icon组件]属性组件
  1170. var iconHtml = '<div class="layui-form-item component-icon">';
  1171. iconHtml += '<label class="layui-form-label sm">{{data.label || "图标"}}</label>';
  1172. iconHtml += '<div class="layui-input-block">';
  1173. iconHtml += '<span class="sm" @click="selected()"><i :class="[\'text-color\',{\'iconfont iconjia\': !parent[data.field] },{\'js-icon\': parent[data.field]},parent[data.field]]" :style="{\'color\': parent[data.field] && parent[data.color] + \'!important\'}"></i></span>';
  1174. iconHtml += '</div>';
  1175. iconHtml += '</div>';
  1176. /**
  1177. * 选择Icon组件:
  1178. * 参数说明:data:链接对象,callback:回调
  1179. */
  1180. Vue.component("nc-icon", {
  1181. props: {
  1182. data: {
  1183. type: Object,
  1184. default: function () {
  1185. return {
  1186. field: null,// icon对象
  1187. label: "图标",// 文本
  1188. color: "" // 图标颜色
  1189. };
  1190. }
  1191. }
  1192. },
  1193. template: iconHtml,
  1194. data: function () {
  1195. return {
  1196. parent: (Object.keys(this.$parent.data).length) ? this.$parent.data : this.$parent.global
  1197. };
  1198. },
  1199. created: function () {
  1200. // 找寻父级
  1201. if (typeof this.data.parent == "string") this.parent = this.$parent.data[this.data.parent];
  1202. if (typeof this.data.parent == "object") this.parent = this.data.parent;
  1203. },
  1204. methods: {
  1205. selected: function () {
  1206. iconSelect((data)=>{
  1207. this.parent[this.data.field] = data;
  1208. },{icon: this.parent[this.data.field]})
  1209. }
  1210. }
  1211. });