szycompontents.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. // 系统内置属性组件
  2. var resourceHtml = '<div v-show="false"><slot></slot></div>';
  3. //CSS·组件
  4. Vue.component("css", {
  5. props: ["src"],
  6. template: resourceHtml,
  7. created: function () {
  8. var self = this;
  9. //内联样式
  10. if (this.$slots.default) {
  11. var css = "<style>" + this.$slots.default[0].text + '</style>';
  12. //防止重复加载资源
  13. if ($("head").html().indexOf(css) == -1) {
  14. $("head").append(css);
  15. }
  16. //延迟
  17. setTimeout(function () {
  18. self.$parent.data.lazyLoadCss = true;
  19. }, 10);
  20. }
  21. //外联样式
  22. if (this.src) {
  23. //防止重复加载资源
  24. if ($("head").html().indexOf(this.src) == -1) {
  25. var styleNode = createLink(this.src);
  26. styleOnload(styleNode, function () {
  27. self.$parent.data.lazyLoadCss = true;
  28. });
  29. } else {
  30. //延迟
  31. setTimeout(function () {
  32. self.$parent.data.lazyLoadCss = true;
  33. }, 10);
  34. }
  35. }
  36. }
  37. });
  38. //JavaScript脚本·组件
  39. Vue.component("js", {
  40. props: ["src"],
  41. template: resourceHtml,
  42. created: function () {
  43. var self = this;
  44. //如果JS全部是内部代码,则延迟10毫秒
  45. //如果JS有内部代码、也有外部JS,则以外部JS加载完成时间为准,同时延迟10毫秒,让外部JS中的组件进行加载
  46. //如果JS全部是外部代码,则以外部JS加载完成时间为准,同时延迟10毫秒,让外部JS中的组件进行加载
  47. //内联js
  48. if (this.$slots.default) {
  49. var script = "<script>" + this.$slots.default[0].text + "</script>";
  50. $("body").append(script);
  51. //如果有外部JS,则以外部JS加载完成时间为准
  52. if (this.$parent.data.outerCountJs == 0) {
  53. setTimeout(function () {
  54. self.$parent.data.lazyLoad = true;
  55. }, 10);
  56. }
  57. }
  58. //外联js
  59. if (this.src) {
  60. $.getScript(this.src, function (res) {
  61. setTimeout(function () {
  62. self.$parent.data.lazyLoad = true;
  63. }, 10);
  64. });
  65. }
  66. }
  67. });
  68. //[颜色]属性组件
  69. var colorHtml = '<div class="layui-form-item flex">';
  70. colorHtml += '<div class="flex_left">';
  71. colorHtml += '<label class="layui-form-label sm">{{d.label}}</label>';
  72. colorHtml += '<div class="curr_color">{{parent[d.field]}}</div>';
  73. colorHtml += '</div>';
  74. colorHtml += '<div class="layui-input-block flex_fill">';
  75. colorHtml += '<span class="color-selector-reset" v-on:click="reset()">重置</span>';
  76. colorHtml += '<div v-bind:id="class_name" class="picker colorSelector"><div v-bind:style="{ background : parent[d.field] }"></div></div>';
  77. // colorHtml += '<div v-bind:id="class_name" v-bind:class="class_name" class="colorSelector"><div v-bind:style="{ background : parent[d.field] }"></div></div>';
  78. colorHtml += '</div>';
  79. colorHtml += '</div>';
  80. /**
  81. * 颜色组件:
  82. * 参数说明:
  83. * data:{ field : 字段名, value : 值(默认:#333333), 'label' : 文本标签(默认:文字颜色) }
  84. */
  85. Vue.component("color", {
  86. props: {
  87. data: {
  88. type: Object,
  89. default: function () {
  90. return {
  91. field: "textColor",
  92. label: "文字颜色",
  93. defaultcolor: ""
  94. };
  95. }
  96. },
  97. },
  98. data: function () {
  99. return {
  100. d: this.data,
  101. class_name: "",
  102. parent: (Object.keys(this.$parent.data).length) ? this.$parent.data : this.$parent.global,
  103. };
  104. },
  105. created: function () {
  106. this.bindColor();
  107. },
  108. watch:{
  109. },
  110. methods: {
  111. init:function(){
  112. if (this.data.field == undefined) this.data.field = "textColor";
  113. if (this.data.label == undefined) this.data.label = "文字颜色";
  114. if (this.data.value == undefined) this.data.value = "#333333";
  115. if (this.data.defaultcolor == undefined) this.data.defaultcolor = "";
  116. if (this.data.defaultvalue == undefined) this.data.defaultvalue = "";
  117. if(this.data.global == 1) this.parent = this.$parent.global;
  118. if (this.parent[this.data.field] == undefined) this.$set(this.parent, this.data.field, this.data.value);
  119. else this.data.value = this.parent[this.data.field];
  120. this.parent[this.data.field] = this.data.value;
  121. this.d = this.data;
  122. },
  123. reset: function () {
  124. try {
  125. if(this.data.global == 1) this.parent = this.$parent.global;
  126. this.parent[this.d.field] = this.d.defaultcolor;
  127. } catch (e) {
  128. console.log("color reset() ERROR:" + e.message);
  129. }
  130. },
  131. bindColor() {
  132. this.init();
  133. this.class_name = "colorSelector_" + (this.data.field ? this.data.field : "textColor") + get_math_rant(10);
  134. var class_name = "." + this.class_name;
  135. var $self = this;
  136. setColorPicker($self.data.value, this.class_name, function (hex) {
  137. try {
  138. if(hex) {
  139. $self.parent[$self.d.field] = hex;
  140. } else {
  141. $self.parent[$self.d.field] = "";
  142. }
  143. } catch (e) {
  144. console.log("color ERROR:" + e.message);
  145. }
  146. });
  147. },
  148. refreshData(){
  149. // 刷新parent、data
  150. // console.log("this.parent",this.parent);
  151. if(this.parent.controller && this.parent.controller != vue.data[vue.currentIndex].controller){
  152. // 数据发送变动
  153. this.parent = vue.data[vue.currentIndex];
  154. this.init();
  155. // console.log("数据发送变动",this.d);
  156. }
  157. return this.parent;
  158. }
  159. },
  160. template: colorHtml
  161. });
  162. /**
  163. * 生成颜色选择器
  164. * @param defaultColor
  165. * @param obj
  166. * @param callBack
  167. */
  168. function setColorPicker(defaultColor, name, callBack) {
  169. setTimeout(function () {
  170. var obj = document.getElementById("picker");
  171. var a = Colorpicker.create({
  172. el: name,
  173. color: defaultColor,
  174. change: function (elem, hex) {
  175. $(elem).find("div").css('background', hex);
  176. if (callBack) callBack(hex);
  177. }
  178. });
  179. if(defaultColor) $("#" + name).find("div").css('background', defaultColor);
  180. }, 500);
  181. }
  182. //[图片上传]组件
  183. var imageSecHtml = '<div @click="showImageDialog(this)" v-show="condition" class="img-block layui-form ns-text-color" :id="id" v-bind:class="{ \'has-choose-image\' : (myData.data[myData.field]) }">';
  184. imageSecHtml += '<div>';
  185. imageSecHtml += '<template v-if="myData.data[myData.field]">';
  186. imageSecHtml += '<img v-bind:src="changeImgUrl(myData.data[myData.field])" />';
  187. imageSecHtml += '<span>更换图片</span>';
  188. // imageSecHtml += '<i class="del" v-on:click.stop="del()" data-disabled="1" v-if = "isShow == true">x</i>';
  189. imageSecHtml += '</template>';
  190. imageSecHtml += '<template v-else>';
  191. imageSecHtml += '<i class="add">+</i>';
  192. // imageSecHtml += '<i class="del" v-on:click.stop="del()" data-disabled="1">x</i>';
  193. imageSecHtml += '</template>';
  194. imageSecHtml += '</div>';
  195. imageSecHtml += '</div>';
  196. /**
  197. * 图片上传
  198. * 参数说明:
  199. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) }
  200. */
  201. Vue.component("img-sec-upload", {
  202. template: imageSecHtml,
  203. props: {
  204. data: {
  205. type: Object,
  206. default: function () {
  207. return {
  208. data: {},
  209. field: "imageUrl",
  210. callback: null,
  211. text: "添加图片"
  212. };
  213. }
  214. },
  215. condition: {
  216. type: Boolean,
  217. default: true
  218. },
  219. currIndex: {
  220. type: Number,
  221. default: 0
  222. },
  223. isShow:{
  224. type: Boolean,
  225. default: true
  226. }
  227. },
  228. data: function () {
  229. return {
  230. myData: this.data,
  231. upload : null,
  232. id : get_math_rant(10),
  233. // parent: (Object.keys(this.$parent.data).length) ? this.$parent.data : this.data,
  234. };
  235. },
  236. watch: {
  237. data: function (val, oldVal) {
  238. if (val.field == undefined) val.field = oldVal.field;
  239. if (val.text == undefined) val.text = "添加图片";
  240. this.myData = val;
  241. }
  242. },
  243. created: function () {
  244. if (this.data.field == undefined) this.data.field = "imageUrl";
  245. if (this.data.data[this.data.field] == undefined) this.$set(this.data.data, this.data.field, "");
  246. if (this.data.text == undefined) this.data.text = "添加图片";
  247. this.id = get_math_rant(10);
  248. },
  249. methods: {
  250. del: function () {
  251. // console.log(this.$parent.list)
  252. // this.$parent.list.splice(this.currIndex,1)
  253. this.data.data[this.data.field] = "";
  254. },
  255. //转换图片路径
  256. changeImgUrl: function (url) {
  257. if (url == null || url == "") return '';
  258. else return url;
  259. },
  260. showImageDialog: function(elm, options) {
  261. var self = this;
  262. var ipt = $(elm).prev();
  263. var val = ipt.val();
  264. require(["util"], function (util) {
  265. options = {
  266. 'class_extra': 'order_menu_icon',
  267. 'global': false,
  268. 'direct': true,
  269. 'multiple': false,
  270. 'fileSizeLimit': 10240
  271. };
  272. util.image(val, function (url) {
  273. if (url.url) {
  274. self.data.data[self.data.field] = url.url;
  275. }
  276. }, options);
  277. })
  278. }
  279. }
  280. });
  281. //滑块属性组件 用于间距等
  282. var sliderHtml = '<div class="layui-form-item slide-component">';
  283. sliderHtml += '<label class="layui-form-label sm">{{data.label}}</label>';
  284. sliderHtml += '<div class="layui-input-block">';
  285. sliderHtml += '<div v-bind:id="id" class="side-process"></div>';
  286. sliderHtml += '<span class="slide-prompt-text">{{parent[data.field]}}</span>';
  287. sliderHtml += '</div>';
  288. sliderHtml += '</div>';
  289. Vue.component("slide", {
  290. props: {
  291. data: {
  292. type: Object,
  293. default: function () {
  294. return {
  295. field: "height",
  296. label: "空白高度",
  297. max: 100,
  298. min: 0
  299. };
  300. }
  301. }
  302. },
  303. created: function () {
  304. if (this.data.label == undefined) this.data.label = "空白高度";
  305. if (this.data.field == undefined) this.data.field = "height";
  306. if (this.data.max == undefined) this.data.max = 100;
  307. if (this.data.min == undefined) this.data.min = 0;
  308. var _self = this;
  309. setTimeout(function () {
  310. layui.use('slider', function(){
  311. var slider = layui.slider;
  312. var ins = slider.render({
  313. elem: '#'+_self.id,
  314. max: _self.data.max,
  315. min: _self.data.min,
  316. tips: false,
  317. theme: '#FF6A00',
  318. value : _self.parent[_self.data.field],
  319. change: function(value){
  320. _self.parent[_self.data.field] = value;
  321. }
  322. });
  323. });
  324. },10);
  325. },
  326. watch: {
  327. data: function (val, oldVal) {
  328. if (val.field == undefined) val.field = oldVal.field;
  329. if (val.label == undefined) val.label = "空白高度";
  330. if (val.max == undefined) val.max = 100;
  331. if (val.min == undefined) val.min = 0;
  332. },
  333. },
  334. template: sliderHtml,
  335. data: function () {
  336. return {
  337. id : "slide_" + get_math_rant(10),
  338. parent: this.$parent.data,
  339. };
  340. }
  341. });
  342. //链接属性组件
  343. var linkHtml = '<div class="layui-form-item component-links">';
  344. linkHtml += '<label class="layui-form-label sm">{{myData[0].label}}</label>';
  345. linkHtml += '<div class="layui-input-block">';
  346. linkHtml += '<span style="display: none;" v-if="myData[0].field.title" v-bind:title="myData[0].field.title"></span>';
  347. linkHtml += '<span v-if="myData[0].field.title" v-for="(item,index) in myData[0].operation" class="sm ns-text-color" v-on:click="selected(item.key,item.method)"><span :title="myData[0].field.title">{{myData[0].field.title}}</span><i class="layui-icon layui-icon-right"></i></span>';
  348. linkHtml += '<span v-else v-for="(item,index) in myData[0].operation" class="sm" style="color: #323233;" v-on:click="selected(item.key,item.method)"><span :title="item.label">{{item.label}}</span><i class="layui-icon layui-icon-right"></i></span>';
  349. linkHtml += '</div>';
  350. linkHtml += '</div>';
  351. /**
  352. * 链接组件:
  353. * 参数说明:data:当前链接对象, click:绑定事件,触发回调
  354. */
  355. Vue.component("sel-link", {
  356. //data:链接对象,callback:回调,refresh:刷新filed
  357. props: {
  358. data: {
  359. type: Object,
  360. default: function () {
  361. return {
  362. //链接对象
  363. field: null,
  364. //文本
  365. label: "链接地址",
  366. //批量操作对象
  367. operation: [
  368. {key: "system", method: '', label: "请选择链接"}
  369. ],
  370. supportDiyView: "",
  371. supportToApplet: 1
  372. };
  373. }
  374. },
  375. callback: null,
  376. refresh: null,
  377. },
  378. template: linkHtml,
  379. data: function () {
  380. return {
  381. myData: [this.data],//此处用数组的目的是触发变异方法,进行视图更新
  382. };
  383. },
  384. created: function () {
  385. if (this.data.supportToApplet == undefined) this.data.supportToApplet = 1;
  386. if (this.data.supportDiyView == undefined) this.data.supportDiyView = "";
  387. if (this.data.label == undefined) this.data.label = "链接地址";
  388. if (this.data.operation == undefined) this.data.operation = [{ key : "system", method : '' , label: "请选择链接" }];
  389. },
  390. watch: {
  391. data: function (val, oldVal) {
  392. if (this.data.supportDiyView == undefined) this.data.supportDiyView = "";
  393. if (this.data.label == undefined) this.data.label = "链接地址";
  394. if (this.data.operation == undefined) this.data.operation = [{ key : "system", method : '' , label: "请选择链接" }];
  395. this.myData[0].field= this.data.field;
  396. },
  397. refresh:function (val,oldVal) {
  398. this.myData[0].field = val;
  399. this.set(val);
  400. }
  401. },
  402. methods: {
  403. //设置链接地址
  404. set: function (link) {
  405. //由于Vue2.0是单向绑定的:子组件无法修改父组件,但是可以修改单个属性,循环遍历属性赋值
  406. if (this.data.field) {
  407. for (var k in link) {
  408. this.data.field[k] = link[k];
  409. }
  410. }
  411. //触发变异方法,进行视图更新
  412. this.myData.push({});
  413. this.myData.pop();
  414. },
  415. selected: function (key,method) {
  416. var $self = this;
  417. if(key == "system") {
  418. //系统链接
  419. select_link($self.myData[0].field,$self.myData[0].supportDiyView, function (data) {
  420. $self.set(data);
  421. if ($self.callback) $self.callback.call(this, data);
  422. }, $self.data.supportToApplet);
  423. }else {
  424. //插件自定义链接
  425. ns[method]($self.myData[0].field, $self.myData[0].supportDiyView, function (data) {
  426. $self.set(data);
  427. if ($self.callback) $self.callback.call(this, data);
  428. }, $self.data.supportToApplet);
  429. }
  430. }
  431. }
  432. });
  433. //[视频上传]组件
  434. var videoSecHtml = '<div @click="showVideoDialog(this)" v-show="condition" class="img-block layui-form ns-text-color" :id="id" v-bind:class="{ \'has-choose-image\' : (myData.data[myData.field]) }">';
  435. videoSecHtml += '<div>';
  436. videoSecHtml += '<template v-if="myData.data[myData.field]">';
  437. videoSecHtml += '<video v-bind:src="changeVideoUrl(myData.data[myData.field])" style="width: 55px;height: 55px;" />';
  438. videoSecHtml += '<span>更换视频</span>';
  439. videoSecHtml += '<i class="del" v-on:click.stop="del()" data-disabled="1" v-if = "isShow == true">x</i>';
  440. videoSecHtml += '</template>';
  441. videoSecHtml += '<template v-else>';
  442. videoSecHtml += '<i class="add">+</i>';
  443. videoSecHtml += '<i class="del" v-on:click.stop="del()" data-disabled="1">x</i>';
  444. videoSecHtml += '</template>';
  445. videoSecHtml += '</div>';
  446. videoSecHtml += '</div>';
  447. /**
  448. * 视频上传
  449. * 参数说明:
  450. * data:{ field : 字段名, value : 值(默认:14), 'label' : 文本标签(默认:文字大小) }
  451. */
  452. Vue.component("video-upload", {
  453. template: videoSecHtml,
  454. props: {
  455. data: {
  456. type: Object,
  457. default: function () {
  458. return {
  459. data: {},
  460. field: "videoUrl",
  461. callback: null,
  462. text: "添加视频"
  463. };
  464. }
  465. },
  466. condition: {
  467. type: Boolean,
  468. default: true
  469. },
  470. currIndex: {
  471. type: Number,
  472. default: 0
  473. },
  474. isShow:{
  475. type: Boolean,
  476. default: true
  477. }
  478. },
  479. data: function () {
  480. return {
  481. myData: this.data,
  482. upload : null,
  483. id : get_math_rant(10),
  484. };
  485. },
  486. watch: {
  487. data: function (val, oldVal) {
  488. if (val.field == undefined) val.field = oldVal.field;
  489. if (val.text == undefined) val.text = "添加视频";
  490. this.myData = val;
  491. }
  492. },
  493. created: function () {
  494. if (this.data.field == undefined) this.data.field = "videoUrl";
  495. if (this.data.data[this.data.field] == undefined) this.$set(this.data.data, this.data.field, "");
  496. if (this.data.text == undefined) this.data.text = "添加视频";
  497. this.id = get_math_rant(10);
  498. },
  499. methods: {
  500. del: function () {
  501. this.data.data[this.data.field] = "";
  502. },
  503. //转换图片路径
  504. changeVideoUrl: function (url) {
  505. if (url == null || url == "") return '';
  506. else return url;
  507. },
  508. showVideoDialog: function(elm, options) {
  509. var self = this;
  510. var ipt = $(elm).prev();
  511. var val = ipt.val();
  512. require(["util"], function (util) {
  513. options = { type: 'video' };
  514. util.audio(val, function (url) {
  515. if (url.url) {
  516. self.data.data[self.data.field] = url.url;
  517. }
  518. }, options);
  519. })
  520. }
  521. }
  522. });