先上个效果图
首先先引入vue
define(['backend'], function (Backend) {require.config({paths: {'vue': '/assets/jeekshopskugoods/libs/vue.min','skuimg': '/assets/jeekshopskugoods/js/skuimg','skugoods': '/assets/jeekshopskugoods/js/skugoods','layui': '/assets/LayuiSpzj/layui/layui',//js省略,如果是vue.min.js,就学vue.min},shim: {//sku商品插件'vue': {exports: 'vue'},'skugoods': {deps: ['css!/assets/jeekshopskugoods/css/skugoods.css',],exports: 'skugoods'},'layui': {deps: ['css!/assets/LayuiSpzj/layui/css/layui.css'],init:function (){return this.layui.config({ base:'/assets/laySku-master/lay-module/'} );}},// 'skuTable': {// // deps: ['/assets/laySku-master/layui/layui.js'],// exports: 'skuTable'// },// 'sorTable': {// deps: ['/assets/laySku-master/layui/layui.js','/assets/laySku-master/lay-module/sorTable.js'],// exports: 'sorTable'// },}});});
sku.html
<style>.delete{width: 20px;height: 20px;position: relative;top: -20px;font-size: 18px;color: red;right: 8px;cursor:pointer;}
</style>
<div class="form-group"><label class="control-label col-xs-12 col-sm-2">{:__('SKU库')}:</label><div class="col-xs-12 col-sm-10"><input id="c-skutitle" data-source="skus/skus/index" class="form-control selectpage" data-field="title" name="row[skutitle]" type="text" value="" placeholder="选择sku,会覆盖现在的sku,请慎重"></div>
</div>
<div class="form-group"><div id="app" v-cloak class="col-xs-12 col-sm-12"><input id="c-skutitles" name="row[skutitle]" @change="getskus" type="hidden" value=""><label class="control-label col-xs-12 col-sm-2">库存/规格</label><div class="input-group"><input type="text" class="form-control" placeholder="输入规格名称" ref="attr-group-name"> <span class="input-group-addon pointer" @click="addRow">添加规格</span></div><!-- 规格项 --><div class="sku-content"><div class="panel panel-default" v-for="(v, i) in attrGroups"><header class="panel-heading text-center"><b>{{v}}</b> <i class="pull-right fa fa-trash pointer text-danger" @click="removeGroup(i)"></i></header><div class="row row-content"><div class="col-md-6 col-sm-6 col-xs-6"><div class="input-group"><input type="text" class="form-control" :ref="`attr-item-name-${i}`"><span class="input-group-addon pointer" @click="addChild(i)">添加</span></div></div><div class="col-md-6 col-sm-6 col-xs-6 tag-content"><span class="tag" v-for="(vv, j) in attrItems[i]">{{vv}} <i class="fa fa-minus-circle pointer text-danger" @click="removeChild(i, j)"></i></span></div></div></div></div><div class="row" v-show="attrGroups.length"><div class="col-md-12"><table class="table table-bordered attr-table"><thead><tr><th v-for="(v, i) in attrGroups">{{v}}</th><th width="80">UPC</th><th width="80">价格</th>
<!-- <th width="80">库存</th>-->
<!-- <th width="80">编码</th>--><th width="180">图片</th>
<!-- <th width="80">状态</th>--></tr></thead><tbody><tr><td :colspan="attrGroups.length" width="80">批量设置</td><td><div class="input-group "><input type="number" ref="batch-market_price" class="form-control no-padding text-center"> <span @click="batchSetAttrs('market_price')" class="input-group-addon pointer">设置</span></div></td><td><div class="input-group "><input type="number" ref="batch-price" class="form-control no-padding text-center"> <span @click="batchSetAttrs('price')" class="input-group-addon pointer">设置</span></div></td><td><!-- <img src="/assets/jeekshopskugoods/img/upload.png" @click="upimage()">--><div @click="upimage()">批量设置</div><!-- <div class="input-group"><input type="number" ref="batch-stock" class="form-control no-padding text-center"> <span @click="batchSetAttrs('stock')" class="input-group-addon pointer">设置</span></div>--></td><!-- <td>--><!-- <div class="input-group"><input type="text" ref="batch-sn" class="form-control"> <span @click="batchSetAttrs('sn')" class="input-group-addon pointer">设置</span></div>--><!-- </td>--></tr><tr v-for="(v, i) in productSkus" :class="v.status!=1?'':'disabled'"><td v-for="(vv, j) in v.attr" width="80">{{vv}}</td><td width="80"><input type="number" name="dsd" class="input-sm form-control attr-market_price" v-model="v.market_price"></td><td width="80"><input type="number" class="input-sm form-control attr-price" v-model="v.price"></td>
<!-- <td width="80">-->
<!-- <input type="number" class="input-sm form-control attr-stock" v-model="v.stock">-->
<!-- </td>-->
<!-- <td width="80">-->
<!-- <input type="text" class="input-sm form-control attr-sn" v-model="v.sn">-->
<!-- </td>--><td width="80"><div class="sku-img" style="width: auto"><div v-if="v.image.length > 0" style="display: inline"><span v-for="(ita,a) in v.image" :key='a' style="margin-top:10px ;display: inline-block"><img:src="ita"style="":draggable="true"@dragstart="dragCurrentStart($event,i, a)"@dragover="e=>e.preventDefault()"@dragenter="dragTargetEnter($event,i ,a)"@drop="dragEnd"><span class="delete" @click="showFiguredelete(i,a)">×</span></span>
<!-- <i v-if="v.image.length > 0" class="fa fa-minus-circle text-danger img-trash" @click.stop="delimage(i,a)"></i>--></div><img src="/assets/jeekshopskugoods/img/upload.png" @click="upimagea($event,i)"></div></td>
<!-- <td width="80">-->
<!-- <input type="hidden" class="input-sm form-control attr-status" v-model="v.status">-->
<!-- <i v-if="v.status==1" class="fa fa-toggle-on text-success fa-2x" @click="toggle(i,0)"></i>-->
<!-- <i v-else class="fa fa-toggle-off text-gray fa-2x" @click="toggle(i,1)"></i>-->
<!-- </td>--></tr></tbody></table><div class="hide"><input type="text" name="row[skus]" :value="productSkusStr"><input type="text" name="row[groups]" :value="attrGroupsStr"><input type="text" name="row[items]" :value="attrItemsStr"></div></div></div></div>
</div>
skugoods.js
define(['jquery', 'vue', 'skuimg'], function($, Vue, Skuimg) {'use strict';var jeekshopsku = {_init: function(d) {var f = { 'market_price': '', 'price': '', 'image': [] }; // 默认商品规格的字段this.vueInit(f, d);},vueInit: function(f, d) {var vm = new Vue({el: '#app',data() {return {attrGroups: d.groups,attrItems: d.items,productSkus: d.products,dragCurIndex: null, // 当前拖拽图片下标timer: null}},computed: {productSkusStr() {return JSON.stringify(this.productSkus)},attrGroupsStr() {return JSON.stringify(this.attrGroups)},attrItemsStr() {return JSON.stringify(this.attrItems)}},mounted() {Skuimg.init()},methods: {// 开始拖拽当前图片dragCurrentStart(e, index,a) {this.dragCurIndex = a;},// 图片拖拽排序dragTargetEnter(e,index,a) {e.preventDefault();if (this.timer) {clearTimeout(this.timer);}// console.log(this.productSkus[index].image)this.timer = setTimeout(()=>{let tmp = this.productSkus[index].image[a];this.productSkus[index].image.splice(a, 1, this.productSkus[index].image[this.dragCurIndex]);this.productSkus[index].image.splice(this.dragCurIndex, 1, tmp);this.dragCurIndex = index;},100)// console.log(this.productSkus[index].image)},// 拖拽结束清除定时器dragEnd() {clearTimeout(this.timer);},setAttrGroupName(i, e) {this.$set(this.attrGroups, i, e.target.value)},addRow() {var val = this.$refs['attr-group-name'].valueif ($.trim(val) == '') {Toastr.error("不能为空")return}if (val.indexOf(',') > -1) {Toastr.error("不能包含符号‘,’")return}this.attrGroups.push(val)this.attrItems.push([])this.$refs['attr-group-name'].value = ''},addChild(index) {var val = this.$refs['attr-item-name-' + index][0].valueif ($.trim(val) == '') {Toastr.error("不能为空")return}if (val.indexOf(',') > -1) {Toastr.error("不能包含符号‘,’")return}if (!val) return falseconsole.log(this.productSkus)if (this.attrItems[index]) {this.attrItems[index].push(val)} else {this.attrItems.push([val])this.productSkus.push( { 'attr':[val],'market_price': '', 'price': '', 'image': [] });}let oldtproductSkus=this.productSkus;this.$refs['attr-item-name-' + index][0].value = ""this.generateProducts()for (var i = 0; i < this.productSkus.length; i++){if (oldtproductSkus.hasOwnProperty(i) && oldtproductSkus[i].attr.length==1){this.productSkus[i].image=oldtproductSkus[i].imagethis.productSkus[i].market_price=oldtproductSkus[i].market_pricethis.productSkus[i].price=oldtproductSkus[i].price}else {for (var j = 0; j < oldtproductSkus.length; j++) {if (this.isEqual(this.productSkus[i].attr,oldtproductSkus[j].attr)) {this.productSkus[i].image = oldtproductSkus[j].imagethis.productSkus[i].market_price = oldtproductSkus[j].market_pricethis.productSkus[i].price = oldtproductSkus[j].price}}}// console.log(arr[i]);}},isEqual(arr1, arr2) {if (arr1.length !== arr2.length) {return false;}for (let i = 0; i < arr1.length; i++) {if (arr1[i] !== arr2[i]) {return false;}}return true;},upimagea(event,i) {let that = this;Skuimg.open(function(data) {console.log(i)console.log(that.productSkus)that.productSkus[i].image=that.productSkus[i].image.concat(data.url)// that.productSkus[i].image.push()// console.log(that.productSkus)Skuimg.close()})},upimage() {let that = this;Skuimg.open(function(data) {// console.log(i)console.log(that.productSkus)for (var i = 0; i < that.productSkus.length; i++){that.productSkus[i].image=that.productSkus[i].image.concat(data.url)// console.log(arr[i]);}// that.productSkus[0].image.push()// console.log(that.productSkus)Skuimg.close()})},getskus(event){this.inputValue = event.target.value; // 更新数据属性let newsku=JSON.parse(this.inputValue);this.productSkus=newsku.productsthis.attrItems=newsku.itemsthis.attrGroups=newsku.groupsconsole.log(1111)console.log(newsku); // 打印输入框的值},showFiguredelete(i,index){console.log(i)console.log(this.productSkus[i].image)// this.productSkus[i].image=this.productSkus[i].image.concat(data.url)this.productSkus[i].image.splice(index,1)},delimage(i,a) {console.log(a)console.log(this.productSkus[i][0]);// vm.$set(this.productSkus[i], 'image', '')// vm.productSkus[i].image.pop();},// toggle(i, j) {// vm.$set(vm.productSkus[i], 'status', j)// },removeElement1(arr, index) {arr.splice(index, 1);return arr;},removeChild(i, j) {let oldtproductSkus=this.productSkus;console.log(this.attrItems)this.removeElement1(this.attrItems[i],j)// this.attrItems[i].pop(j)this.generateProducts()for (var i = 0; i < this.productSkus.length; i++){if (oldtproductSkus[i].attr.length==1){this.productSkus[i].image=oldtproductSkus[i].imagethis.productSkus[i].market_price=oldtproductSkus[i].market_pricethis.productSkus[i].price=oldtproductSkus[i].price}else {for (var n = 0; n < oldtproductSkus.length; n++) {if (this.isEqual(this.productSkus[i].attr,oldtproductSkus[n].attr)) {this.productSkus[i].image = oldtproductSkus[n].imagethis.productSkus[i].market_price = oldtproductSkus[n].market_pricethis.productSkus[i].price = oldtproductSkus[n].price}}}// console.log(arr[i]);}},removeGroup(i) {let oldtproductSkus=this.productSkus;this.attrGroups.pop(i)if (this.attrItems[i]){this.attrItems.pop(i)}for (var i = 0; i < this.productSkus.length; i++){if (oldtproductSkus[i].attr.length==1){this.productSkus[i].image=oldtproductSkus[i].imagethis.productSkus[i].market_price=oldtproductSkus[i].market_pricethis.productSkus[i].price=oldtproductSkus[i].price}else {for (var n = 0; n < oldtproductSkus.length; n++) {if (this.isEqual(this.productSkus[i].attr,oldtproductSkus[n].attr)) {this.productSkus[i].image = oldtproductSkus[n].imagethis.productSkus[i].market_price = oldtproductSkus[n].market_pricethis.productSkus[i].price = oldtproductSkus[n].price}}}// console.log(arr[i]);}this.generateProducts()},generateProducts() {this.productSkus = this.descartes(this.attrItems)},descartes(array) {var arr = [].reduce.call(array, function(a, b) {var ret = [];a.forEach(function(a) {b.forEach(function(b) {ret.push(a.concat([b]));});});return ret;}, [[]]);var ret = [];arr.map(function(v, i) {var sku = { "attr": v };Object.assign(sku, f);ret.push(sku)});return ret;},batchSetAttrs(field) {var v = this.$refs['batch-' + field].valuevar v = isNaN(Number(v)) ? v : Number(v);var productSkus = this.productSkusfor (var i = 0; i < productSkus.length; i++) {productSkus[i][field] = v}this.productSkus = productSkus}}})},}return jeekshopsku;
});
skuimg.js
define(['jquery', 'upload', 'form'
], function($, Upload, Form) {'use strict';var skuimg = {html: '<div class="i-modal"><div class="i-content"><p>上传/选择图片</p><button data-upload-success="onSuccess" data-multiple="true" type="button" id="plupload-i-image" class="plupload" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp"><i class="fa fa-upload"></i> 上传</button><button type="button" id="fachoose-i-image" class="fachoose" data-mimetype="image/*" ><i class="fa fa-list"></i>选择</button><span class="close fa fa-close"></span></div></div>',css: "<style>.i-modal {background: rgba(0, 0, 0, 0.3); z-index: 9999; position: fixed;left: 0; top: 0; height: 100%; width: 100%;}.i-content{text-align: center;background: #fff; border-radius: 8px; width: 400px; height: 190px;position: absolute;left: 50%;top: 50%;-webkit-transform: translate(-50%, -50%);transform: translate(-50%, -50%);}.i-content button{width: 100px;height: 100px;color: #606266;border: 1px dashed #999;border-radius: 10px;background: none;margin: 0 5px;}.i-content button:hover{border-color: #409eff}.i-modal .i-content p {margin: 15px 0;}.i-modal .i-content .close{position: absolute;right: 5px; top: 5px; font-size: 20px;}</style>",el: '.i-modal',cb: function() {},open: function(cb) {var _this = thisthis.cb = cbUpload.api.custom['onSuccess'] = _this.cb$(this.el).show()},close: function() {$(this.el).hide()},init: function() {$(document.body).append(this.html)$(document.body).append(this.css)this.bindEvent()this.close()},bindEvent: function() {var _this = thisUpload.api.plupload('.plupload', $(_this.el))$(".fachoose", _this.el).on('click', function() {var multiple = $(this).data("multiple") ? $(this).data("multiple") : false;var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';var admin_id = $(this).data("admin-id") ? $(this).data("admin-id") : '';var user_id = $(this).data("user-id") ? $(this).data("user-id") : '';parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype + "&admin_id=" + admin_id + "&user_id=" + user_id, __('Choose'), {callback: function(data) {console.log(data)// var arr = data.url.split(",");// data.url = arr;_this.cb(data)// console.log(data)}})})$('.close', _this.el).on('click', function() {_this.close()})$('.i-modal', document).on('click', function(e) {_this.close()})$('.i-content', '.i-modal').on('click', function(e) {e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true})}};return skuimg;
});
goods.js
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'skugoods'], function($, undefined, Backend, Table, Form, Sku) {var Controller = {index: function () {// 初始化表格参数配置Table.api.init({extend: {index_url: 'goods/goods/index' + location.search,add_url: 'goods/goods/add',edit_url: 'goods/goods/edit',del_url: 'goods/goods/del',multi_url: 'goods/goods/multi',import_url: 'goods/goods/import',table: 'goods',}});var table = $("#table");// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: 'id',sortName: 'id',maintainSelected: true,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: 'id', title: __('Id')},{field: 'member_id', title: __('Member_id')},{field: 'title', title: __('Title'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},{field: 'sku', title: __('Sku'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},{field: 'upc', title: __('Upc'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},{field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image},// {field: 'images', title: __('Images'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.images},{field: 'price', title: __('Price'), operate:'BETWEEN'},{field: 'currency_unit', title: __('Currency_unit'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},{field: 'url', title: __('Url'), operate: 'LIKE', formatter: Table.api.formatter.url},{field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},// {field: 'image_trans', title: __('Image_trans')},{field: 'button',width: "150px",title: __('转化图片'),table: table,// events: Controller.api.events.trans,buttons: [{name: 'click',title: __('转化图片'),classname: 'btn btn-xs btn-info btn-trans btn-click',icon: 'fa fa-magic',}],formatter: function (value, row, index) {var progress = "<div class='progress'><div class='progress-bar' role='progressbar' aria-valuenow='50' aria-valuemin='0' aria-valuemax='100' style='width:"+row['image_trans'].toFixed(2)+"%'>"+row['image_trans'].toFixed(2)+"</div></div>"var trans = ''if(row['image_trans']<100) trans = Table.api.buttonlink(this, this.buttons, value, row, index, 'button')transhtml = "<div class='trans'>" + trans + "</div>"return transhtml + progress;}},{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}]]});//导出var submitForm = function (ids, layero) {var options = table.bootstrapTable('getOptions');console.log(options);var columns = [];$.each(options.columns[0], function (i, j) {if (j.field && !j.checkbox && j.visible && j.field != 'operate') {columns.push(j.field);}});var search = options.queryParams({});$("input[name=search]", layero).val(options.searchText);$("input[name=ids]", layero).val(ids);$("input[name=filter]", layero).val(search.filter);$("input[name=op]", layero).val(search.op);$("input[name=columns]", layero).val(columns.join(','));$("form", layero).submit();};var submitData = function (ids, layero) {var options = table.bootstrapTable('getOptions');console.log(options);var columns = [];$.each(options.columns[0], function (i, j) {if (j.field && !j.checkbox && j.visible && j.field != 'operate') {columns.push(j.field);}});var search = options.queryParams({});return search;};$(document).on("click", ".btn-export", function () {var ids = Table.api.selectedids(table);var page = table.bootstrapTable('getData');var all = table.bootstrapTable('getOptions').totalRows;console.log(ids, page, all);Layer.confirm("请选择导出的选项<form action='" + Fast.api.fixurl("goods/goods/export") + "' method='post' target='_blank'><input type='hidden' name='ids' value='' /><input type='hidden' name='filter' ><input type='hidden' name='op'><input type='hidden' name='search'><input type='hidden' name='columns'></form>", {title: '导出数据',btn: ["选中项(" + ids.length + "条)", "本页(" + page.length + "条)", "全部(" + all + "条)"],success: function (index,layero) {$(".layui-layer-btn a", layero).addClass("layui-layer-btn0");},yes: function (index, layero) {submitForm(ids.join(","), layero);return false;},btn2: function (index, layero) {var ids = [];$.each(page, function (i, j) {ids.push(j.id);});submitForm(ids.join(","), layero);return false;},btn3: function (index, layero) {submitForm("all", layero);return false;}});parent.Layer.close(index);});// 为表格绑定事件Table.api.bindevent(table);},add: function () {//获取sku库数据var d = { groups: [], items: [], products: [] }$('input[name="row[skutitle]"]').change(function() {// 当单选按钮的值发生变化时,这里的代码会被执行var selectedValue = $(this).val();console.log('选中的值是:', selectedValue);$.ajax({url:'skus/skus/getOne',type: 'GET',dataType: 'json',data: {ids: selectedValue,},success:function(res){console.log(res.data)var inputElement = document.getElementById('c-skutitles');inputElement.value = res.data;// $('#c-skutitles').val();inputElement.dispatchEvent(new Event('change'));}});});Sku._init(d);Controller.api.bindevent();},edit: function (row) {$('input[name="row[skutitle]"]').change(function() {// 当单选按钮的值发生变化时,这里的代码会被执行var selectedValue = $(this).val();console.log('选中的值是:', selectedValue);$.ajax({url:'skus/skus/getOne',type: 'GET',dataType: 'json',data: {ids: selectedValue,},success:function(res){console.log(res.data)var inputElement = document.getElementById('c-skutitles');inputElement.value = res.data;// $('#c-skutitles').val();inputElement.dispatchEvent(new Event('change'));}});});Sku._init(Config.skus);Controller.api.bindevent();},api: {bindevent: function () {Form.api.bindevent($("form[role=form]"));},}};return Controller;
});
项目代码 https://gitee.com/btzhyxjdmg/sku-plugin