fastadmin 后台商品sku(vue)
先上个效果图
首先先引入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'].value
if ($.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].value
if ($.trim(val) == '') {
Toastr.error("不能为空")
return
}
if (val.indexOf(',') > -1) {
Toastr.error("不能包含符号‘,’")
return
}
if (!val) return false
console.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].image
this.productSkus[i].market_price=oldtproductSkus[i].market_price
this.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].image
this.productSkus[i].market_price = oldtproductSkus[j].market_price
this.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.products
this.attrItems=newsku.items
this.attrGroups=newsku.groups
console.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].image
this.productSkus[i].market_price=oldtproductSkus[i].market_price
this.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].image
this.productSkus[i].market_price = oldtproductSkus[n].market_price
this.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].image
this.productSkus[i].market_price=oldtproductSkus[i].market_price
this.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].image
this.productSkus[i].market_price = oldtproductSkus[n].market_price
this.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].value
var v = isNaN(Number(v)) ? v : Number(v);
var productSkus = this.productSkus
for (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 = this
this.cb = cb
Upload.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 = this
Upload.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