product.js 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. //加载Vue 主要用作规格
  2. require.config({
  3. paths: {
  4. "vue": "../addons/unishop/js/vue",
  5. //"vue": "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue",
  6. }
  7. });
  8. define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload', 'vue'], function ($, undefined, Backend, Table, Form, Upload, Vue) {
  9. // 规格模板
  10. //使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象
  11. var specComponent = Vue.extend({
  12. template: '<div>' +
  13. ' <div style="display: none" class="form-group">\n' +
  14. ' <label class="control-label col-xs-12 col-sm-2">' + __('use_spec') + '</label>\n' +
  15. ' <div class="col-xs-12 col-sm-8">\n' +
  16. ' <input type="radio" name="row[use_spec]" value="0" v-model="use_spec"/>否\n' +
  17. ' <input type="radio" name="row[use_spec]" value="1" v-model="use_spec"/>是\n' +
  18. ' </div>\n' +
  19. ' </div>\n' +
  20. '\n' +
  21. ' <div class="form-group" v-if="use_spec == 1">\n' +
  22. ' <label class="control-label col-xs-12 col-sm-2">' + __('Spec') + '</label>\n' +
  23. ' <div class="col-xs-12 col-sm-8">\n' +
  24. ' <input id="c-specList" type="hidden" name="row[specList]" v-model="specListJSON"/>\n' +
  25. ' <input id="c-specTableList" type="hidden" name="row[specTableList]" v-model="specTableListJSON"/>\n' +
  26. '\n' +
  27. ' <table class="table table-hover">\n' +
  28. ' <thead>\n' +
  29. ' <tr>\n' +
  30. ' <th class="col-sm-4">\n' +
  31. ' <a href="javascript:;" class="btn btn-success btn-add" title="添加" data-toggle="modal"\n' +
  32. ' data-target="#addSpec"><i class="fa fa-plus"></i> 添加属性</a>\n' +
  33. ' <!-- 输入规格名称 -->\n' +
  34. ' <div class="modal fade" id="addSpec" tabindex="-1" role="dialog">\n' +
  35. ' <div class="modal-dialog modal-sm" role="document">\n' +
  36. ' <div class="modal-content">\n' +
  37. ' <div class="modal-body">\n' +
  38. ' <label>输入规格名称</label>\n' +
  39. ' <input type="text" class="form-control" v-model="specName">\n' +
  40. ' </div>\n' +
  41. ' <div class="modal-footer">\n' +
  42. ' <button type="button" class="btn btn-default" data-dismiss="modal">\n' +
  43. __('Close') +
  44. ' </button>\n' +
  45. ' <button type="button" class="btn btn-primary" data-dismiss="modal"\n' +
  46. ' v-on:click="addSpecList">' + __('Add') + '\n' +
  47. ' </button>\n' +
  48. ' </div>\n' +
  49. ' </div>\n' +
  50. ' </div>\n' +
  51. ' </div>\n' +
  52. ' <!-- 输入规格值 -->\n' +
  53. ' <div class="modal fade" id="addSpecValue" tabindex="-1" role="dialog">\n' +
  54. ' <div class="modal-dialog modal-sm" role="document">\n' +
  55. ' <div class="modal-content">\n' +
  56. ' <div class="modal-body">\n' +
  57. ' <label>输入规格 {{specFatherName}} 的值</label>\n' +
  58. ' <input type="text" class="form-control" v-model="specValue">\n' +
  59. ' </div>\n' +
  60. ' <div class="modal-footer">\n' +
  61. ' <button type="button" class="btn btn-default" data-dismiss="modal">\n' +
  62. __('Close') +
  63. ' </button>\n' +
  64. ' <button type="button" class="btn btn-primary" data-dismiss="modal"\n' +
  65. ' v-on:click="addSpecChildList">' + __('Add') + '\n' +
  66. ' </button>\n' +
  67. ' </div>\n' +
  68. ' </div>\n' +
  69. ' </div>\n' +
  70. ' </div>\n' +
  71. ' <!-- 批量设置值 -->\n' +
  72. ' <div class="modal fade" id="addMultiValue" tabindex="-1" role="dialog">\n' +
  73. ' <div class="modal-dialog modal-sm" role="document">\n' +
  74. ' <div class="modal-content">\n' +
  75. ' <div class="modal-body">\n' +
  76. ' <label>批量设置 {{multiName_}} 的值</label>\n' +
  77. ' <input type="number" class="form-control" v-model="multiValue">\n' +
  78. ' </div>\n' +
  79. ' <div class="modal-footer">\n' +
  80. ' <button type="button" class="btn btn-default" data-dismiss="modal">\n' +
  81. __('Close') +
  82. ' </button>\n' +
  83. ' <button type="button" class="btn btn-primary" data-dismiss="modal"\n' +
  84. ' v-on:click="addMultiValue">' + __('Multi setting') + '\n' +
  85. ' </button>\n' +
  86. ' </div>\n' +
  87. ' </div>\n' +
  88. ' </div>\n' +
  89. ' </div>\n' +
  90. ' </th>\n' +
  91. ' <th style=" height: 50px;\n' +
  92. ' display: block;\n' +
  93. ' line-height: 36px;\n' +
  94. ' text-align: center;">\n' +
  95. __('Specchildlist') + '\n' +
  96. ' </th>\n' +
  97. ' </tr>\n' +
  98. ' </thead>\n' +
  99. ' <tbody>\n' +
  100. ' <tr v-for="(item,index) in specList">\n' +
  101. ' <td>\n' +
  102. ' <div class="input-group">\n' +
  103. ' <input type="text" class="form-control" v-model="item.name">\n' +
  104. ' <span class="input-group-btn">\n' +
  105. ' <button class="btn btn-default" type="button" v-on:click="delSpec(index)">\n' +
  106. ' <span aria-hidden="true" class="tab-danger">&times;</span>\n' +
  107. ' </button>\n' +
  108. ' </span>\n' +
  109. ' </div>\n' +
  110. ' </td>\n' +
  111. ' <td>\n' +
  112. ' <div class="input-group" v-for="(childItem, childIndex) in item.child">\n' +
  113. ' <input type="text" class="form-control" disabled v-model="item.child[childIndex]">\n' +
  114. ' <span class="input-group-btn">\n' +
  115. ' <button class="btn btn-default" type="button"\n' +
  116. ' v-on:click="delSpecChild(index,childIndex)">\n' +
  117. ' <span aria-hidden="true" class="tab-danger">&times;</span>\n' +
  118. ' </button>\n' +
  119. ' </span>\n' +
  120. ' </div>\n' +
  121. ' <a href="javascript:;" v-on:click="herFatherSpec(index)" class="btn btn-success btn-add"\n' +
  122. ' title="添加" data-toggle="modal" data-target="#addSpecValue"><i class="fa fa-plus"></i>\n' +
  123. ' 添加属性值</a>\n' +
  124. ' </td>\n' +
  125. ' </tr>\n' +
  126. ' </tbody>\n' +
  127. ' </table>\n' +
  128. ' </div>\n' +
  129. ' </div>\n' +
  130. ' <div class="form-group" v-if="use_spec == 1">\n' +
  131. ' <div class="col-xs-12 col-sm-1"></div>\n' +
  132. ' <div class="col-xs-12 col-sm-10">\n' +
  133. ' <table class="table table-bordered table-hover">\n' +
  134. ' <thead>\n' +
  135. ' <tr>\n' +
  136. ' <th>图片</th>\n' +
  137. ' <th v-for="(item) in specList" v-if="item.child.length > 0">\n' +
  138. ' <span>\n' +
  139. ' {{item.name}}\n' +
  140. ' </span>\n' +
  141. ' </th>\n' +
  142. ' <th><i class="fa fa-plus btn-success" data-toggle="modal" data-target="#addMultiValue" v-on:click="addMultiType(\'code\')"></i>' + __('Code') + '</th>\n' +
  143. ' <th><i class="fa fa-plus btn-success" data-toggle="modal" data-target="#addMultiValue" v-on:click="addMultiType(\'market_price\')"></i>' + __('Market price') + '</th>\n' +
  144. ' <th><i class="fa fa-plus btn-success" data-toggle="modal" data-target="#addMultiValue" v-on:click="addMultiType(\'sales_price\')"></i>' + __('Sales price') + '</th>\n' +
  145. ' <th><i class="fa fa-plus btn-success" data-toggle="modal" data-target="#addMultiValue" v-on:click="addMultiType(\'stock\')"></i>' + __('Stock') + '</th>\n' +
  146. ' <th><i class="fa fa-plus btn-success" data-toggle="modal" data-target="#addMultiValue" v-on:click="addMultiType(\'sales\')"></i>' + __('Sales') + '</th>\n' +
  147. ' </tr>\n' +
  148. ' </thead>\n' +
  149. ' <tbody>\n' +
  150. ' <tr v-for="(tItem,index) in specTableList">\n' +
  151. ' <td>\n' +
  152. ' <input v-bind:id="\'c-logoSpec\' + index" type="hidden" v-model="tItem.image" >\n' +
  153. '\n' +
  154. ' <button type="button" v-bind:id="\'fachoose-logoSpec\'+index" class="btn btn-primary fachoose-spec"\n' +
  155. ' v-bind:data-input-id="\'c-logoSpec\'+index" v-bind:data-preview-id="\'p-logoSpec\'+index" data-mimetype="image/*"\n' +
  156. ' data-multiple="false">' + __('Choose') +
  157. ' </button>\n' +
  158. ' <button style="display: none;" type="button" v-bind:id="\'plupload-logoSpec\'+index"\n' +
  159. ' class="btn btn-danger plupload-spec" v-bind:data-input-id="\'c-logoSpec\'+index"\n' +
  160. ' data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp"\n' +
  161. ' data-multiple="false" v-bind:data-preview-id="\'p-logoSpec\'+index">\n' +
  162. __('Upload') +
  163. ' </button>\n' +
  164. ' <ul class="row list-inline plupload-preview width100" v-bind:id="\'p-logoSpec\'+index">\n' +
  165. '\n' +
  166. ' </ul>\n' +
  167. ' </td>\n' +
  168. ' <td v-for="vItem in tItem.value">\n' +
  169. ' <input class="form-control" disabled v-bind:value="vItem" />\n' +
  170. ' </td>\n' +
  171. ' <td><input class="form-control" data-rule="required" min="0" type="number" v-model="tItem.code"></td>\n' +
  172. ' <td><input class="form-control" data-rule="required" min="0" type="number" v-model="tItem.market_price"></td>\n' +
  173. ' <td><input class="form-control" data-rule="required" min="0" type="number" v-model="tItem.sales_price"></td>\n' +
  174. ' <td><input class="form-control" data-rule="required" min="0" type="number" v-model="tItem.stock"></td>\n' +
  175. ' <td><input class="form-control" data-rule="required" min="0" type="number" v-model="tItem.sales"></td>\n' +
  176. ' </tr>\n' +
  177. ' </tbody>\n' +
  178. ' </table>\n' +
  179. ' </div>\n' +
  180. ' </div>\n' +
  181. '\n' +
  182. ' <div class="form-group">\n' +
  183. ' <label class="control-label col-xs-12 col-sm-2">' + __('Lower market price') + ':</label>\n' +
  184. ' <div class="col-xs-12 col-sm-8">\n' +
  185. ' <input id="c-market_price" data-rule="required" v-bind:readonly="use_spec == 1" class="form-control"\n' +
  186. ' name="row[market_price]" min="0" type="number" v-model="noSpecValue.market_price">\n' +
  187. ' </div>\n' +
  188. ' </div>\n' +
  189. ' <div class="form-group">\n' +
  190. ' <label class="control-label col-xs-12 col-sm-2">' + __('Lower sales price') + ':</label>\n' +
  191. ' <div class="col-xs-12 col-sm-8">\n' +
  192. ' <input id="c-sales_price" data-rule="required" v-bind:readonly="use_spec == 1" class="form-control"\n' +
  193. ' name="row[sales_price]" min="0" type="number" v-model="noSpecValue.sales_price">\n' +
  194. ' </div>\n' +
  195. ' </div>\n' +
  196. '\n' +
  197. ' <div class="form-group">\n' +
  198. ' <label class="control-label col-xs-12 col-sm-2">' + __('Total stock') + ':</label>\n' +
  199. ' <div class="col-xs-12 col-sm-8">\n' +
  200. ' <input id="c-stock" data-rule="required" v-bind:readonly="use_spec == 1" class="form-control"\n' +
  201. ' name="row[stock]" min="0" type="number" v-model="noSpecValue.stock">\n' +
  202. ' </div>\n' +
  203. ' </div>\n' +
  204. ' <div class="form-group">\n' +
  205. ' <label class="control-label col-xs-12 col-sm-2">' + __('Total sales') + ':</label>\n' +
  206. ' <div class="col-xs-12 col-sm-8">\n' +
  207. ' <input id="c-sales" data-rule="required" v-bind:readonly="use_spec == 1" class="form-control"\n' +
  208. ' name="row[sales]" min="0" type="number" v-model="noSpecValue.sales">\n' +
  209. ' </div>\n' +
  210. ' </div>\n' +
  211. '</div>\n',
  212. data() {
  213. return {
  214. specList: _specList ? _specList : '',
  215. //[ //规格列表
  216. // {
  217. // name: '尺寸',
  218. // child: ['XS']
  219. // }, {
  220. // name: '大小',
  221. // child: ['大', '小']
  222. // },
  223. //],
  224. specTableList: _specTableList ? _specTableList : '',
  225. //[
  226. // {
  227. // value: ['XS', '大'],
  228. // code: 0,
  229. // market_price: 0.00,
  230. // sales_price: 0.00,
  231. // stock: 0,
  232. // sales: 0,
  233. // image: ''
  234. // },
  235. // {
  236. // value: ['XS', '小'],
  237. // code: 0,
  238. // market_price: 0.00,
  239. // sales_price: 0.00,
  240. // stock: 0,
  241. // sales: 0,
  242. // image: ''
  243. // }
  244. //],
  245. use_spec: _use_spec ? _use_spec : 0, //是否使用
  246. specName: '', //要添加的规格健名
  247. specValue: '', //要添加的规格值
  248. specChildValue: '', //要添加的规格值
  249. specFatherIndex: 0,
  250. market_price: _market_price ? _market_price : 0.00,
  251. sales_price: _sales_price ? _sales_price : 0.00,
  252. stock: _stock ? _stock : 0,
  253. sales: _sales ? _sales : 0,
  254. multiType:'code', // 当前批量添加的类型
  255. multiValue: '', // 当前批量编辑的值
  256. multi: [{ // 批量类型数组
  257. 'type': 'code',
  258. 'name': __('Code')
  259. }, {
  260. 'type': 'market_price',
  261. 'name': __('Market price')
  262. },{
  263. 'type': 'sales_price',
  264. 'name': __('Sales price')
  265. },{
  266. 'type': 'stock',
  267. 'name': __('Stock')
  268. },{
  269. 'type': 'sales',
  270. 'name': __('Sales')
  271. }]
  272. }
  273. },
  274. computed: {
  275. specListJSON() {
  276. return JSON.stringify(this.specList);
  277. },
  278. specTableListJSON() {
  279. let data = [];
  280. // 按字母排序
  281. for (let i in this.specTableList) {
  282. let newData = {};
  283. Object.keys(this.specTableList[i]).sort().map(key => {
  284. //newData[i][key]=this.specTableList[i].key;
  285. newData[key] = this.specTableList[i][key];
  286. });
  287. data[i] = newData;
  288. }
  289. return JSON.stringify(data);
  290. },
  291. specFatherName() {
  292. return this.specList[this.specFatherIndex] ? this.specList[this.specFatherIndex].name : '';
  293. },
  294. noSpecValue() {
  295. if (this.specTableList.length > 0) {
  296. let value = this.specTableList[0];
  297. let market_price = value.market_price;
  298. let sales_price = value.sales_price;
  299. let stock = 0;
  300. let sales = 0;
  301. for (let item of this.specTableList) {
  302. market_price = parseFloat(item.market_price) < parseFloat(market_price) ? parseFloat(item.market_price) : market_price;
  303. sales_price = parseFloat(item.sales_price) < parseFloat(sales_price) ? parseFloat(item.sales_price) : sales_price;
  304. stock = parseFloat(stock) + parseFloat(item.stock);
  305. sales = parseFloat(sales) + parseFloat(item.sales);
  306. }
  307. return {market_price, sales_price, stock, sales};
  308. } else {
  309. return {
  310. market_price: this.market_price,
  311. sales_price: this.sales_price,
  312. stock: this.stock,
  313. sales: this.sales,
  314. }
  315. }
  316. },
  317. multiName_() {
  318. let res = '';
  319. for (let i in this.multi) {
  320. if (this.multi[i].type == this.multiType) {
  321. res = this.multi[i].name;
  322. }
  323. }
  324. return res;
  325. }
  326. },
  327. watch: {
  328. multiValue(val) {
  329. switch (this.multiType) {
  330. case 'code':
  331. case 'stock':
  332. case 'sales':
  333. this.multiValue = parseInt(val);
  334. break;
  335. }
  336. }
  337. },
  338. methods: {
  339. //渲染到表格
  340. render() {
  341. let arr = this.specList;
  342. if (arr.length == 0) {
  343. //空
  344. return;
  345. }
  346. let specTableList = this.specTableList;
  347. this.specTableList = [];
  348. let td = []; //tbody
  349. var xNum = [];
  350. // 自创笛卡尔乘积算法 @author: mingwei zheng
  351. // 主逻辑
  352. for (var i = 0; i < arr.length; i++) {
  353. var valueLenght = arr[i]['child'].length; //是一个数组
  354. var cols = cols ? cols : valueLenght;//行数
  355. xNum[i] = 1;
  356. for (var ii = i + 1; ii < arr.length; ii++) {
  357. if (arr[ii]) {
  358. let length = arr[ii]['child'].length ? arr[ii]['child'].length : 1;
  359. xNum[i] *= length;
  360. }
  361. if (i == 0) {
  362. let length = arr[ii]['child'].length ? arr[ii]['child'].length : 1;
  363. cols *= length;
  364. }
  365. }
  366. //console.log(xNum[i]);//每个值填多少个行
  367. for (var ii = 0; ii < cols;) {
  368. if (arr[i]['child'].length == 0) {
  369. ii++;
  370. }
  371. for (var v = 0; v < arr[i]['child'].length; v++) {
  372. for (var x = 0; x < xNum[i]; x++) {
  373. td[ii] = td[ii] ? td[ii] : {
  374. value: [],
  375. code: 0,
  376. market_price: 0.00,
  377. sales_price: 0.00,
  378. stock: 0,
  379. sales: 0,
  380. image: ''
  381. };
  382. td[ii].value.push(arr[i]['child'][v]);
  383. //保留原来大值(针对添加的情况)
  384. for (let tItem of specTableList) {
  385. if (
  386. tItem.value.toString() + ',' + arr[i]['child'][v] == td[ii].value.toString()
  387. ||
  388. tItem.value.toString() == td[ii].value.toString()
  389. ) {
  390. let tempValue = td[ii].value;
  391. td[ii] = tItem;
  392. td[ii].value = tempValue;
  393. break;
  394. }
  395. }
  396. ii++;
  397. }
  398. }
  399. }
  400. }
  401. this.specTableList = td;
  402. },
  403. //添加规格名
  404. addSpecList() {
  405. if (this.specName == '') {
  406. Toastr.error('不能为空');
  407. return
  408. }
  409. for (let item of this.specList) {
  410. if (item.name == this.specName) {
  411. Toastr.error('不能重复');
  412. this.specName = '';
  413. return
  414. }
  415. }
  416. if (this.specList === '') {
  417. this.specList = [];
  418. }
  419. this.specList.push({
  420. name: this.specName,
  421. child: []
  422. });
  423. this.specName = '';
  424. },
  425. //添加规格值
  426. addSpecChildList() {
  427. if (this.specValue == '') {
  428. Toastr.error('不能为空');
  429. return
  430. }
  431. for (let item of this.specList) {
  432. if (item.name == this.specFatherName) {
  433. for (let Citem of item.child) {
  434. if (Citem == this.specValue) {
  435. Toastr.error('不能重复的');
  436. this.specValue = '';
  437. return
  438. }
  439. }
  440. item.child.push(this.specValue)
  441. }
  442. }
  443. this.specValue = '';
  444. //更新到表格
  445. this.render();
  446. },
  447. //设置父亲规格名
  448. herFatherSpec(index) {
  449. this.specFatherIndex = index;
  450. },
  451. //删除规格属性
  452. delSpec(index) {
  453. let confir = confirm('是否删除属性:' + this.specList[index].name + '。若有属性值则一带删除。');
  454. if (confir) {
  455. for (var i = this.specList[index].child.length - 1; i >= 0; i--) {
  456. this.delSpecChild(index, i, true);
  457. }
  458. this.specList.splice(index, 1);
  459. this.render();
  460. }
  461. },
  462. //删除规格属性值
  463. delSpecChild(index, childIndex, noconfir = false) {
  464. if (!noconfir)
  465. var confir = confirm('是否删除属性值:' + this.specList[index].child[childIndex] + '。');
  466. if (confir || noconfir) {
  467. var value = this.specList[index].child.splice(childIndex, 1)[0];
  468. //更新到表格
  469. //console.log(value)
  470. this.renderDel(index, value)
  471. }
  472. return;
  473. },
  474. //删除渲染
  475. renderDel(index, value) {
  476. const that = this;
  477. if (that.specList[index].child.length == 0) {
  478. //删除最后一个的情况。只删除specTableList.value的
  479. for (let item of this.specTableList) {
  480. for (let i in item.value) {
  481. if (item.value[i] == value) {
  482. item.value.splice(i, 1);
  483. break;
  484. }
  485. }
  486. }
  487. this.render();
  488. } else {
  489. //还有属性值的情况。直接删除跟value相关的specTableList
  490. for (var i = this.specTableList.length - 1; i >= 0; i--) {
  491. for (let item of that.specTableList[i].value) {
  492. if (item == value) {
  493. this.specTableList.splice(i, 1);
  494. break;
  495. }
  496. }
  497. }
  498. }
  499. return;
  500. },
  501. // 批量添加规格值
  502. addMultiType(type) {
  503. this.multiType = type;
  504. this.multiValue = '';
  505. },
  506. addMultiValue() {
  507. this.multiType; // 当前批量添加的类型
  508. this.multiValue; // 当前批量编辑的值
  509. if (this.multiValue === '') {
  510. Toastr.error('不能为空');
  511. return;
  512. }
  513. switch (this.multiType) {
  514. case 'market_price':
  515. case 'sales_price':
  516. this.multiValue = parseFloat(this.multiValue).toFixed(2);
  517. break;
  518. }
  519. for (let i in this.specTableList) {
  520. this.specTableList[i][this.multiType] = this.multiValue;
  521. }
  522. this.render();
  523. }
  524. }
  525. });
  526. var Controller = {
  527. index: function () {
  528. // 初始化表格参数配置
  529. Table.api.init({
  530. extend: {
  531. index_url: 'unishop/product/index' + location.search,
  532. add_url: 'unishop/product/add',
  533. edit_url: 'unishop/product/edit',
  534. del_url: 'unishop/product/del',
  535. multi_url: 'unishop/product/multi',
  536. evaluate_url: 'unishop/evaluate/index',
  537. copy_url: 'unishop/product/copy',
  538. table: 'unishop_product',
  539. dragsort_url: false,
  540. }
  541. });
  542. $.fn.bootstrapTable.locales[Table.defaults.locale]['formatSearch'] = function () {
  543. return "请输入产品名称";
  544. };
  545. // 合并操作方法
  546. Table.api.events.operate = $.extend(Table.api.events.operate,
  547. {
  548. 'click .btn-evaluate': function (e, value, row, index) {
  549. e.stopPropagation();
  550. e.preventDefault();
  551. var table = $(this).closest('table');
  552. var options = table.bootstrapTable('getOptions');
  553. var ids = row[options.pk];
  554. row = $.extend({}, row ? row : {}, {ids: ids});
  555. var url = options.extend.evaluate_url + '?product_id=' + row.id;
  556. Fast.api.open(Table.api.replaceurl(url, row, table), __('Evaluate'), $(this).data() || {});
  557. }
  558. },
  559. {
  560. 'click .btn-copy': function (e, value, row, index) {
  561. e.stopPropagation();
  562. e.preventDefault();
  563. var table = $(this).closest('table');
  564. var options = table.bootstrapTable('getOptions');
  565. var ids = row[options.pk];
  566. row = $.extend({}, row ? row : {}, {ids: ids});
  567. var url = options.extend.copy_url;
  568. Fast.api.open(Table.api.replaceurl(url, row, table), __('Copy'), $(this).data() || {});
  569. }
  570. }
  571. );
  572. var table = $("#table");
  573. // 初始化表格
  574. table.bootstrapTable({
  575. url: $.fn.bootstrapTable.defaults.extend.index_url,
  576. pk: 'id',
  577. sortName: 'weigh',
  578. placeholder: '请输入产品名称',
  579. fixedColumns:true,
  580. fixedRightNumber:1,
  581. columns: [
  582. [
  583. {checkbox: true},
  584. {field: 'id', title: __('Id')},
  585. // {field: 'category_id', title: __('Category_id'), visible: false},
  586. /* {
  587. field: 'category', title: __('Category name'), formatter: function (value, row, index) {
  588. if (value) {
  589. if (value.parent) {
  590. return value.parent.name + ' / ' + value.name;
  591. } else {
  592. return value.name;
  593. }
  594. }
  595. return value;
  596. }
  597. },*/
  598. {field: 'title', title: __('Title')},
  599. {
  600. field: 'image',
  601. title: __('Image'),
  602. operate: false,
  603. events: Table.api.events.image,
  604. formatter: Table.api.formatter.image
  605. },
  606. {field: 'activetime', title: __('Activetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
  607. {field: 'activestatus', title: '活动状态',searchList: {"normal":'正常',"passed":'已过期'}, formatter: Table.api.formatter.status},
  608. /*{
  609. field: 'images',
  610. title: __('Images'),
  611. events: Table.api.events.image,
  612. formatter: Table.api.formatter.images,
  613. visible: false
  614. },*/
  615. {field: 'sales_price',operate: false, title: __('Lower price')},
  616. {field: 'stock', title: __('Stock'),operate: false},
  617. // {field: 'look', title: __('Look')},
  618. // {field: 'sales', title: __('Sales')},
  619. {field: 'real_sales', title: __('Real sales'),operate: false},
  620. // {field: 'no_buy_yet', title: __('No buy yet')},
  621. // {field: 'real_look', title: __('Real look')},
  622. // {field: 'delivery_id', title: __('Delivery_id'), visible: false},
  623. // {field: 'delivery.name', title: __('Delivery_id'), visible: false},
  624. /*{
  625. field: 'updatetime',
  626. title: __('Updatetime'),
  627. operate: 'RANGE',
  628. addclass: 'datetimerange',
  629. formatter: Table.api.formatter.datetime,
  630. visible: false
  631. },*/
  632. {
  633. field: 'createtime',
  634. title: __('Createtime'),
  635. operate: 'RANGE',
  636. addclass: 'datetimerange',
  637. formatter: Table.api.formatter.datetime
  638. },
  639. {field: 'weigh', title: __('Weigh')},
  640. {field: 'switch', title: __('Switch'),operate: false, formatter: Table.api.formatter.toggle},
  641. {
  642. field: 'operate',
  643. title: __('Operate'),
  644. table: table,
  645. events: Table.api.events.operate,
  646. formatter: Table.api.formatter.operate,
  647. /*buttons:[
  648. {
  649. name: 'evaluate',
  650. text: __('Evaluate'),
  651. classname: 'btn btn-xs btn-info btn-evaluate',
  652. extend: 'data-toggle="tooltip"',
  653. icon: 'fa fa-commenting'
  654. },
  655. {
  656. name: 'copy',
  657. text: __('Copy'),
  658. classname: 'btn btn-xs btn-info btn-copy',
  659. extend: 'data-toggle="tooltip"',
  660. icon: 'fa fa-copy'
  661. }
  662. ]*/
  663. }
  664. ]
  665. ]
  666. });
  667. // 为表格绑定事件
  668. Table.api.bindevent(table);
  669. },
  670. recyclebin: function () {
  671. // 初始化表格参数配置
  672. Table.api.init({
  673. extend: {
  674. 'dragsort_url': ''
  675. }
  676. });
  677. var table = $("#table");
  678. // 初始化表格
  679. table.bootstrapTable({
  680. url: 'unishop/product/recyclebin' + location.search,
  681. pk: 'id',
  682. sortName: 'id',
  683. columns: [
  684. [
  685. {checkbox: true},
  686. {field: 'id', title: __('Id')},
  687. {field: 'title', title: __('Title'), align: 'left'},
  688. {
  689. field: 'deletetime',
  690. title: __('Deletetime'),
  691. operate: 'RANGE',
  692. addclass: 'datetimerange',
  693. formatter: Table.api.formatter.datetime
  694. },
  695. {
  696. field: 'operate',
  697. width: '130px',
  698. title: __('Operate'),
  699. table: table,
  700. events: Table.api.events.operate,
  701. buttons: [
  702. {
  703. name: 'Restore',
  704. text: __('Restore'),
  705. classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
  706. icon: 'fa fa-rotate-left',
  707. url: 'unishop/product/restore',
  708. refresh: true
  709. },
  710. /* {
  711. name: 'Destroy',
  712. text: __('Destroy'),
  713. classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
  714. icon: 'fa fa-times',
  715. url: 'unishop/product/destroy',
  716. refresh: true
  717. }*/
  718. ],
  719. formatter: Table.api.formatter.operate
  720. }
  721. ]
  722. ]
  723. });
  724. // 为表格绑定事件
  725. Table.api.bindevent(table);
  726. },
  727. add: function () {
  728. Controller.api.bindevent();
  729. var component = new specComponent().$mount();
  730. // 插入页面
  731. document.getElementById('spec').appendChild(component.$el);
  732. $('#spec').on('click', function () {
  733. // 选择图片
  734. let chooseImageButtons = $(".fachoose-spec", $("#spec"));
  735. if (chooseImageButtons) {
  736. //console.log(chooseImageButtons);
  737. for (let i = 0; i < chooseImageButtons.length; i++) {
  738. let events = $._data(chooseImageButtons[i], 'events');
  739. if (events && events['click']) {
  740. // 已绑定事件
  741. //console.log('获取图片不重新绑定事件');
  742. } else {
  743. $(chooseImageButtons[i]).on('click', function () {
  744. var that = this;
  745. var multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
  746. var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
  747. parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype , __('Choose'), {
  748. callback: function (data) {
  749. var button = $("#" + $(that).attr("id"));
  750. var preview_id = $(button).data("preview-id") ? $(button).data("preview-id") : "";
  751. var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
  752. if (input_id) {
  753. $("#" + input_id).val(data.url).trigger("change");
  754. //TODO 出发一下input事件,让vue的v-model接收到数据
  755. document.getElementById(input_id).dispatchEvent(new Event('input'));
  756. // 插入图片
  757. if (preview_id && input_id) {
  758. var inputStr = data.url;
  759. var inputArr = inputStr.split(/\,/);
  760. $("#" + preview_id).empty();
  761. var tpl = $("#" + preview_id).data("template") ? $("#" + preview_id).data("template") : "";
  762. $.each(inputArr, function (i, j) {
  763. if (!j) {
  764. return true;
  765. }
  766. var data = {
  767. url: j,
  768. fullurl: Fast.api.cdnurl(j),
  769. data: $(that).data()
  770. };
  771. var html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
  772. let preview = $("#" + preview_id);
  773. preview.append(html);
  774. $('.btn-trash', preview).on('click', function () {
  775. preview.empty();
  776. })
  777. });
  778. }
  779. }
  780. }
  781. });
  782. return false;
  783. });
  784. }
  785. }
  786. }
  787. });
  788. },
  789. edit: function () {
  790. Controller.api.bindevent();
  791. var component = new specComponent().$mount();
  792. // 插入页面
  793. document.getElementById('spec').appendChild(component.$el);
  794. $('#spec').on('click', function () {
  795. // 选择图片
  796. let chooseImageButtons = $(".fachoose-spec", $("#spec"));
  797. if (chooseImageButtons) {
  798. for (let i = 0; i < chooseImageButtons.length; i++) {
  799. let events = $._data(chooseImageButtons[i], 'events');
  800. let that = chooseImageButtons[i];
  801. let button = $("#" + $(that).attr("id"))
  802. let maxcount = $(button).data("maxcount");
  803. let preview_id = $(button).data("preview-id") ? $(button).data("preview-id") : "";
  804. let input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
  805. if (events && events['click']) {
  806. // 已绑定事件
  807. //console.log('获取图片不重新绑定事件');
  808. } else {
  809. $(chooseImageButtons[i]).on('click', function () {
  810. let multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
  811. let mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
  812. parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype , __('Choose'), {
  813. callback: function (data) {
  814. maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
  815. if (input_id) {
  816. $("#" + input_id).val(data.url).trigger("change");
  817. //TODO 出发一下input事件,让vue的v-model接收到数据
  818. document.getElementById(input_id).dispatchEvent(new Event('input'));
  819. // 插入图片
  820. if (preview_id && input_id) {
  821. let inputStr = data.url;
  822. let inputArr = inputStr.split(/\,/);
  823. $("#" + preview_id).empty();
  824. let tpl = $("#" + preview_id).data("template") ? $("#" + preview_id).data("template") : "";
  825. $.each(inputArr, function (i, j) {
  826. if (!j) {
  827. return true;
  828. }
  829. let data = {
  830. url: j,
  831. fullurl: Fast.api.cdnurl(j),
  832. data: $(that).data()
  833. };
  834. let html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
  835. let preview = $("#" + preview_id);
  836. preview.append(html);
  837. $('.btn-trash', preview).on('click', function(){
  838. preview.empty();
  839. $("#" + input_id).val('');
  840. //TODO 出发一下input事件,让vue的v-model接收到数据
  841. document.getElementById(input_id).dispatchEvent(new Event('input'));
  842. })
  843. });
  844. }
  845. }
  846. }
  847. });
  848. return false;
  849. });
  850. }
  851. // 首次加载的时候用到, 加载数据
  852. let inputStr = $('#' + input_id).val();
  853. if (inputStr && input_id) {
  854. let inputArr = inputStr.split(/\,/);
  855. $("#" + preview_id).empty();
  856. let tpl = $("#" + preview_id).data("template") ? $("#" + preview_id).data("template") : "";
  857. $.each(inputArr, function (i, j) {
  858. if (!j) {
  859. return true;
  860. }
  861. let data = {
  862. url: j,
  863. fullurl: Fast.api.cdnurl(j),
  864. data: $(that).data()
  865. };
  866. let html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
  867. //console.log(preview_id);
  868. let preview = $("#" + preview_id);
  869. preview.append(html);
  870. $('.btn-trash', preview).on('click', function(){
  871. $("#" + preview_id).empty();
  872. $('#' + input_id).val('');
  873. //TODO 出发一下input事件,让vue的v-model接收到数据
  874. document.getElementById(input_id).dispatchEvent(new Event('input'));
  875. })
  876. });
  877. }
  878. }
  879. }
  880. });
  881. $('#spec').click();
  882. },
  883. copy:function(){
  884. Controller.api.bindevent();
  885. var component = new specComponent().$mount();
  886. // 插入页面
  887. document.getElementById('spec').appendChild(component.$el);
  888. $('#spec').on('click', function () {
  889. // 选择图片
  890. let chooseImageButtons = $(".fachoose-spec", $("#spec"));
  891. if (chooseImageButtons) {
  892. for (let i = 0; i < chooseImageButtons.length; i++) {
  893. let events = $._data(chooseImageButtons[i], 'events');
  894. let that = chooseImageButtons[i];
  895. let button = $("#" + $(that).attr("id"))
  896. let maxcount = $(button).data("maxcount");
  897. let preview_id = $(button).data("preview-id") ? $(button).data("preview-id") : "";
  898. let input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
  899. if (events && events['click']) {
  900. // 已绑定事件
  901. //console.log('获取图片不重新绑定事件');
  902. } else {
  903. $(chooseImageButtons[i]).on('click', function () {
  904. let multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
  905. let mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
  906. parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype , __('Choose'), {
  907. callback: function (data) {
  908. maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
  909. if (input_id) {
  910. $("#" + input_id).val(data.url).trigger("change");
  911. //TODO 出发一下input事件,让vue的v-model接收到数据
  912. document.getElementById(input_id).dispatchEvent(new Event('input'));
  913. // 插入图片
  914. if (preview_id && input_id) {
  915. let inputStr = data.url;
  916. let inputArr = inputStr.split(/\,/);
  917. $("#" + preview_id).empty();
  918. let tpl = $("#" + preview_id).data("template") ? $("#" + preview_id).data("template") : "";
  919. $.each(inputArr, function (i, j) {
  920. if (!j) {
  921. return true;
  922. }
  923. let data = {
  924. url: j,
  925. fullurl: Fast.api.cdnurl(j),
  926. data: $(that).data()
  927. };
  928. let html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
  929. let preview = $("#" + preview_id);
  930. preview.append(html);
  931. $('.btn-trash', preview).on('click', function(){
  932. preview.empty();
  933. $("#" + input_id).val('');
  934. //TODO 出发一下input事件,让vue的v-model接收到数据
  935. document.getElementById(input_id).dispatchEvent(new Event('input'));
  936. })
  937. });
  938. }
  939. }
  940. }
  941. });
  942. return false;
  943. });
  944. }
  945. // 首次加载的时候用到, 加载数据
  946. let inputStr = $('#' + input_id).val();
  947. if (inputStr && input_id) {
  948. let inputArr = inputStr.split(/\,/);
  949. $("#" + preview_id).empty();
  950. let tpl = $("#" + preview_id).data("template") ? $("#" + preview_id).data("template") : "";
  951. $.each(inputArr, function (i, j) {
  952. if (!j) {
  953. return true;
  954. }
  955. let data = {
  956. url: j,
  957. fullurl: Fast.api.cdnurl(j),
  958. data: $(that).data()
  959. };
  960. let html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
  961. //console.log(preview_id);
  962. let preview = $("#" + preview_id);
  963. preview.append(html);
  964. $('.btn-trash', preview).on('click', function(){
  965. $("#" + preview_id).empty();
  966. $('#' + input_id).val('');
  967. //TODO 出发一下input事件,让vue的v-model接收到数据
  968. document.getElementById(input_id).dispatchEvent(new Event('input'));
  969. })
  970. });
  971. }
  972. }
  973. }
  974. });
  975. $('#spec').click();
  976. },
  977. api: {
  978. bindevent: function () {
  979. Form.api.bindevent($("form[role=form]"));
  980. }
  981. },
  982. select: function () {
  983. // 初始化表格参数配置
  984. Table.api.init({
  985. extend: {
  986. index_url: 'unishop/product/index',
  987. }
  988. });
  989. $.fn.bootstrapTable.locales[Table.defaults.locale]['formatSearch'] = function () {
  990. return "请输入产品名称";
  991. };
  992. var table = $("#table");
  993. // 初始化表格
  994. table.bootstrapTable({
  995. url: $.fn.bootstrapTable.defaults.extend.index_url,
  996. sortName: 'id',
  997. placeholder: '请输入产品名称',
  998. columns: [
  999. [
  1000. {field: 'state', checkbox: true,},
  1001. {field: 'id', title: __('Id'), sortable: true},
  1002. {field: 'title', title: __('Title')},
  1003. {field: 'image', title: __('Image'), operate: false, formatter: Table.api.formatter.image},
  1004. {field: 'stock', title: __('Stock')},
  1005. {field: 'category.name', title: __('Category name')},
  1006. {
  1007. field: 'switch',
  1008. title: __('Switch'),
  1009. formatter: Table.api.formatter.status,
  1010. searchList: {"1": __('Yes'), "0": __('No')}
  1011. },
  1012. {
  1013. field: 'createtime',
  1014. title: __('Createtime'),
  1015. formatter: Table.api.formatter.datetime,
  1016. operate: 'RANGE',
  1017. addclass: 'datetimerange',
  1018. sortable: true
  1019. },
  1020. {
  1021. field: 'operate', title: __('Operate'), events: {
  1022. 'click .btn-chooseone': function (e, value, row, index) {
  1023. var dataArr = new Array();
  1024. dataArr.push(row);
  1025. Fast.api.close({data: dataArr, multiple: false});
  1026. },
  1027. }, formatter: function () {
  1028. return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>';
  1029. }
  1030. }
  1031. ]
  1032. ]
  1033. });
  1034. // 选中多个
  1035. $(document).on("click", ".btn-choose-multi", function () {
  1036. var dataArr = new Array();
  1037. $.each(table.bootstrapTable("getAllSelections"), function (i, j) {
  1038. dataArr.push(j);
  1039. });
  1040. var multiple = Backend.api.query('multiple');
  1041. multiple = multiple == 'true' ? true : false;
  1042. Fast.api.close({data: dataArr, multiple: true});
  1043. });
  1044. // 为表格绑定事件
  1045. //Table.api.bindevent(table);
  1046. }
  1047. };
  1048. return Controller;
  1049. });