wip
This commit is contained in:
parent
9eac191b3a
commit
3f18ce69ca
|
|
@ -19,7 +19,7 @@ class DesignController extends Controller
|
|||
public function index(Request $request): View
|
||||
{
|
||||
$data = [
|
||||
'editors' => ['editor-slide_show', 'editor-image401'],
|
||||
'editors' => ['editor-slide_show', 'editor-image401', 'editor-product'],
|
||||
'languages' => LanguageRepo::all(),
|
||||
'design_settings' => system_setting('base.design_setting'),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
/**
|
||||
* Render.php
|
||||
*
|
||||
* @copyright 2022 opencart.cn - All Rights Reserved
|
||||
* @link http://www.guangdawangluo.com
|
||||
* @author Edward Yang <yangjin@opencart.cn>
|
||||
* @created 2022-07-08 17:09:15
|
||||
* @modified 2022-07-08 17:09:15
|
||||
*/
|
||||
|
||||
namespace Beike\Admin\View\DesignBuilders;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
class Product extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function render(): View
|
||||
{
|
||||
$data['register'] = [
|
||||
'code' => 'product',
|
||||
'sort' => 0,
|
||||
'name' => '推荐商品',
|
||||
'icon' => '',
|
||||
];
|
||||
|
||||
return view('admin::pages.design.module.product', $data);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,9 @@ body.page-design {
|
|||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
body.page-design [class*=" el-icon-"], body.page-design [class^=el-icon-] {
|
||||
font-weight: 600;
|
||||
}
|
||||
body.page-design .tag {
|
||||
margin: 8px 0;
|
||||
color: #777;
|
||||
|
|
@ -51,6 +54,12 @@ body.page-design .design-box .design-head > div {
|
|||
font-size: 0.8rem;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
body.page-design .design-box .design-head > div.save-btn {
|
||||
border-right: 1px solid #5692ff;
|
||||
}
|
||||
body.page-design .design-box .design-head > div i {
|
||||
margin-right: 7px;
|
||||
}
|
||||
body.page-design .design-box .design-head > div:hover {
|
||||
background-color: #005bcc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ body.page-design {
|
|||
height: 100vh;
|
||||
overflow: hidden;
|
||||
|
||||
[class*=" el-icon-"], [class^=el-icon-] {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin: 8px 0;
|
||||
color: #777;
|
||||
|
|
@ -42,6 +46,14 @@ body.page-design {
|
|||
font-size: .8rem;
|
||||
transition: all .2s ease-in-out;
|
||||
|
||||
&.save-btn {
|
||||
border-right: 1px solid #5692ff;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken($main_color, 10%);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,13 @@
|
|||
<div class="design-box">
|
||||
<div class="sidebar-edit-wrap" id="app" v-cloak>
|
||||
<div class="design-head">
|
||||
<div @click="saveButtonClicked">保存</div>
|
||||
<div @click="exitDesign">退出</div>
|
||||
<template v-if="design.editType == 'add'">
|
||||
<div @click="saveButtonClicked" class="save-btn"><i class="el-icon-check"></i>保存</div>
|
||||
<div @click="exitDesign"><i class="el-icon-switch-button"></i>退出</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div @click="showAllModuleButtonClicked"><i class="el-icon-back"></i>返回</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="module-edit" v-if="form.modules.length > 0 && design.editType == 'module'">
|
||||
<component
|
||||
|
|
@ -62,6 +67,15 @@
|
|||
var $languages = @json($languages);
|
||||
var $language_id = '{{ current_language_code() }}';
|
||||
|
||||
function languagesFill(text) {
|
||||
var obj = {};
|
||||
$languages.map(e => {
|
||||
obj[e.code] = text
|
||||
})
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Vue.prototype.thumbnail = function thumbnail(image, width, height) {
|
||||
return '{{ asset('catalog') }}' + image;
|
||||
};
|
||||
|
|
@ -78,9 +92,13 @@
|
|||
previewWindow = document.getElementById("preview-iframe").contentWindow;
|
||||
app.design.ready = true;
|
||||
app.design.sidebar = true;
|
||||
$(previewWindow.document).find('.module-edit .edit').on('click', function(event) {
|
||||
// console.log($(this).parents('.module-item').prop('id'))
|
||||
window.parent.postMessage({index: 0}, '*')
|
||||
|
||||
$(previewWindow.document).on('click', '.module-edit .edit', function(event) {
|
||||
// module-b0448efb0989 删除 module-
|
||||
const module_id = $(this).parents('.module-item').prop('id').replace('module-', '');
|
||||
const modules = app.form.modules;
|
||||
const editingModuleIndex = modules.findIndex(e => e.module_id == module_id);
|
||||
app.editModuleButtonClicked(editingModuleIndex);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -135,17 +153,24 @@
|
|||
moduleUpdated(module) {
|
||||
const data = this.form.modules[this.design.editingModuleIndex]
|
||||
|
||||
$http.post('design/builder/preview', data, {hload: true}).then((res) => {
|
||||
// layer.msg(res.message)
|
||||
console.log(res)
|
||||
// $(previewWindow.document).find('.module-edit .edit').on('click', function(event) {
|
||||
// });
|
||||
$http.post('design/builder/preview?design=1', data, {hload: true}).then((res) => {
|
||||
$(previewWindow.document).find('#module-' + data.module_id).replaceWith(res);
|
||||
})
|
||||
// console.log(module)
|
||||
},
|
||||
|
||||
addModuleButtonClicked(code) {
|
||||
console.log(code)
|
||||
const sourceModule = this.source.modules.find(e => e.code == code)
|
||||
const _data = {
|
||||
code: code,
|
||||
content: sourceModule.make,
|
||||
module_id: '',
|
||||
name: sourceModule.name,
|
||||
}
|
||||
|
||||
$http.post('design/builder', _data).then((res) => {
|
||||
// layer.msg(res.message)
|
||||
// $(previewWindow.document).find('#module-' + data.module_id + ' .module-info').replaceWith(res);
|
||||
})
|
||||
},
|
||||
|
||||
// 编辑模块
|
||||
|
|
@ -162,6 +187,11 @@
|
|||
|
||||
exitDesign() {
|
||||
location = '/';
|
||||
},
|
||||
|
||||
showAllModuleButtonClicked() {
|
||||
this.design.editType = 'add';
|
||||
this.design.editingModuleIndex = 0;
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
|
@ -171,12 +201,12 @@
|
|||
},
|
||||
})
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
event.stopPropagation()
|
||||
if (typeof(event.data.index) !== 'undefined') {
|
||||
app.editModuleButtonClicked(event.data.index)
|
||||
}
|
||||
}, false)
|
||||
// window.addEventListener('message', (event) => {
|
||||
// event.stopPropagation()
|
||||
// if (typeof(event.data.index) !== 'undefined') {
|
||||
// app.editModuleButtonClicked(event.data.index)
|
||||
// }
|
||||
// }, false)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@
|
|||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
setTimeout(() => {
|
||||
app.source.modules.push(@json($register))
|
||||
}, 100)
|
||||
Vue.component('module-editor-image-401', {
|
||||
template: '#module-editor-image-401-template',
|
||||
|
||||
|
|
@ -59,4 +56,52 @@ Vue.component('module-editor-image-401', {
|
|||
},
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const make = {
|
||||
style: {
|
||||
background_color: ''
|
||||
},
|
||||
floor: languagesFill(''),
|
||||
images: [
|
||||
{
|
||||
image: languagesFill('image/default/image_plus_1.png'),
|
||||
show: true,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
},
|
||||
{
|
||||
image: languagesFill('image/default/image_plus_2.png'),
|
||||
show: false,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
},
|
||||
{
|
||||
image: languagesFill('image/default/image_plus_3.png'),
|
||||
show: false,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
},
|
||||
{
|
||||
image: languagesFill('image/default/image_plus_4.png'),
|
||||
show: false,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
let register = @json($register);
|
||||
|
||||
register.make = make;
|
||||
app.source.modules.push(register)
|
||||
}, 100)
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
<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>
|
||||
|
|
@ -50,10 +50,6 @@
|
|||
|
||||
<script type="text/javascript">
|
||||
|
||||
setTimeout(() => {
|
||||
app.source.modules.push(@json($register))
|
||||
}, 100)
|
||||
|
||||
Vue.component('module-editor-slideshow', {
|
||||
template: '#module-editor-slideshow-template',
|
||||
|
||||
|
|
@ -96,4 +92,37 @@ Vue.component('module-editor-slideshow', {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const make = {
|
||||
style: {
|
||||
background_color: ''
|
||||
},
|
||||
full: true,
|
||||
floor: languagesFill(''),
|
||||
images: [
|
||||
{
|
||||
image: languagesFill('/demo/banner.png'),
|
||||
show: true,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
},
|
||||
{
|
||||
image: languagesFill('/demo/banner.png'),
|
||||
show: false,
|
||||
link: {
|
||||
type: 'product',
|
||||
value:''
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
let register = @json($register);
|
||||
|
||||
register.make = make;
|
||||
app.source.modules.push(register)
|
||||
}, 100)
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
|
||||
@if ($design)
|
||||
<div class="module-edit">
|
||||
<div class="edit-wrap">
|
||||
<div class=""><i class="bi bi-chevron-down"></i></div>
|
||||
<div class=""><i class="bi bi-chevron-up"></i></div>
|
||||
<div class="delete"><i class="bi bi-x-lg"></i></div>
|
||||
<div class="edit"><i class="bi bi-pencil-square"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="module-info">
|
||||
<div class="module-title">推荐品牌模块</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@for ($i = 0; $i < 8; $i++)
|
||||
<div class="col-6 col-md-4 col-lg-3">
|
||||
<div class="brand-item"><img src="{{ asset('image/default/banner-1.png') }}" class="img-fluid"></div>
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
|
@ -28,9 +28,7 @@
|
|||
<div class="swiper-button-next"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@push('add-scripts')
|
||||
<script>
|
||||
new Swiper ('.module-swiper-{{ $module_id }}', {
|
||||
loop: true, // 循环模式选项
|
||||
|
|
@ -50,6 +48,7 @@
|
|||
},
|
||||
})
|
||||
</script>
|
||||
@endpush
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue