This commit is contained in:
pushuo 2022-07-18 20:06:09 +08:00
parent e0685c9069
commit e004cffc05
5 changed files with 202 additions and 134 deletions

View File

@ -19,7 +19,7 @@ class DesignController extends Controller
public function index(Request $request): View
{
$data = [
'editors' => ['editor-slide_show', 'editor-image401', 'editor-product'],
'editors' => ['editor-slide_show', 'editor-image401', 'editor-tab_product'],
'languages' => LanguageRepo::all(),
'design_settings' => system_setting('base.design_setting'),
];

View File

@ -14,7 +14,7 @@ namespace Beike\Admin\View\DesignBuilders;
use Illuminate\View\Component;
use Illuminate\Contracts\View\View;
class Product extends Component
class TabProduct extends Component
{
/**
* Create a new component instance.
@ -35,10 +35,10 @@ class Product extends Component
$data['register'] = [
'code' => 'product',
'sort' => 0,
'name' => '推荐商品',
'name' => '选项卡商品',
'icon' => '',
];
return view('admin::pages.design.module.product', $data);
return view('admin::pages.design.module.tab_product', $data);
}
}

View File

@ -1,130 +0,0 @@
<template id="module-editor-product-template">
<div class="module-editor-product-template">
<div class="module-editor-title">设置</div>
<div class="module-edit-group">
<div class="module-edit-title">设置标题</div>
<text-i18n v-model="module.title"></text-i18n>
</div>
<div class="module-editor-title">内容</div>
<div class="module-edit-group">
<div class="module-edit-title">设置商品</div>
<div class="autocomplete-group-wrapper">
<el-autocomplete
class="inline-input"
v-model="keyword"
value-key="name"
size="small"
:fetch-suggestions="querySearch"
placeholder="请输入关键字搜索"
:trigger-on-focus="false"
:highlight-first-item="true"
@select="handleSelect"
></el-autocomplete>
<div class="item-group-wrapper" v-loading="loading">
<draggable
ghost-class="dragabble-ghost"
:list="productData"
@change="itemChange"
:options="{animation: 330}"
>
<div v-for="(item, index) in productData" :key="index" class="item">
<span>@{{ item.name }}</span>
<i class="fa fa-minus-circle" @click="removeProduct(index)"></i>
</div>
</draggable>
</div>
</div>
</div>
</div>
</template>
<script type="text/javascript">
Vue.component('module-editor-product', {
template: '#module-editor-product-template',
props: ['module'],
data: function () {
return {
keyword: '',
productData: [],
loading: null,
}
},
watch: {
module: {
handler: function (val) {
this.$emit('on-changed', val);
},
deep: true
}
},
created: function () {
var that = this;
if (!this.module.items.length) return;
this.loading = true;
$.ajax({
url: 'index.php?route=extension/theme/default/page/module/product/productsByIds',
data: {product_ids: this.module.items},
type: 'post',
dataType: 'json',
success: function (json) {
if (json) {
that.loading = false;
that.productData = json;
}
}
});
},
methods: {
querySearch(keyword, cb) {
if (!keyword) {
return;
}
$http.get(`products/${keyword}/name`, null, {hload: true}).then((res) => {
if (res.data) {
cb(res.data);
}
})
},
handleSelect(item) {
if (!this.module.items.find(v => v == item.product_id)) {
this.module.items.push(item.product_id * 1);
this.productData.push(item);
}
this.keyword = ""
},
itemChange(evt) {
this.module.items = this.productData.map(e => e.product_id * 1);
},
removeProduct(index) {
this.productData.splice(index, 1)
this.module.items.splice(index, 1);
}
}
});
setTimeout(() => {
const make = {
style: {
background_color: ''
},
floor: languagesFill(''),
items: [0],
title: languagesFill('商品模块'),
}
let register = @json($register);
register.make = make;
app.source.modules.push(register)
}, 100)
</script>

View File

@ -0,0 +1,198 @@
<template id="module-editor-product-tab-template">
<div class="module-editor-product-tab-template">
<div class="module-editor-title">设置</div>
<div class="module-edit-group">
<div class="module-edit-title">模块标题</div>
<text-i18n v-model="module.title"></text-i18n>
</div>
<div class="module-editor-title">内容</div>
<div class="module-edit-group">
<div class="module-edit-title">选择图片</div>
<div class="pb-images-selector">
<div class="selector-head">
<div class="left">
<img :src="thumbnail(module.image.image[{{ current_language_code() }}], 40, 40)" class="img-responsive">
</div>
<div class="right"><i :class="'fa fa-angle-'+(module.image.show ? 'up' : 'down')"></i></div>
</div>
<div :class="'pb-images-list ' + (module.image.show ? 'active' : '')">
<div class="pb-images-top">
<div class="pb-image-selector-wrapper">
<pb-image-selector v-model="module.image.image"></pb-image-selector>
<div class="tag">建议尺寸: 440 x 1022</div>
</div>
</div>
<link-selector v-model="module.image.link"></link-selector>
</div>
</div>
</div>
<div class="module-edit-group">
<div class="module-edit-title">配置商品</div>
<el-tabs v-model="editableTabsValue" class="tab-edit-category" type="card" editable @edit="handleTabsEdit">
<el-tab-pane
v-for="(item, index) in module.tabs"
:key="index"
:label="tabTitleLanguage(item.title)"
:name="index + ''"
>
<div class="tab-info">
<div class="module-edit-group">
<div class="module-edit-title">配置标题</div>
<text-i18n v-model="item.title"></text-i18n>
</div>
<div class="module-edit-group">
<div class="module-edit-title">商品</div>
<div class="autocomplete-group-wrapper">
<el-autocomplete
class="inline-input"
v-model="keyword"
value-key="name"
size="small"
:fetch-suggestions="querySearch"
placeholder="请输入关键字搜索"
:trigger-on-focus="false"
:highlight-first-item="true"
@select="handleSelect"
></el-autocomplete>
<div class="item-group-wrapper" v-loading="loading">
<template v-if="productData.length">
<draggable
ghost-class="dragabble-ghost"
:list="productData"
@change="itemChange"
:options="{animation: 330}"
>
<div v-for="(item, index) in productData" :key="index" class="item">
<span>${item.name}</span>
<i class="fa fa-minus-circle" @click="removeProduct(index)"></i>
</div>
</draggable>
</template>
<template v-else>请添加商品</template>
</div>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script type="text/javascript">
Vue.component('module-editor-product-tab', {
delimiters: ['${', '}'],
template: '#module-editor-product-tab-template',
props: ['module'],
data: function () {
return {
keyword: '',
productData: [],
loading: null,
editableTabsValue: '0',
}
},
watch: {
module: {
handler: function (val) {
this.$emit('on-changed', val);
},
deep: true
},
editableTabsValue() {
this.productData = [];
this.tabsValueProductData();
}
},
created: function () {
this.tabsValueProductData();
},
computed: {
},
methods: {
tabTitleLanguage(titles) {
return titles[{{ current_language_code() }}];
},
tabsValueProductData() {
var that = this;
if (!this.module.tabs[0].products.length) return;
this.loading = true;
$.ajax({
url: 'index.php?route=extension/theme/default/page/module/product/productsByIds',
data: {product_ids: this.module.tabs[this.editableTabsValue].products},
type: 'post',
dataType: 'json',
success: function (json) {
if (json) {
that.loading = false;
that.productData = json;
}
}
});
},
querySearch(keyword, cb) {
if (!keyword) {
return;
}
$.ajax({
url: 'index.php?route=extension/theme/default/page/module/product/autocomplete&filter_name=' + encodeURIComponent(keyword),
dataType: 'json',
success: function (json) {
if (json) {
cb(json);
}
}
});
},
handleSelect(item) {
if (!this.module.tabs[this.editableTabsValue].products.find(v => v == item.product_id)) {
this.module.tabs[this.editableTabsValue].products.push(item.product_id * 1);
this.productData.push(item);
}
this.keyword = ""
},
itemChange(evt) {
this.module.tabs[this.editableTabsValue].products = this.productData.map(e => e.product_id * 1);
},
removeProduct(index) {
this.productData.splice(index, 1)
this.module.tabs[this.editableTabsValue].products.splice(index, 1);
},
handleTabsEdit(targetName, action) {
if (action === 'add') {
this.module.tabs.push({title: languagesFill('标题'), products: []});
this.editableTabsValue = this.module.tabs.length - 1 + '';
}
if (action === 'remove') {
let tabs = this.module.tabs;
tabs.splice(targetName, 1);
let activeName = this.editableTabsValue == 0 ? '0' : targetName * 1 - 1 + '';
this.editableTabsValue = activeName;
this.module.tabs = tabs.filter(tab => tab.name !== targetName);
}
}
}
});
</script>