初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
<link rel="stylesheet" href="STATIC_EXT/colorPicker/css/colorpicker.css" />
<link rel="stylesheet" href="STATIC_EXT/diyview/css/diyview.css?time=20240316" />
<link rel="stylesheet" href="STATIC_EXT/diyview/css/bottom_nav_design.css" />
<div id="bottomNav" class="layui-form">
<div class="preview">
<div class="preview-head">
<span>底部导航</span>
</div>
<div class="preview-block">
<ul v-show="data.list.length>0" :style="{ backgroundColor : data.backgroundColor }">
<li v-for="(item,index) in data.list" @mouseover="mouseOver(index)" @mouseout="mouseOut()" :key="item.id">
<div v-show="data.type == 1 || data.type == 2">
<template v-if="selected == index">
<img v-if="item.selected_icon_type == 'img'" :src="(selected == index ? (item.selectedIconPath? changeImgUrl(item.selectedIconPath) : changeImgUrl('public/static/img/default_img/square.png')) : (item.iconPath? changeImgUrl(item.iconPath) : changeImgUrl('public/static/img/default_img/square.png')) )"/>
<iconfont v-else :icon="selected == index ? item.selectedIconPath : item.iconPath" :value="selected == index ? (item.selected_style ? item.selected_style : null) :(item.style ? item.style : null)"></iconfont>
</template>
<template v-else>
<img v-if="item.icon_type == 'img'" :src="(selected == index ? (item.selectedIconPath? changeImgUrl(item.selectedIconPath) : changeImgUrl('public/static/img/default_img/square.png')) : (item.iconPath? changeImgUrl(item.iconPath) : changeImgUrl('public/static/img/default_img/square.png')) )"/>
<iconfont v-else :icon="selected == index ? item.selectedIconPath : item.iconPath" :value="selected == index ? (item.selected_style ? item.selected_style : null) :(item.style ? item.style : null)"></iconfont>
</template>
</div>
<span :style="{ fontSize : ( data.fontSize + 'px'), color : (selected == index ? data.textHoverColor : data.textColor ) }" v-show="data.type == 1 || data.type == 3">{{ item.text }}</span>
</li>
</ul>
</div>
<div class="custom-save">
<button class="layui-btn save">保存</button>
</div>
</div>
<div class="edit-attribute">
<bottom-menu></bottom-menu>
</div>
</div>
{if condition="$bottom_nav_info"}
<input type="hidden" id="info" value='{:json_encode($bottom_nav_info)}' />
{/if}
<script>
{if condition="$bottom_nav_info"}
var bottomNavInfo = JSON.parse($("#info").val().toString());
{else/}
var bottomNavInfo = null;
{/if}
</script>
<script src="STATIC_JS/vue.js"></script>
{include file="diy/iconfont_component"/}
<script src="STATIC_EXT/colorPicker/js/colorpicker.js"></script>
<script src="STATIC_EXT/diyview/js/ddsort.js"></script>
<script src="STATIC_EXT/diyview/js/components.js"></script>
<script src="STATIC_EXT/diyview/js/shop_bottom_nav.js?time=20241119"></script>

160
app/shop/view/diy/edit.html Executable file
View File

@@ -0,0 +1,160 @@
<link rel="stylesheet" href="STATIC_EXT/colorPicker/css/colorpicker.css" />
<link rel="stylesheet" href="STATIC_EXT/diyview/css/diyview.css?time=20240316" />
<div class="custom-save js-top-custom-save layui-hide">
<span></span>
<div class="button-group">
<button class="layui-btn save-button save">保存</button>
{notempty name="$diy_view_info"}
<button class="layui-btn" onclick="preview()">预览</button>
{/notempty}
<button class="layui-btn layui-btn-primary cancel-btn">取消</button>
</div>
</div>
<div id="diyView">
<!-- 组件列表 -->
<div class="component-list">
<div class="tab">
<span class="selected">内置组件</span>
<span data-type="EXTEND">第三方组件</span>
</div>
<nav>
{foreach name="$diy_view_utils" item="vo" key="k"}
<h3 data-index="{$k}" data-type="{$vo.type}" {if $vo['type'] == 'EXTEND'}style="display:none;"{/if}><img src="__STATIC__/ext/diyview/img/component_down.png" />{$vo.type_name}</h3>
<ul data-index="{$k}" data-type="{$vo.type}" {if $vo['type'] == 'EXTEND'}style="display:none;"{/if}>
{if $vo['type'] == 'SYSTEM'}
<li title="弹窗广告" @click='changeCurrentIndex(-98)'>
<i class="iconfont icondanchuangguanggao"></i>
<span>弹窗广告</span>
</li>
{/if}
{foreach name="$vo.list" item="li" key="li_k"}
<li title="{$li.title}" data-name="{$li.name}" data-max-count="{$li.max_count}" data-value='{$li.value}' data-is-delete="{$li.is_delete}" data-addon-name="{$li.addon_name}"
{if condition="$li.value"} @click='addComponent({$li.value},{ name : "{$li.name}", title : "{$li.title}", max_count : {$li.max_count}, addon_name : "{$li.addon_name}", is_delete : "{$li.is_delete}" })'
:class="{ 'disabled' : !checkComponentIsAdd('{$li.name}') }"
{else/}class="disabled"{/if}>
<i class="{$li.icon}"></i>
<span>{$li.title}</span>
</li>
{/foreach}
</ul>
{/foreach}
</nav>
</div>
<div class="preview-wrap">
<div class="loading-layer">
<div class="loading-anim">
<div class="box item"><div class="border out item"></div></div>
</div>
</div>
<div class="preview-restore-wrap">
<div class="div-wrap">
<button class="layui-btn layui-btn-primary position-page-btn" @click="changeCurrentIndex(-99)">页面设置</button>
<!-- 快捷操作 -->
<ul class="quick-action">
<!-- <li>-->
<!-- <i class="icondiy icon-system-eye-line"></i>-->
<!-- <span>隐藏</span>-->
<!-- </li>-->
<li @click="moveUpComponent()" :class="{ disabled : ((currentIndex - 1) < 0) }">
<i class="icondiy icon-system-jiantoushang"></i>
<span>上移</span>
</li>
<li @click="moveDownComponent()" :class="{ disabled : ( currentIndex < 0 || data.length === 0 || (currentIndex + 1) === data.length) }">
<i class="icondiy icon-system-jiantouxia"></i>
<span>下移</span>
</li>
<li @click="copyComponent()" :class="{ disabled : ( currentIndex < 0) }">
<i class="icondiy icon-system-file-copy-line"></i>
<span>复制</span>
</li>
<li @click="delComponent(currentIndex)" :class="{ disabled : currentIndex < -1 }">
<i class="icondiy icon-system-delete-bin-6-line"></i>
<span>删除</span>
</li>
<li @click="resetComponent()" :class="{ disabled : ( currentIndex < 0) }">
<i class="icondiy icon-system-loader-4-line"></i>
<span>重置</span>
</li>
</ul>
<div class='diy-view-wrap layui-form' :style="{ backgroundColor : global.pageBgColor,backgroundImage : 'url('+changeImgUrl(global.bgUrl)+')' }">
<div class="preview-head" @click="changeCurrentIndex(-99)">
<!-- 顶部tabbar风格 -->
<tabbar :current-index="currentIndex" :global="global"></tabbar>
<!-- 页面设置 -->
<div class="page-set-wrap" :class="{ selected : currentIndex == -99 }" :data-sort="-99" v-show="data.length == 0 || currentIndex == -99">
<page-set :current-index="currentIndex" :global="global" :global-lazy-load="globalLazyLoad"></page-set>
</div>
</div>
<!-- 弹窗广告 -->
<pop-window :current-index="currentIndex" :global="global" :global-lazy-load="globalLazyLoad"></pop-window>
<div class="preview-block">
<div v-for="(nc,index) in data" :key="nc.id" :data-index="index" :data-id="nc.id" :class="{ 'draggable-element' : true,selected : currentIndex == index }" :data-sort="index">
{foreach name="$diy_view_utils" item="vo"}
{foreach name="$vo.list" item="li"}
<template v-if="nc.componentName == '{$li.name}'">
{:event('DiyViewUtils',[ 'name' => $li['name'], 'addon_name' => $li['addon_name'] ],true)}
</template>
{/foreach}
{/foreach}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 预览 -->
<template slot="preview"></template>
<div class="custom-save js-bottom-custom-save">
<button class="layui-btn save">保存</button>
{notempty name="$diy_view_info"}
<button class="layui-btn" onclick="preview()">预览</button>
{/notempty}
<button class="layui-btn full-screen-btn">全屏</button>
</div>
</div>
{if condition="!empty($diy_view_info)"}
<input type="hidden" id="id" value="{$diy_view_info.id}">
<input type="hidden" id="info" value='' />
{/if}
<input type="hidden" id="name" value="{$name}" />
<input type="hidden" id="title" value="{$title}" />
<input type="hidden" id="template_id" value="{$template_id}" />
<input type="hidden" id="page_type" value="{$page_type ?? ''}" />
<script>
var requestUrl = '{$request_url}';
var storeIsExit = '{$store_is_exit}';
//直接在隐藏域中写入,有些单引号和双引号会无法解析,导致字符串被截断
$("#info").val(JSON.stringify({php}echo $diy_view_info['value'] ?? '';{/php}));
</script>
<script src="STATIC_JS/vue.js"></script>
<script src="STATIC_EXT/colorPicker/js/colorpicker.js"></script>
<script src="STATIC_EXT/diyview/js/async_load_css.js"></script>
<script src="STATIC_EXT/diyview/js/ddsort.js"></script>
<script src="STATIC_EXT/ueditor/ueditor.config.js?time=20240614"></script>
<script src="STATIC_EXT/ueditor/ueditor.all.js?time=20240614"> </script>
<script src="STATIC_EXT/ueditor/lang/zh-cn/zh-cn.js"></script>
<script src="STATIC_EXT/diyview/js/components.js?time=20250312"></script>
<script src="STATIC_EXT/diyview/js/custom_template.js?time=20250312"></script>
{include file="app/shop/view/diy/iconfont_component.html"/}

765
app/shop/view/diy/heat_map.html Executable file
View File

@@ -0,0 +1,765 @@
<style>
.content-box {
position: relative;
width: 600px;
height: 600px;
background-color: rgb(242, 244, 244);
border: 1px dashed #333;
background-size: 100% 100%;
box-sizing: border-box;
}
.box {
width: 100px;
height: 100px;
background-color: rgba(255, 255, 255, 0.7);
border: 1px solid #ccc;
position: absolute;
left: 0px;
top: 0px;
}
.box1, .box2, .box3, .box4 {
width: 10px;
height: 10px;
background-color: #fff;
position: absolute;
border-radius: 50%;
border: 1px solid #333;
}
.box1 {
top: -5px;
left: -5px;
cursor: nw-resize;
}
.box2 {
top: -5px;
right: -5px;
cursor: ne-resize;
}
.box3 {
left: -5px;
bottom: -5px;
cursor: sw-resize;
}
.box4 {
bottom: -5px;
right: -5px;
cursor: se-resize;
}
.heat-map-wrap {
display: flex;
align-items: flex-start;
width: 900px;
margin: 0 auto;
padding: 30px;
}
.heat-map-wrap .area-box {
width: 100px;
height: 100px;
position: absolute;
top: 0;
left: 0;
user-select: none;
cursor: move;
border: 1px solid #ccc;
padding: 5px;
box-sizing: border-box;
}
.heat-map-wrap .manage-wrap {
padding-left: 20px;
}
.heat-map-wrap .manage-wrap h3 {
margin-bottom: 10px;
font-size: 16px;
}
.heat-map-wrap .manage-wrap button {
margin-bottom: 10px;
}
.heat-map-wrap .manage-wrap .list-wrap {
overflow-y: auto;
height: 500px;
}
.heat-map-wrap .manage-wrap .list-wrap .item {
margin-bottom: 16px;
display: flex;
}
.heat-map-wrap .manage-wrap .list-wrap .item label {
width: 80px;
padding-right: 10px;
text-align: right;
}
.heat-map-wrap .manage-wrap .list-wrap .item div span {
cursor: pointer;
}
.heat-map-wrap .manage-wrap .list-wrap .item div i {
cursor: pointer;
margin: 0 10px;
}
</style>
<div class="layui-form heat-map-wrap">
<div class="content-box" id="content_box"><!-- 热区列表 --></div>
<div class="manage-wrap">
<h3>热区管理</h3>
<button class="layui-btn" id="addArea">添加热区</button>
<div class="list-wrap"><!-- 热区列表 --></div>
</div>
</div>
<script type="text/html" id="dragBoxHtml">
{{# for(let i=0;i<d.length;i++){ }}
<div id="box_{{ i }}" class="area-box" style="left:{{ d[i].left }}{{ d[i].unit }};top:{{ d[i].top }}{{ d[i].unit }};width:{{ d[i].width }}{{ d[i].unit }};height:{{ d[i].height }}{{ d[i].unit }}" onmousedown="mouseDown(event,{{ i }})">
<span>{{ i + 1 }}</span>
{{# if(d[i].link.title){ }}
<span class="p-[4px]">|</span>
<span>{{ d[i].link.title }}</span>
{{# } }}
<span class="box1" onmousedown="resizeMouseDown(event,{{ i }})"></span>
<span class="box2" onmousedown="resizeMouseDown(event,{{ i }})"></span>
<span class="box3" onmousedown="resizeMouseDown(event,{{ i }})"></span>
<span class="box4" onmousedown="resizeMouseDown(event,{{ i }})"></span>
</div>
{{# } }}
</script>
<script type="text/html" id="manageHotAreaHtml">
{{# for(let i=0;i<d.length;i++){ }}
<div class="item">
<label>热区{{ i+1 }}</label>
<div>
{{# if(d[i].link.title){ }}
<span data-index="{{i}}" class="text-color">{{ d[i].link.title }}</span>
{{# }else{ }}
<span data-index="{{i}}">选择跳转链接</span>
{{# } }}
<i class="icondiy icon-system-delete-bin-6-line" onclick="deleteHotArea({{i}})"></i>
</div>
</div>
{{# } }}
</script>
<script>
// 热区设置数据
var imageData = JSON.parse(sessionStorage.getItem('imageData'));
var dragBoxArr = [];
var contentBoxWidth = 600;
var contentBoxHeight = 600;
var num = 6;// 每行显示的数量
var laytpl,form,layer;
layui.use(['form','layer','laytpl'], function() {
layer = layui.layer;
laytpl = layui.laytpl;
form = layui.form;
form.render();
if (imageData == null) return;
if (Object.keys(imageData.heatMapData).length) {
dragBoxArr.splice(0, dragBoxArr.length, ...imageData.heatMapData);
} else {
dragBoxArr.splice(0, dragBoxArr.length);
$("#addArea").click();
}
$("#content_box").css({
backgroundImage: "url(" + ns.img(imageData.imageUrl) + ")",
width: contentBoxWidth + 'px',
height: contentBoxHeight + 'px'
});
renderDragBox();
});
// 增加热区
$("#addArea").click(function() {
let left = dragBoxArr.length % num * 100;
let top = Math.floor(dragBoxArr.length / num) * 100;
if (top >= contentBoxWidth) {
top = 0;
left = 0;
}
dragBoxArr.push({
left: left,
top: top,
width: 100,
height: 100,
unit: 'px',
link: {
name: ''
}
});
renderDragBox();
});
// 渲染热区
function renderDragBox() {
laytpl($('#dragBoxHtml').html()).render(dragBoxArr,function(html){
$('#content_box').html(html);
});
laytpl($('#manageHotAreaHtml').html()).render(dragBoxArr,function(html){
$('.heat-map-wrap .manage-wrap .list-wrap').html(html);
});
}
// 选择跳转链接
$('body').off('click','.heat-map-wrap .manage-wrap .list-wrap .item div span').on('click','.heat-map-wrap .manage-wrap .list-wrap .item div span',function () {
let index = $(this).attr('data-index');
dragBoxArr[index].link = dragBoxArr[index].link || {};
ns.select_link(dragBoxArr[index].link, function (data) {
dragBoxArr[index].link = data;
renderDragBox();
});
});
// 删除热区
function deleteHotArea(index) {
dragBoxArr.splice(index,1);
renderDragBox();
}
// 移动事件
function mouseDown(e, index) {
let box = document.getElementById('box_' + index);
let disX = e.clientX - box.offsetLeft;
let disY = e.clientY - box.offsetTop;
//鼠标移动时
document.onmousemove = function (e) {
box.style.left = e.clientX - disX + 'px';
box.style.top = e.clientY - disY + 'px';
//边界判断
if (e.clientX - disX < 0) {
box.style.left = 0;
}
if (e.clientX - disX > contentBoxWidth - box.offsetWidth) {
box.style.left = contentBoxWidth - box.offsetWidth + 'px';
}
if (e.clientY - disY < 0) {
box.style.top = 0;
}
if (e.clientY - disY > contentBoxHeight - box.offsetHeight) {
box.style.top = contentBoxHeight - box.offsetHeight + 'px';
}
dragBoxArr[index].left = box.offsetLeft;
dragBoxArr[index].top = box.offsetTop;
dragBoxArr[index].width = box.offsetWidth;
dragBoxArr[index].height = box.offsetHeight;
dragBoxArr[index].unit = 'px';
};
//鼠标抬起时
document.onmouseup = function (e) {
document.onmousemove = null;
}
}
// 拖拽大小事件
function resizeMouseDown(e,index) {
var oEv = e;
oEv.stopPropagation();
let box = document.getElementById('box_' + index);
let className = e.target.className;
// 获取移动前盒子的宽高,
var oldWidth = box.offsetWidth;
var oldHeight = box.offsetHeight;
// 获取鼠标距离屏幕的left和top值
var oldX = oEv.clientX;
var oldY = oEv.clientY;
// 元素相对于最近的父级定位
var oldLeft = box.offsetLeft;
var oldTop = box.offsetTop;
// 设置最小的宽度
var minWidth = 50;
var minHeight = 50;
document.onmousemove = function (e) {
var oEv = e;
// console.log('move', "width" + oldWidth,
// 'oldLeft: ' + oldLeft, 'oldTop: ' + oldTop,
// 'oldXclientX-- ' + oldX + '' + oEv.clientX,
// 'oldYclientY-- ' + oldY + '' + oEv.clientY,
// )
// 左上角
if (className == "box1") {
let width = oldWidth - (oEv.clientX - oldX);
let maxWidth = contentBoxWidth;
let height = oldHeight - (oEv.clientY - oldY);
let maxHeight = contentBoxHeight - oldTop;
let left = oldLeft + (oEv.clientX - oldX);
let top = oldTop + (oEv.clientY - oldY);
if (width < minWidth) {
width = minWidth
}
if (width > maxWidth) {
width = maxWidth
}
if (height < minHeight) {
height = minHeight
}
if (height > maxHeight) {
height = maxHeight
}
if (oldLeft == 0 && oldTop == 0) {
// 坐标left = 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 最小宽度top = 最小高度
left = minWidth;
top = minHeight
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 最小宽度top = 不予处理
left = minWidth;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值left = 不予处理top = 最小高度
top = minHeight
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值left = 不予处理top = 不予处理
}
} else if (oldLeft == 0 && oldTop > 0) {
// 坐标left = 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 最小宽度top = 元素上偏移位置
left = minWidth;
top = box.offsetTop
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 最小宽度top = 元素上偏移位置
left = minWidth;
top = box.offsetTop;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值left = 不予处理top = 元素上偏移位置
top = box.offsetTop;
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值left = 不予处理top = 不予处理
}
} else if (oldLeft > 0 && oldTop == 0) {
// 坐标left > 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 元素左偏移位置top = 元素上偏移位置
left = box.offsetLeft;
top = box.offsetTop;
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 元素左偏移位置top = 0
left = box.offsetLeft;
top = 0;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值left = 不予处理top = 元素上偏移位置
top = box.offsetTop;
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值left = 不予处理top = 不予处理
}
} else if (oldLeft > 0 && oldTop > 0) {
// 坐标left > 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 元素左偏移位置top = 元素上偏移位置
left = box.offsetLeft;
top = box.offsetTop
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 元素左偏移位置top = 元素上偏移位置
left = box.offsetLeft;
top = box.offsetTop;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值left = 不予处理top = 元素上偏移位置
top = box.offsetTop;
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值left = 不予处理top = 不予处理
}
}
//左上 宽
if (left < 0) {
left = 0;
width = oldWidth - (oEv.clientX - oldX) + (oldLeft + (oEv.clientX - oldX));
}
//左上 高
if (top < 0) {
top = 0;
height = oldTop + (oEv.clientY - oldY) + (oldHeight - (oEv.clientY - oldY));
}
box.style.width = width + 'px';
box.style.height = height + 'px';
box.style.left = left + 'px';
box.style.top = top + 'px';
} else if (className == "box2") {
// 右上角
let width = oldWidth + (oEv.clientX - oldX);
let maxWidth = contentBoxWidth - oldLeft;
let height = oldHeight - (oEv.clientY - oldY);
let maxHeight = contentBoxHeight - oldTop;
let top = oldTop + (oEv.clientY - oldY);
if (width < minWidth) {
width = minWidth
}
if (width > maxWidth) {
width = maxWidth
}
if (height < minHeight) {
height = minHeight
}
if (height > maxHeight) {
height = maxHeight
}
if (oldLeft == 0 && oldTop == 0) {
// 坐标left = 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值top = 最小高度
top = minHeight
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值,不予处理
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值top = 最小高度
top = minHeight
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft == 0 && oldTop > 0) {
// 坐标left = 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft > 0 && oldTop == 0) {
// 坐标left = 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值top = 0
top = 0
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft > 0 && oldTop > 0) {
// 坐标left > 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值top = 元素上偏移位置
top = box.offsetTop
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
}
//右上 高
if (top < 0) {
top = 0;
height = oldTop + (oEv.clientY - oldY) + (oldHeight - (oEv.clientY - oldY))
}
box.style.width = width + 'px';
box.style.height = height + 'px';
box.style.top = top + 'px';
} else if (className == "box3") {
// 左下角
let width = oldWidth - (oEv.clientX - oldX);
let maxWidth = contentBoxWidth;
let height = oldHeight + (oEv.clientY - oldY);
let maxHeight = contentBoxHeight - oldTop;
let left = oldLeft + (oEv.clientX - oldX);
if (width < minWidth) {
width = minWidth
}
if (width > maxWidth) {
width = maxWidth
}
if (height < minHeight) {
height = minHeight
}
if (height > maxHeight) {
height = maxHeight
}
if (oldLeft == 0 && oldTop == 0) {
// 坐标left = 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 最小宽度
left = minWidth;
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 最小宽度
left = minWidth;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值,不予处理
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft == 0 && oldTop > 0) {
// 坐标left = 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 最小宽度
left = minWidth;
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 最小宽度
left = minWidth;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值,不予处理
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft > 0 && oldTop == 0) {
// 坐标left > 0top = 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 元素左偏移位置
left = box.offsetLeft;
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 元素左偏移位置
left = box.offsetLeft;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值,不予处理
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
} else if (oldLeft > 0 && oldTop > 0) {
// 坐标left > 0top > 0
if (width == minWidth && height == minHeight) {
// 宽高 = 最小值left = 元素左偏移位置
left = box.offsetLeft;
} else if (width == minWidth && height > minHeight) {
// 宽 = 最小值,高 > 最小值left = 元素左偏移位置
left = box.offsetLeft;
} else if (width > minWidth && height == minHeight) {
// 宽 > 最小值,高 = 最小值,不予处理
} else if (width > minWidth && height > minHeight) {
// 宽 > 最小值,高 > 最小值,不予处理
}
}
if (left < 0) {
left = 0;
width = oldWidth - (oEv.clientX - oldX) + (oldLeft + (oEv.clientX - oldX));
}
box.style.width = width + 'px';
box.style.height = height + 'px';
box.style.left = left + 'px';
} else if (className == "box4") {
// 右下角
let width = oldWidth + (oEv.clientX - oldX);
let maxWidth = contentBoxWidth - oldLeft;
let height = oldHeight + (oEv.clientY - oldY);
let maxHeight = contentBoxHeight - oldTop;
if (width < minWidth) {
width = minWidth
}
if (width > maxWidth) {
width = maxWidth
}
if (height < minHeight) {
height = minHeight
}
if (height > maxHeight) {
height = maxHeight
}
box.style.width = width + 'px';
box.style.height = height + 'px';
}
dragBoxArr[index].left = box.offsetLeft;
dragBoxArr[index].top = box.offsetTop;
dragBoxArr[index].width = box.offsetWidth;
dragBoxArr[index].height = box.offsetHeight;
dragBoxArr[index].unit = 'px';
};
// 鼠标抬起时
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
//获取操作结果
function heatMapListener(callback){
var isOk = true;
for (let i = 0; i < dragBoxArr.length; i++) {
if (!dragBoxArr[i].link.title) {
layer.msg('请选择热区'+ (i + 1) + '的链接地址');
isOk = false;
break;
}
}
if (!isOk) return;
dragBoxArr.forEach((item, index) => {
var box = document.getElementById('box_' + index);
item.width = parseFloat(box.offsetWidth / contentBoxWidth * 100).toFixed(2);
item.height = parseFloat(box.offsetHeight / contentBoxHeight * 100).toFixed(2);
item.left = parseFloat(box.offsetLeft / contentBoxWidth * 100).toFixed(2);
item.top = parseFloat(box.offsetTop / contentBoxHeight * 100).toFixed(2);
item.unit = '%';
});
imageData.heatMapData = dragBoxArr;
if(typeof callback == 'function'){
callback(imageData);
}
}
</script>

View File

@@ -0,0 +1,47 @@
<style>
.icon-img-box{
width: 48px;
height: 48px;
margin: 0 auto;
box-sizing: border-box;
overflow: hidden;
}
.icon-img-box img{
width: 40px;
max-height: 40px;
}
</style>
<div id="{$id}">
<div class="icon-img-box" v-if="myData.iconType == 'img'">
<img :src="changeImgUrl(myData.imageUrl) || changeImgUrl('public/static/img/default_img/square.png')" alt="">
</div>
<div class="icon-img-box" v-if="myData.iconType == 'icon'" style="font-size: 36px">
<iconfont v-if="myData.icon" :icon="myData.icon" :value="(myData.style ? myData.style : null)"></iconfont>
</div>
</div>
<script src="STATIC_EXT/colorPicker/js/colorpicker.js"></script>
<script src="STATIC_JS/vue.js"></script>
{include file="diy/iconfont_component"/}
<script>
var vue,data;
data = {:json_encode($data)};
data = JSON.parse(data);
vue = new Vue({
el: "#{$id}",
data: {
myData:{}
},
created(){
this.myData = data;
},
methods: {
changeImgUrl: function (url) {
if (url == null || url === "") return '';
if (url.indexOf("static/img/") > -1) return ns.img(ns_url.staticImg + "/" + url.replace("public/static/img/", ""));
else return ns.img(url);
},
}
})
</script>

342
app/shop/view/diy/icon_style.html Executable file
View File

@@ -0,0 +1,342 @@
<style>
.layui-form {
padding: 15px;
}
.icon-block {
width: 60px;
height: 60px;
font-size: 60px;
border: 1px dashed #eee;
}
.main-icon {
width: 100px;
height: 100px;
font-size: 100px;
}
.icon-block .icon {
width: inherit;
height: inherit;
font-size: 100%;
color: #000;
display: flex;
align-items: center;
justify-content: center;
}
.icon-block .js-icon {
font-size: 50%;
line-height:1;
}
.icon-block .js-icon.gradient {
-webkit-background-clip:text!important;
-webkit-text-fill-color:transparent;
}
.icon-style {
display: flex;
flex-wrap: wrap;
}
.icon-style .icon-block {
margin: 0 10px 10px 0;
cursor: pointer;
}
.icon-style .no-style .icon {
color: #eee;
}
.icon-style .active, .icon-style .icon-block:hover {
border-color: var(--base-color);
}
.title {
font-weight: bold;
margin-bottom: 10px;
padding-left: 10px;
border-left: 2px solid var(--base-color);
line-height: 1;
margin-left: 10px;
}
.slide-wrap {
display: flex;
align-items: center;
padding-left: 10px;
}
.slide-wrap > div {
flex: 1;
}
.icon-color {
display: flex;
}
.icon-color .color-item {
border: 2px solid #d7d7d7;
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.icon-color .color-item .js-icon {
font-size: 12px;
color: #aaa;
}
.icon-color .color-item.disabled {
cursor: not-allowed;
}
.icon-color .color-item.disabled .js-icon {
color: #eee;
border-color: #eee;
}
.flexbox-fix-btn .btn {
margin: 0px;
line-height: 18px;
font-size: 12px;
}
</style>
<div id="app" class="layui-form icon-style-set">
<div class="layui-form-item">
<label class="layui-form-label">图标:</label>
<div class="layui-input-block icon-block main-icon">
<div class="icon" :style="iconBgStyle">
<i class="js-icon {$icon}" :class="{gradient: style.iconColor.length > 1}" :style="iconStyle"></i>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标风格:</label>
<div class="layui-input-block icon-style">
<div class="icon-block no-style" :class="{active: styleIndex == -1}" title="无风格" @click="selectStyle(-1)">
<div class="icon">
<i class="iconfont iconzhuanliwuxiao"></i>
</div>
</div>
<div class="icon-block" :class="{active: styleIndex == index}" v-for="(item, index) in styleList" :key="index" @click="selectStyle(index)">
<iconfont icon="{$icon}" :value="item"></iconfont>
</div>
</div>
</div>
<div class="title">图标设置</div>
<div class="layui-form-item">
<label class="layui-form-label">背景颜色</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="icon-color">
<div class="color-item" :id="'iconBgColor' + index" v-show="style.iconBgColor[index]" :style="{background: style.iconBgColor[index] ?? '#fff'}" v-for="(item, index) in 6" :key="index"></div>
<div class="color-item" :class="{disabled: style.iconBgColor.length >= 6}" @click="addColor('iconBgColor')">
<i class="iconfont iconjia"></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-show="style.iconBgColor.length > 1">
<label class="layui-form-label">渐变角度</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="icon-bgcolor-deg"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">圆角大小</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="bg-radius"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标大小</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="font-size"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标颜色</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="icon-color">
<div class="color-item" :id="'iconColor' + index" v-show="style.iconColor[index]" :style="{background: style.iconColor[index] ?? '#fff'}" v-for="(item, index) in 6" :key="index"></div>
<div class="color-item" :class="{disabled: style.iconColor.length >= 6}" @click="addColor('iconColor')">
<i class="iconfont iconjia"></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-show="style.iconColor.length > 1">
<label class="layui-form-label">渐变角度</label>
<div class="layui-input-block slide-wrap len-mid">
<div class="icon-color-deg"></div>
</div>
</div>
</div>
<script src="STATIC_EXT/colorPicker/js/colorpicker.js"></script>
<script src="STATIC_JS/vue.js"></script>
{include file="diy/iconfont_component"/}
<script>
var form,slider,colorpicker,vue,_colorPicker = {};
layui.use(['form', 'slider', 'colorpicker'], function() {
form = layui.form;
slider = layui.slider;
colorpicker = layui.colorpicker;
vue = new Vue({
el: "#app",
data: {
style: {
fontSize: 50,
iconBgColor: [],
iconBgColorDeg: 0,
iconBgImg: '',
bgRadius: 0,
iconColor: ['#000'],
iconColorDeg: 0,
},
styleIndex: -1,
styleList:{:json_encode($icon_style)}
},
methods: {
addColor(key) {
if (this.style[key].length >= 6) return;
this.style[key].push('#fff');
},
colorRender(id, color, callback){
if (_colorPicker[id]) {
_colorPicker[id].setColorByInput(color);
return;
}
_colorPicker[id] = Colorpicker.create({
el: id,
color: color,
change: function (elem, hex) {
callback(hex, elem)
}
});
},
updateArray(key){
this.style[key].push('')
this.style[key].pop()
},
selectStyle(index){
this.styleIndex = index;
if (index == -1) {
this.style = {
fontSize: 50,
iconBgColor: [],
iconBgColorDeg: 0,
iconBgImg: '',
bgRadius: 0,
iconColor: ['#000'],
iconColorDeg: 0,
}
} else {
this.style = ns.deepclone(this.styleList[index]);
}
var self = this;
setTimeout(function () {
self.style.iconBgColor.forEach(function (item, index) {
self.colorRender('iconBgColor' + index, self.style.iconBgColor[index])
})
self.style.iconColor.forEach(function (item, index) {
self.colorRender('iconColor' + index, self.style.iconColor[index])
})
})
},
img(src){
return ns.img(src);
}
},
mounted(){
if (localStorage.getItem('iconStyle')) this.style = JSON.parse(localStorage.getItem('iconStyle'));
var self = this;
slider.render({
elem: '.icon-style-set .font-size',
input: true,
value: self.style.fontSize,
min: 10,
max: 100,
change: function (value) {
self.style.fontSize = value;
}
});
slider.render({
elem: '.icon-style-set .icon-color-deg',
input: true,
max: 360,
value: self.style.iconColorDeg,
change: function (value) {
self.style.iconColorDeg = value;
}
});
slider.render({
elem: '.icon-style-set .icon-bgcolor-deg',
input: true,
max: 360,
value: self.style.iconBgColorDeg,
change: function (value) {
self.style.iconBgColorDeg = value;
}
});
slider.render({
elem: '.icon-style-set .bg-radius',
input: true,
value: self.style.bgRadius,
max: 50,
change: function (value) {
self.style.bgRadius = value;
}
});
setTimeout(function () {
for (var index = 0; index < 6; index++) {
self.colorRender('iconBgColor' + index, self.style.iconBgColor[index] ? self.style.iconBgColor[index] : '', function (color, elem) {
var _index = $(elem).index();
self.style.iconBgColor[_index] = color;
self.updateArray('iconBgColor')
})
self.colorRender('iconColor' + index, self.style.iconColor[index] ? self.style.iconColor[index] : '', function (color, elem) {
var _index = $(elem).index();
self.style.iconColor[_index] = color;
self.updateArray('iconColor')
})
}
})
},
computed: {
iconBgStyle(){
var style = {
'border-radius': this.style.bgRadius + '%',
'background': ''
};
if (this.style.iconBgImg) style['background'] += 'url('+ this.img(this.style.iconBgImg) +') no-repeat bottom / contain'
if (this.style.iconBgColor.length) {
if (style.background) style.background += ',';
if (this.style.iconBgColor.length == 1) {
style.background += this.style.iconBgColor[0];
} else {
style['background'] += 'linear-gradient('+ this.style.iconBgColorDeg +'deg, '+ this.style.iconBgColor.join(',') +')';
}
}
return style;
},
iconStyle(){
var style = {
fontSize: this.style.fontSize + '%'
}
if (this.style.iconColor.length == 1) {
style.color = this.style.iconColor[0];
} else {
style['background'] = 'linear-gradient('+ this.style.iconColorDeg +'deg, '+ this.style.iconColor.join(',') +')';
}
return style;
}
}
})
})
function iconStyleListener(callback) {
var data = ns.deepclone(vue._data.style);
callback(data);
}
</script>

128
app/shop/view/diy/iconfont.html Executable file
View File

@@ -0,0 +1,128 @@
<style>
.iconfont-wrap{display: flex;margin-top: 10px;border-bottom: 1px solid #f1f1f1;}
.iconfont-wrap .iconfont-left{padding: 10px 15px;width: 155px;height:429px; box-sizing: border-box;overflow-y: auto;}
.iconfont-wrap .iconfont-left::-webkit-scrollbar{width: 4px;}
.iconfont-wrap .iconfont-left::-webkit-scrollbar-track{background: rgb(179, 177, 177);border-radius: 10px;}
.iconfont-wrap .iconfont-left::-webkit-scrollbar-thumb{background: rgb(136, 136, 136);border-radius: 10px;}
.iconfont-wrap .iconfont-left::-webkit-scrollbar-thumb:hover{background: rgb(100, 100, 100);border-radius: 10px;}
.iconfont-wrap .iconfont-left::-webkit-scrollbar-thumb:active{background: rgb(68, 68, 68);border-radius: 10px;}
.iconfont-wrap .iconfont-left li{height: 32px;line-height: 32px;padding: 0 10px;margin-bottom: 9px;box-sizing: border-box;border: 1px solid #f1f1f1;border-radius: 3px;cursor: pointer;}
.iconfont-wrap .iconfont-left li.active{color: var(--base-color);border-color: var(--base-color);}
.iconfont-wrap .iconfont-left li:last-child{margin-bottom: 0;}
.iconfont-wrap .iconfont-right{flex: 1;border-left: 1px solid #f1f1f1;}
.iconfont-wrap .iconfont-right ul{padding: 0 10px;display: flex;flex-wrap: wrap;align-content: baseline;box-sizing: border-box;}
.iconfont-wrap .iconfont-right li{margin: 6px 12px;display: flex;justify-content: center;align-items: center;width: 60px;height: 60px;border: 1px solid #f1f1f1;border-radius: 5px;cursor: pointer;}
.iconfont-wrap .iconfont-right li span{font-size: 30px;}
.iconfont-wrap .iconfont-right li .icon{width: 40px;height: 40px;vertical-align: -0.15em;fill: currentColor;overflow: hidden;}
.iconfont-wrap .iconfont-right li:hover, .iconfont-wrap .iconfont-right li.active{color: var(--base-color);border-color: var(--base-color);}
.iconfont-wrap .iconfont-right .empty{text-align: center;padding: 20px;}
#iconPage{padding-right: 30px;text-align: right;}
</style>
<div class="iconfont-wrap">
<ul class="iconfont-left">
<li data-value="">全部</li>
{foreach name="$icon_type" item="vo" key="k"}
<li data-value="{$k}" {if $k == 'icon-system'}class="active"{/if}>{$vo}</li>
{/foreach}
</ul>
<div class="iconfont-right">
<div class="list-wrap"></div>
<div id="iconPage"></div>
</div>
</div>
<script id="iconTemplate" type="text/html">
{{# if(d.list.length){ }}
<ul>
{{# layui.each(d.list, function(index, item){ }}
<li data-icon="{{item}}" class="{{item == '{$icon}' && 'active'}}">
<span class="{{item}}"></span>
</li>
{{# }); }}
</ul>
{{# }else{ }}
<div class="empty">无数据</div>
{{# } }}
</script>
<!--<script src="https://cdn3.codesign.qq.com/icons/MQmlyZwl3GjWRA1/latest/iconfont.js"></script>-->
<script>
window.Page2 = {
limit: 45
}
var laypage, laytpl, currPage = 1, iconData = [],currIcon="";
layui.use(['laypage','laytpl'], function(){
laypage = layui.laypage;
laytpl = layui.laytpl;
getIconData('icon-system'); //默认查询系统
});
// 获取iconfont数据
function getIconData(type) {
$.ajax({
type: 'post',
url: ns.url("shop/diy/iconfont"),
data: {type: type, site_id: ns_url.siteId, app_module: ns_url.appModule},
dataType: 'JSON',
success: function (res) {
if (res.code >= 0) {
iconData = res.data;
currPage = 1;
renderTemplate(iconData);
if(iconData.length>0) {
$("#iconPage").show();
laypage.render({
elem: 'iconPage',
count: iconData.length, //数据总数,从服务端得到
limit: window.Page2.limit,
jump: function (obj, first) {
//obj包含了当前分页的所有参数比如
currPage = obj.curr;
//首次不执行
if (!first) {
renderTemplate(iconData);
}
}
});
}else{
$("#iconPage").hide();
}
}
}
});
}
// 渲染模版
function renderTemplate(data){
var iconPagingData = data.filter((item,index) => {
if((currPage-1)*window.Page2.limit < (index+1) && (index+1) <= currPage*window.Page2.limit){
return item;
}
});
var getTpl = $("#iconTemplate").html();
laytpl(getTpl).render({list: iconPagingData}, function(html){
$(".iconfont-wrap .iconfont-right .list-wrap").html(html);
});
}
// 图标分类
$('.iconfont-left li').click(function () {
$(this).addClass('active').siblings().removeClass('active');
var type = $(this).attr('data-value');
getIconData(type);
});
$("body").off("click",".iconfont-wrap .iconfont-right li").on("click",".iconfont-wrap .iconfont-right li",function(){
$(this).addClass("active").siblings().removeClass("active");
currIcon = $(this).attr("data-icon");
window.currIcon = currIcon;
});
function selectIconListener(callback) {
if (typeof callback == "function") callback(currIcon);
}
</script>

View File

@@ -0,0 +1,82 @@
<template id="iconfont">
<div class="icon-wrap" :style="iconBgStyle">
<i class="js-icon" :class="iconClass" :style="iconStyle"></i>
</div>
</template>
<style>
.icon-wrap {
width: inherit;
height: inherit;
font-size: 100%;
color: #000;
display: flex;
align-items: center;
justify-content: center;
}
.icon-wrap .js-icon {
font-size: 50%;
line-height:1;
}
.icon-wrap .js-icon.gradient {
-webkit-background-clip:text!important;
-webkit-text-fill-color:transparent;
}
</style>
<script>
Vue.component('iconfont', {
props: {
icon: {
type: String,
default: ''
},
value: {
type: Object,
default: function () {
return null;
}
}
},
computed: {
iconClass(){
var _class = ' ' + this.icon;
if (this.value && this.value.iconColor.length > 1) _class += ' gradient';
return _class;
},
iconBgStyle(){
if (!this.value) return {};
var style = {
'border-radius': this.value.bgRadius + '%',
'background': ''
};
if (this.value.iconBgImg) style['background'] += 'url('+ ns.img(this.value.iconBgImg) +') no-repeat bottom / contain'
if (this.value.iconBgColor.length) {
if (style.background) style.background += ',';
if (this.value.iconBgColor.length == 1) {
style.background += this.value.iconBgColor[0];
} else {
style['background'] += 'linear-gradient('+ this.value.iconBgColorDeg +'deg, '+ this.value.iconBgColor.join(',') +')';
}
}
return style;
},
iconStyle(){
if (!this.value) return {};
var style = {
fontSize: this.value.fontSize + '%'
}
if (this.value.iconColor.length == 1) {
style.color = this.value.iconColor[0];
} else {
style['background'] = 'linear-gradient('+ this.value.iconColorDeg +'deg, '+ this.value.iconColor.join(',') +')';
}
return style;
}
},
template: '#iconfont'
})
</script>

311
app/shop/view/diy/link.html Executable file
View File

@@ -0,0 +1,311 @@
<style>
.link-box{font-size:12px;margin-top: 10px;}
.link-box .link-center{display:flex;height:480px}
.link-box .link-left{overflow-y:auto;width:138px;height:100%;border-right:1px solid #f2f2f2}
.link-box .link-left::-webkit-scrollbar{display: none;}
.link-box .link-left dt{position:relative;padding-left:15px;height:32px;line-height:32px;cursor:pointer;transition:all .3s}
.link-box .link-left dt.triangle:after{content:'';position:absolute;left:0;top:51%;transform:translateY(-50%);border:4px solid transparent;border-right-color:#333;border-bottom-color:#333;cursor:pointer}
.link-box .link-left dt.active:after{transform:translateY(-50%) rotate(-45deg)}
.link-box .link-left dd{margin-right:25px;padding-left:25px;height:32px;line-height:32px;color:#666;cursor:pointer}
.link-box .link-left dd:hover{background-color:#f2f2f2}
.link-box .link-right{overflow-y:auto;height:100%;flex:1;padding-left:20px;display: none;}
.link-box .link-right dl{overflow:hidden;display: none;}
.link-box .link-right dt{height:40px;line-height:40px}
.link-box .link-right dd{float:left;margin:5px 5px 5px 0;padding:0 16px;border:1px solid #ededed;border-radius:3px;line-height:30px;color:#666;cursor:pointer}
.link-btn{position: relative;top: 10px;padding-top: 10px;margin-top:20px;padding-right:10px;height:45px;line-height:45px;text-align:right;border-top:1px solid #f2f2f2}
.goods-category-list .layui-table td {border-left: 0;border-right: 0;}
.goods-category-list .layui-table .switch {font-size: 16px;cursor: pointer;width: 12px;line-height: 1;display: inline-block;text-align: center;vertical-align: middle;}
.goods-category-list .layui-table img {width: 40px;}
.layui-layer-page .layui-layer-btn{padding: 0;}
</style>
<div class="link-box">
<div class="link-center">
<div class="link-left">
{foreach $list as $k => $link}
<dl>
<dt data-name="{$link.name}" {notempty name='$link.child_list'}class="triangle"{/notempty}>{$link.title}</dt>
{foreach $link.child_list as $child_k => $child_link}
<dd data-name="{$child_link.name}" {if !empty($select_link) && !empty($select_link.parent) && $select_link.parent == $child_link.name }class="text-color"{/if}>{$child_link.title}</dd>
{/foreach}
</dl>
{/foreach}
</div>
<div class="link-right js-system">
{foreach $list as $k => $link}
{foreach $link.child_list as $second_k => $second_link}
{notempty name="$second_link.child_list"}
{foreach $second_link.child_list as $third_k => $third_link}
<dl data-parent="{$third_link.parent}">
<dt>{$third_link.title}</dt>
{notempty name="$third_link.child_list"}
{foreach $third_link.child_list as $four_k => $four_link}
<dd data-name="{$four_link.name}" data-wap-url="{$four_link.wap_url}" {if !empty($select_link) && isset($select_link.name) && $select_link.name == $four_link.name }class="border-color text-color"{/if}>{$four_link.title}</dd>
{/foreach}
{/notempty}
</dl>
{/foreach}
{/notempty}
{/foreach}
{/foreach}
</div>
<div class="link-right js-extend"></div>
</div>
<div class="link-btn">
<button class="layui-btn link-save">确定</button>
<button class="layui-btn link-eliminate layui-btn-primary">清空</button>
<button class="layui-btn link-cancel layui-btn-primary">取消</button>
</div>
</div>
<!-- 商品分类 -->
<script type="text/html" id="goodsCategoryHtml">
<div class="goods-category-list layui-form">
<table class="layui-table">
<colgroup>
<col width="5%">
<col width="3%">
<col width="34%">
<col width="33%">
<col width="25%">
</colgroup>
<thead>
<tr>
<th></th>
<th></th>
<th>分类名称</th>
<th>简称</th>
<th>图片</th>
</tr>
</thead>
<tbody>
{if condition="$category_list"}
{foreach name="$category_list" item="vo"}
<tr class='category-line'>
<td><input type="checkbox" name="category_id" lay-skin="primary" data-category-name="{$vo['category_name']}" value="{$vo['category_id']}" lay-filter="category_id" {if !empty($select_link.category_id) && $select_link.category_id == $vo['category_id']}checked{/if}></td>
<td>
{notempty name="$vo['child_list']"}
<span class="switch text-color js-switch" data-category-id="{$vo['category_id']}" data-operation="off">+</span>
{/notempty}
</td>
<td>{$vo['category_name']}</td>
<td>{$vo['short_name']}</td>
<td>
{notempty name="$vo['image']"}
<div class="img-box">
<img layer-src src="{:img($vo['image'])}"/>
</div>
{/notempty}
</td>
</tr>
{notempty name="$vo['child_list']"}
{foreach name="$vo['child_list']" item="second"}
<tr class='category-line' data-pid="{$second['pid']}" style="display:none;">
<td><input type="checkbox" name="category_id" lay-skin="primary" data-category-name="{$second['category_name']}" lay-filter="category_id" value='{$second['category_id']}' {if !empty($select_link.category_id) && $select_link.category_id == $second['category_id']}checked{/if}></td>
<td></td>
<td style="padding-left: 30px;">
{notempty name="$second['child_list']"}
<span class="switch text-color js-switch" data-category-id="{$second['category_id']}" data-operation="off" style="padding-right: 20px;">+</span>
{/notempty}
<span>{$second['category_name']}</span>
</td>
<td>{$second['short_name']}</td>
<td>
{notempty name="$second['image']"}
<div class="img-box">
<img layer-src src="{:img($second['image'])}"/>
</div>
{/notempty}
</td>
</tr>
{notempty name="$second['child_list']"}
{foreach name="$second['child_list']" item="third"}
<tr class='category-line' data-pid="{$third['pid']}" style="display:none;">
<td><input type="checkbox" name="category_id" lay-skin="primary" data-category-name="{$third['category_name']}" lay-filter="category_id" value='{$third['category_id']}' {if !empty($select_link.category_id) && $select_link.category_id == $third['category_id']}checked{/if}></td>
<td></td>
<td style="padding-left: 80px;">
<span>{$third['category_name']}</span>
</td>
<td>{$third['short_name']}</td>
<td>
{notempty name="$third['image']"}
<div class="img-box">
<img layer-src src="{:img($third['image'])}"/>
</div>
{/notempty}
</td>
</tr>
{/foreach}
{/notempty}
{/foreach}
{/notempty}
{/foreach}
{else/}
<tr>
<td colspan="5" style="text-align: center">无数据</td>
</tr>
{/if}
</tbody>
</table>
</div>
</script>
<script type="text/html" id="goodsCategoryPageHtml">
<div class="goods-category-list layui-form">
<table class="layui-table">
<colgroup>
<col width="5%">
<col width="34%">
<col width="33%">
<col width="25%">
</colgroup>
<thead>
<tr>
<th></th>
<th>分类名称</th>
<th>简称</th>
<th>图片</th>
</tr>
</thead>
<tbody>
{if condition="$category_list"}
{foreach name="$category_list" item="vo"}
<tr class='category-line'>
<td><input type="checkbox" name="category_id" lay-skin="primary" data-category-name="{$vo['category_name']}" value="{$vo['category_id']}" lay-filter="category_id" {if !empty($select_link.category_id) && $select_link.category_id == $vo['category_id']}checked{/if}></td>
<td>{$vo['category_name']}</td>
<td>{$vo['short_name']}</td>
<td>
{notempty name="$vo['image']"}
<div class="img-box">
<img layer-src src="{:img($vo['image'])}"/>
</div>
{/notempty}
</td>
</tr>
{/foreach}
{else/}
<tr>
<td colspan="5" style="text-align: center">无数据</td>
</tr>
{/if}
</tbody>
</table>
</div>
</script>
{if(addon_is_exit('cardservice'))}
<!-- 服务分类 -->
<script type="text/html" id="serviceCategoryHtml">
<div class="goods-category-list layui-form">
<table class="layui-table">
<colgroup>
<col width="8%">
<col width="46%">
<col width="46%">
</colgroup>
<thead>
<tr>
<th></th>
<th>分类名称</th>
<th>图片</th>
</tr>
</thead>
<tbody>
{if condition="$service_category_list"}
{foreach name="$service_category_list" item="vo"}
<tr class='category-line'>
<td><input type="checkbox" name="service_category_id" lay-skin="primary" data-category-name="{$vo['category_name']}" value="{$vo['category_id']}" lay-filter="service_category_id" {if !empty($select_link.service_category_id) && $select_link.service_category_id == $vo['category_id']}checked{/if}></td>
<td>{$vo['category_name']}</td>
<td>
{notempty name="$vo['image']"}
<div class="img-box">
<img layer-src src="{:img($vo['image'])}"/>
</div>
{/notempty}
</td>
</tr>
{/foreach}
{else/}
<tr>
<td colspan="3" style="text-align: center">无数据</td>
</tr>
{/if}
</tbody>
</table>
</div>
</script>
{/if}
<script type="text/html" id="goods_info">
<div class="table-title">
<div class="title-pic" id="goods_img_{{d.goods_id}}">
<img layer-src src="{{ns.img(d.goods_image.split(',')[0],'small')}}"/>
</div>
<div class="title-content">
<a href="javascript:;" class="multi-line-hiding" title="{{d.goods_name}}">{{d.goods_name}}</a>
</div>
</div>
</script>
<!--自定义链接-->
<script type="text/html" id="customHtml">
<div class="layui-form custom-link">
<div class="layui-form-item">
<label class="layui-form-label mid"><span class="required">*</span></label>
<div class="layui-input-inline">
<input type="text" name="title" value="{{ d.title ? d.title : '' }}" placeholder="请输入链接名称" class="layui-input len-mid" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label mid"><span class="required">*</span></label>
<div class="layui-input-block">
<input type="text" name="wap_url" value="{{ d.wap_url ? d.wap_url : '' }}" placeholder="请输入跳转路径" class="layui-input len-mid" autocomplete="off">
</div>
<div class="word-aux mid">路径必须以/开头/pages/index/index</div>
<div class="word-aux mid">跳转外部链接/开头https://baidu.com</div>
</div>
</div>
</script>
<!--跳转小程序-->
<script type="text/html" id="appletHtml">
<div class="layui-form other-applet">
<div class="layui-form-item">
<label class="layui-form-label mid"><span class="required">*</span>AppID</label>
<div class="layui-input-inline">
<input type="text" name="appid" value="{{ d.appid ? d.appid : '' }}" class="layui-input len-mid" placeholder="请输入要打开的小程序的appid" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label mid">小程序路径</label>
<div class="layui-input-block">
<input type="text" name="page" value="{{ d.page ? d.page : '' }}" class="layui-input len-mid" placeholder="请输入要打开的小程序路径" autocomplete="off">
</div>
<div class="word-aux mid">仅支持小程序之间的跳转不支持从其他渠道跳转小程序</div>
<div class="word-aux mid">小程序路径如果为空则跳转到小程序首页</div>
<div class="word-aux mid">小程序路径格式如page/index/index</div>
</div>
</div>
</script>
<!--拨打手机号-->
<script type="text/html" id="mobileHtml">
<div class="layui-form call-mobile">
<div class="layui-form-item">
<label class="layui-form-label mid"><span class="required">*</span></label>
<div class="layui-input-inline">
<input type="text" name="mobile" value="{{ d.mobile ? d.mobile : '' }}" class="layui-input len-mid" placeholder="请输入电话号码">
</div>
</div>
<div class="word-aux mid">电话号码支持手机号码和固定电话</div>
</div>
</script>
<script>
var selectLink = {:json_encode($select_link)};
</script>
<script src="STATIC_EXT/diyview/js/link.js?v=1.1"></script>

481
app/shop/view/diy/lists.html Executable file
View File

@@ -0,0 +1,481 @@
<style>
.layui-table-view td:last-child>div{overflow: inherit;}
.operation-wrap{position: relative;}
.layui-table-box{overflow: inherit;}
.layui-table-body{overflow: inherit;}
.set-home{display:inline-block;margin-left: 5px;padding: 3px;font-size: 12px;line-height: 1;color: #fff;}
.popup-qrcode-wrap{text-align: center;background: #fff;border-radius: 2px;box-shadow: 0 2px 8px 0 rgba(200,201,204,.5);padding: 10px;position: absolute;z-index: 1;top: -73px;left: -180px;display: none;width: 170px;height: 230px;}
.popup-qrcode-wrap:before, .popup-qrcode-wrap:after {left: 100%;top: 50%;border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none;}
.popup-qrcode-wrap:before {border-color: transparent;border-left-color: #e5e5e5;border-width: 8px;margin-top: -29px;}
.popup-qrcode-wrap:after {border-color: transparent;border-left-color: #ffffff;border-width: 7px;margin-top: -31px;}
.popup-qrcode-wrap img{width: 150px;height: 150px;max-width: initial;}
.popup-qrcode-wrap p{font-size: 12px;margin: 5px 0;line-height: 1.8!important;}
.popup-qrcode-wrap a{font-size: 12px;}
.popup-qrcode-wrap input{opacity: 0;position: absolute;}
.popup-qrcode-wrap .popup-qrcode-loadimg {width: 16px!important; height: 16px!important; margin-top: 107px;}
.edit-sort.len-short{width: 100px !important;}
.use{
display: inline-block;
line-height: 20px;
}
.unused{
display: inline-block;
line-height: 20px;
}
.custom-tag{
display: inline-block;
line-height: 20px;
}
.select-page{
display: flex;
flex-wrap: nowrap;
justify-content: center;
text-align: center;
}
.select-page .item {position: relative;margin-right: 30px;padding: 10px;width: 200px;height: 390px;cursor: pointer;overflow: hidden;box-sizing: border-box;border: 1px solid #e9edef;}
.select-page .item:last-child{margin-right: 0;}
.select-page .item .checked {position: absolute;bottom: -1px;right: -1px;z-index: 101;font-size: 30px;display: none;}
.select-page .item .mask{position: absolute;background: -webkit-gradient(linear, left top, left bottom, color-stop(52.65%, rgba(255,255,255,0)), color-stop(83.57%, #fff));background: linear-gradient(180deg, rgba(255,255,255,0) 52.65%, #fff 83.57%);height: 100%;width: 100%;z-index: 99;left:0;}
.select-page .item img{width: 180px;}
.select-page .item .info{position: absolute;bottom: 12px;z-index: 100;background-color: #ffffff;display: flex;flex-direction: column;width: 100%;text-align: center;color: #333;left: 0;}
.select-page .item .info i {margin-bottom: 10px;font-size: 24px;color: #333;}
.select-page .item .info span{font-size: 16px;font-weight: bold;}
.select-page .item.selected .checked{display: block;}
.select-btn{padding-top: 10px;margin-top:20px;padding-right:10px;height:40px;line-height:40px;text-align:right;border-top:1px solid #e9edef;}
.table-tab{margin: 0;}
</style>
<!-- 搜索框 -->
<div class="single-filter-box">
<button class="layui-btn" onclick="createPage()">新建页面</button>
<div class="layui-form">
<div class="layui-input-inline">
<input type="text" name="search_text" placeholder="请输入页面名称" autocomplete="off" class="layui-input">
<button type="button" class="layui-btn layui-btn-primary" lay-filter="search" lay-submit>
<i class="layui-icon">&#xe615;</i>
</button>
</div>
</div>
</div>
<!-- 筛选面板 -->
<!--<div class="screen layui-collapse" lay-filter="selection_panel">-->
<!-- <div class="layui-colla-item">-->
<!-- <form class="layui-colla-content layui-form layui-show">-->
<!-- <div class="layui-form-item">-->
<!-- <div class="layui-inline">-->
<!-- <label class="layui-form-label">页面名称</label>-->
<!-- <div class="layui-input-inline">-->
<!-- <input type="text" name="search_text" placeholder="请输入页面名称" autocomplete="off" class="layui-input">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="layui-inline">-->
<!-- <label class="layui-form-label">店铺模板</label>-->
<!-- <div class="layui-input-inline">-->
<!-- <select name="template_id" lay-filter="template_id">-->
<!-- {foreach name="$template_goods_list" item="vo"}-->
<!-- <option value="{$vo.goods_id}">{$vo.title}</option>-->
<!-- {/foreach}-->
<!-- </select>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="layui-inline">-->
<!-- <label class="layui-form-label">页面类型</label>-->
<!-- <div class="layui-input-inline">-->
<!-- <select name="type" lay-filter="type">-->
<!-- <option value="">全部</option>-->
<!-- <option value="DIY_PAGE">自定义页面</option>-->
<!-- {foreach name="$template_list" item="vo"}-->
<!-- <option value="{$vo.name}">{$vo.title}</option>-->
<!-- {/foreach}-->
<!-- </select>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="form-row">-->
<!-- <button class="layui-btn" lay-submit lay-filter="search">筛选</button>-->
<!-- <button type="reset" class="layui-btn layui-btn-primary">重置</button>-->
<!-- </div>-->
<!-- </form>-->
<!-- </div>-->
<!--</div>-->
<div class="layui-tab table-tab" lay-filter="diy_list_tab">
<ul class="layui-tab-title js-diy-tab">
{foreach name="$template_list" item="vo"}
<li {if $vo.name==$type }class="layui-this"{/if} lay-id="{$vo.name}">{$vo.title}({$vo.count})</li>
{/foreach}
</ul>
<div class="layui-tab-content">
<table id="diy_list" lay-filter="diy_list"></table>
</div>
</div>
<script type="text/html" id="action">
<div class="operation-wrap" data-id="{{d.id}}">
<div class="table-btn">
<div class="popup-qrcode-wrap"><img class="popup-qrcode-loadimg" src="__STATIC__/loading/loading.gif" /></div>
{{# if(d.type != 'DIY_PAGE' && d.is_default == 0){ }}
<a class="layui-btn" lay-event="setUse">使用</a>
{{# } }}
<a class="layui-btn text-color" lay-event="promote">推广</a>
<a class="layui-btn" lay-event="edit">编辑</a>
<a class="layui-btn" lay-event="copy">复制页面</a>
{{# if(d.type == 'DIY_PAGE' || d.is_default == 0){ }}
<a class="layui-btn" lay-event="delete">删除</a>
{{# } }}
</div>
</div>
</script>
<!-- 编辑排序 -->
<script type="text/html" id="editSort">
<input name="sort" type="number" onchange="editSort({{d.id}}, this)" value="{{d.sort}}" class="layui-input edit-sort len-short">
</script>
<script type="text/html" id="toolbarOperation">
<button class="layui-btn layui-btn-primary" lay-event="delete">批量删除</button>
</script>
<script type="text/html" id="batchOperation">
<button class="layui-btn layui-btn-primary" lay-event="delete">批量删除</button>
</script>
<script type="text/html" id="createPageHtml">
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label sm"><span class="required">*</span></label>
<div class="layui-input-inline len-mid">
<select name="template_id" lay-filter="template_id" lay-verify="required">
{foreach name="$template_goods_list" item="vo"}
<option value="{$vo.goods_id}">{$vo.title}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label sm"><span class="required">*</span></label>
<div class="layui-input-inline len-mid">
<input type="text" name="title" placeholder="请输入页面名称" lay-verify="required" autocomplete="off" maxlength="15" class="layui-input">
</div>
</div>
<div class="form-row sm">
<button class="layui-btn" lay-submit lay-filter="createPage">确定</button>
<button class="layui-btn layui-btn-primary" onclick="layer.close(createPageIndex)">取消</button>
</div>
</div>
</script>
<script type="text/html" id="selectPageHtml">
<div class="layui-form select-page">
{foreach name="$page_type_list" item="vo" key="k"}
<div class="item{if $k==0} selected border-color{/if}" data-page-type="{$vo.name}">
<i class="iconfont iconxuanzhong text-color checked"></i>
<div class="mask"></div>
<img src="{:img($vo.preview)}" alt="">
<div class="info">
<i class="{$vo.icon}{if $k==0} text-color{/if}"></i>
<span {if $k==0}class="text-color"{/if}>{$vo.title}</span>
</div>
</div>
{/foreach}
</div>
<div class="select-btn">
<button class="layui-btn select-save" onclick="selectPage()">确定</button>
<button class="layui-btn select-cancel layui-btn-primary" onclick="layer.close(createPageIndex)">取消</button>
</div>
</script>
<script>
var form,laytpl,element,table,createPageIndex;
layui.use([ 'laytpl', 'form','element'], function () {
laytpl = layui.laytpl;
form = layui.form;
element = layui.element;
table = new Table({
id: 'diy_list',
elem: '#diy_list',
url: ns.url("shop/diy/lists"),
cols: [[{
type: 'checkbox',
width: '3%'
}, {
width: '20%',
title: '页面名称',
templet: function (res) {
var html = '';
html += `<span>${res.title}</span>`;
return html;
}
}, {
field: 'type_name',
width: '16%',
title: '页面类型',
}, {
width: '16%',
title: '状态',
templet: function (res) {
var html = '';
if (res.type == 'DIY_PAGE'){
html = '<span class="custom-tag">-</span>';
}else{
if(res.is_default == 1) html = `<span class="use text-color">使用中</span>`;
else html = `<span class="unused">未使用</span>`;
}
return html;
}
},
// {
// field: 'click_num',
// width: '13%',
// title: '浏览量',
// sort: true
// },
{
width: '20%',
title: '创建时间',
templet: function (d) {
return ns.time_to_date(d.create_time);
}
},
// {
// field: 'sort',
// width: '12%',
// title: '排序',
// templet: '#editSort',
// sort: true
// },
{
title: '操作',
toolbar: '#action',
width: '25%',
align: 'right'
}]],
where: {
template_id: $("select[name='template_id']").val()
},
toolbar: '#toolbarOperation',
bottomToolbar: "#batchOperation"
});
//监听工具条
table.tool(function (obj) {
var data = obj.data;
if (obj.event === 'promote') {
// 推广
window.open(ns.url('index/index/h5preview', {id: data.id, type: 'page'}));
} else if (obj.event === 'edit') {
window.open(ns.href("shop/diy/edit", {id: data.id}));
} else if (obj.event === "delete") {
deleteSiteDiyView(data.id);
} else if (obj.event === "copy") {
layer.confirm('确定要复制该页面吗?', function (index) {
$.ajax({
type: "post",
url: ns.url("shop/diy/copySiteDiyView"),
data: {'id': data.id},
dataType: "JSON",
success: function (res) {
layer.msg(res.message);
if (res.code >= 0) {
table.reload();
getPageCount();
}
}
});
layer.close(index);
});
}else if(obj.event === 'setUse') {
$.ajax({
type: "post",
url: ns.url("shop/diy/setUse"),
data: {id: data.id, name: data.name},
dataType: "JSON",
success: function (res) {
layer.msg(res.message);
if (res.code >= 0) {
table.reload();
}
}
});
}
});
//批量操作
table.bottomToolbar(function (obj) {
if (obj.data.length < 1) {
layer.msg('请选择要操作的数据');
return;
}
switch (obj.event) {
case "delete":
var id_array = [];
for (var i in obj.data) id_array.push(obj.data[i].id);
deleteSiteDiyView(id_array.toString());
break;
}
});
//批量操作
table.toolbar(function (obj) {
if (obj.data.length < 1) {
layer.msg('请选择要操作的数据');
return;
}
switch (obj.event) {
case "delete":
var id_array = [];
for (var i in obj.data) id_array.push(obj.data[i].id);
deleteSiteDiyView(id_array.toString());
break;
}
});
// 搜索功能
form.on('submit(search)', function (data) {
table.reload({
page: {
curr: 1
},
where: data.field
});
return false;
});
form.on('submit(createPage)', function (data) {
location.hash = ns.hash('shop/diy/edit',data.field);
});
element.on('tab(diy_list_tab)', function () {
var type = this.getAttribute('lay-id');
table.reload({
page: {
curr: 1
},
where: {
search_text : $('input[name="search_text"]').val(),
type : type
}
});
});
});
// 监听单元格编辑
function editSort(id, event){
var data = $(event).val();
if (data == '') {
$(event).val(0);
data = 0;
}
let reg = ns.getRegexp('>=0num');
if (!reg.test(data)) {
layer.msg("排序号必须是大于或等于0的整数");
return;
}
$.ajax({
type: 'POST',
url: ns.url("shop/diy/modifySort"),
data: {
id: id,
sort: data
},
dataType: 'JSON',
success: function(res) {
layer.msg(res.message);
if(res.code==0){
table.reload();
}
}
});
}
function createPage() {
createPageIndex = layer.open({
type: 1,
title: '选择页面类型',
content: $('#selectPageHtml').html(),
offset: 'auto',
area: ['auto','auto'],
success: function (layero, index) {
form.render();
$('.select-page .item').click(function () {
$(this).addClass('selected border-color').siblings().removeClass('selected border-color');
$('.select-page .item').find('.info>*').removeClass('text-color');
$(this).find('.info>*').addClass('text-color');
});
}
});
}
function selectPage() {
layer.close(createPageIndex)
var selected = $('.select-page .item.selected');
var params = {};
// 排除自定义页面类型
if (selected.attr('data-page-type') !== 'DIY_PAGE') {
params.page_type = selected.attr('data-page-type');
}
setTimeout(function () {
location.hash = ns.hash('shop/diy/edit', params);
},150);
}
// 删除店铺微页面
function deleteSiteDiyView(id_array) {
layer.confirm('确定要删除这些微页面模板吗', function (index) {
layer.close(index);
$.ajax({
url: ns.url("shop/diy/deleteSiteDiyView"),
data: {'id': id_array},
dataType: "JSON",
success: function (res) {
layer.msg(res.message);
if (res.code == 0) {
getPageCount();
table.reload();
}
}
});
});
}
// 查询页面数量
function getPageCount() {
$.ajax({
type: "post",
url: ns.url("shop/diy/getPageCount"),
data: {},
dataType: "JSON",
success: function (res) {
if (res.code >= 0) {
var str = '';
for (var i = 0; i < res.data.length; i++) {
var item = res.data[i];
var type = $('.js-diy-tab li.layui-this').attr('lay-id');
str += `<li`;
if(item.name == type){
str += ` class="layui-this"`;
}
str += ` lay-id="${item.name}">`;
str += `${item.title}(${item.count})</li>`;
}
$('.js-diy-tab').html(str);
}
}
});
}
</script>

235
app/shop/view/diy/management.html Executable file
View File

@@ -0,0 +1,235 @@
<style type="text/css">
.management-info{
display: flex;
margin-bottom: 50px;
}
.management-info .management{
margin-left: 10px;
}
.management-info .phone-wrap{
min-width: 340px;
width: 340px;
height: 667px;
}
.management-info .phone-wrap .iframe-wrap{
width: 340px;
height: 100%;
border: 1px solid #eee;
}
.management-info .phone-wrap .iframe-wrap #iframe-management{
width: 340px;
height: 100%;
}
.management-info-left{
margin-left: 40px;
max-width: 680px;
width:100%;
}
.management-info-left-box{
position: relative;
padding: 20px;
border: 1px solid #eee;
}
.management-info-left-box::after{
position: absolute;
content: '';
width: 26px;
height: 26px;
background-color: #fff;
transform:rotate(-45deg);
left:-13px;
top:26px;
border: 1px solid #eee;
border-right: 0;
border-bottom: 0;
}
.management-info .management-info-left .management-info-top{
border-bottom: 1px solid #eee;
padding-bottom: 20px;
}
.management-info .management-info-title{
font-size: 18px;
font-weight: 800;
display: flex;
align-items: center;
}
.management-info .management-info-left .management-info-top .word-aux{
margin: 10px 0 0 0;
}
.management-info .management-info-box{
margin-top: 20px;
background-color: #F7F8FA;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.management-info .management-info-box-img{
width: 100px;
min-height: 100px;
}
.management-info .management-info-box-img img{
width: 100%;
height: 100%;
}
.management-info .management-info-box-img .tips {
text-align: center;
font-size: 12px;
color: #999;
border: 1px dashed #ddd;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
cursor: pointer;
box-sizing: border-box;
}
.management-info .management-info-box-title-bottom{
color: #999;
}
.management-info .management-empty {
text-align: center;
}
.management-info .management-empty img{
width: 190px;
display: block;
margin:80px auto 40px;
}
.blockflex{
margin-top: 10px;
text-align: center;
cursor:pointer;
}
</style>
<div class="main-wrap-margin">
<div class="management-info">
<div class="phone-wrap">
<div class="iframe-wrap">
{if !empty($qrcode_info) && $qrcode_info['url']}
<iframe id="iframe-management" src="{$qrcode_info['url']}" frameborder="0"></iframe>
{else/}
<div class="management-empty">
<img src="__STATIC__/img/wap_not_found.png" />
<p>当前手机页面无法访问</p>
<a href="https://www.kancloud.cn/niucloud/niushop_b2c_v4/1842146" class="text-color" target="_blank">请检查手机端域名配置以及伪静态</a>
</div>
{/if}
</div>
</div>
<div class="management-info-left">
<div class="management-info-left-box">
<div class="management-info-top">
<div class="management-info-title">
<button type="button" class="layui-btn" onclick="toIndex()">装修</button>
</div>
{if $store_business == 'store'}
<p class="word-aux text-color">当前系统为连锁门店运营模式,首页按照门店页面装修</p>
{/if}
</div>
<div class="management-info-content">
<div class="management-info-box">
<div>
<div class="management-info-box-title">H5</div>
<div class="management-info-box-title-bottom">扫描右侧二维码查看</div>
</div>
<div class="management-info-box-img">
{notempty name="$qrcode_info"}
<img layer-src src="{:img($qrcode_info['img'])}" />
<div class="blockflex">
<a class="text-color" href="{:url('index/index/h5preview')}" target="_blank">访问店铺</a>
</div>
{/notempty}
</div>
</div>
{notempty name="$wechat_config"}
<div class="management-info-box">
<div>
<div class="management-info-box-title">微信公众号</div>
<div class="management-info-box-title-bottom">扫描右侧二维码查看</div>
</div>
<div class="management-info-box-img">
{notempty name="$wechat_config['qrcode']"}
<img layer-src src="{:img($wechat_config['qrcode'])}" onerror="this.src = 'STATIC_IMG/default_img/square.png'"/>
{else/}
<p class="tips" onclick="window.open('{:href_url(\'wechat://shop/wechat/config\')}')">请上传<br>公众号二维码</p>
{/notempty}
</div>
</div>
{else/}
<div class="management-info-box">
<div>
<div class="management-info-box-title">微信公众号</div>
<div class="management-info-box-title-bottom">需要配置已认证的微信公众号,才能使用该功能哦!</div>
</div>
<button type="button" class="layui-btn jump-type" onclick="window.open('{:href_url(\'wechat://shop/wechat/config\')}')">立即配置</button>
</div>
{/notempty}
{notempty name="$weapp_config"}
<div class="management-info-box">
<div>
<div class="management-info-box-title">微信小程序</div>
<div class="management-info-box-title-bottom">扫描右侧二维码查看</div>
</div>
<div class="management-info-box-img">
{notempty name="$weapp_config['qrcode']"}
<img layer-src src="{:img($weapp_config['qrcode'])}" onerror="this.src = 'STATIC_IMG/default_img/square.png'"/>
{else/}
<p class="tips" onclick="window.open('{:href_url(\'weapp://shop/weapp/config\')}')">请上传<br>小程序二维码</p>
{/notempty}
</div>
</div>
{else/}
<div class="management-info-box">
<div>
<div class="management-info-box-title">微信小程序</div>
<div class="management-info-box-title-bottom">需要配置已认证的微信小程序,才能使用该功能哦!</div>
</div>
<button type="button" class="layui-btn jump-type" onclick="window.open('{:href_url(\'weapp://shop/weapp/config\')}')">立即配置</button>
</div>
{/notempty}
{if isset($aliapp_config) }
{notempty name="$aliapp_config"}
<div class="management-info-box">
<div>
<div class="management-info-box-title">支付宝小程序</div>
<div class="management-info-box-title-bottom">扫描右侧二维码查看</div>
</div>
<div class="management-info-box-img">
{notempty name="$aliapp_config['qrcode']"}
<img layer-src src="{:img($aliapp_config['qrcode'])}" onerror="this.src = 'STATIC_IMG/default_img/square.png'"/>
{else/}
<p class="tips" onclick="window.open('{:href_url(\'aliapp://shop/aliapp/config\')}')">请上传<br>小程序二维码</p>
{/notempty}
</div>
</div>
{else/}
<div class="management-info-box">
<div>
<div class="management-info-box-title">支付宝小程序</div>
<div class="management-info-box-title-bottom">需要配置支付宝小程序,才能使用该功能哦!</div>
</div>
<button type="button" class="layui-btn jump-type" onclick="window.open('{:href_url(\'aliapp://shop/aliapp/config\')}')">立即配置</button>
</div>
{/notempty}
{/if}
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var storeBusiness = '{$store_business}'; // 店铺运营模式
function toIndex(){
if(storeBusiness == 'shop') location.hash = ns.hash('shop/diy/index');
else if(storeBusiness == 'store') location.hash = ns.hash('store://shop/store/diy');
}
</script>

141
app/shop/view/diy/route.html Executable file
View File

@@ -0,0 +1,141 @@
<style>
.table-tab .layui-tab-title{margin-bottom: 20px;}
.layui-table-box{overflow: inherit;}
.layui-table-body{overflow: inherit;}
.layui-table-view td>div{overflow: inherit;}
.route-wrap{display: flex;align-items: center;}
.route-wrap a{margin: 0 10px;}
.route-wrap .iconfont{font-size: 24px;vertical-align:bottom;cursor: pointer;}
.promote-wrap{position: relative;}
.qrcode-wrap {display: none;font-size: 14px;line-height: 20px;background-color: #fff;box-shadow: 0 2px 8px 0 rgba(200, 201, 204, .5);position: absolute;z-index: 2000;border-radius: 2px;top: 40px;right: 5px;transform: translateX(10px);width: 200px;margin-bottom: 20px;}
.qrcode-wrap:before {right: 7px;top: -14px;border: solid transparent;content: "";height: 0;width: 0;position: absolute;pointer-events: none;border-color: transparent;border-bottom-color: #fff;border-width: 8px;}
.qrcode-wrap h4{text-align: center;border-bottom: 2px solid;line-height: 40px;}
.qrcode-wrap img{display: block;width: 130px;height: 130px;max-width: 100%;margin: 10px auto;}
.qrcode-wrap span{display: block;text-align: center;margin-bottom: 10px;cursor: pointer;}
</style>
<!-- 搜索框 -->
<div class="single-filter-box">
<div class="layui-form">
<div class="layui-input-inline">
<input type="text" name="search_text" placeholder="请输入页面名称" autocomplete="off" class="layui-input">
<button type="button" class="layui-btn layui-btn-primary" lay-filter="search" lay-submit>
<i class="layui-icon">&#xe615;</i>
</button>
</div>
</div>
</div>
<table id="route_list" lay-filter="route_list"></table>
<script type="text/html" id="h5_route">
<div class="route-wrap">
<span>{$h5_domain}{{d.wap_url}}</span>
<a class="text-color" href="javascript:ns.copy('h5_route_{{d.id}}');">复制</a>
<div class="promote-wrap">
<span class="text-color iconfont iconerweima" data-event="qrcode" data-name="{{d.name}}" data-path="{{d.wap_url}}" onclick="showQrcode(this,'h5')"></span>
<div class="qrcode-wrap" data-event="qrcode">
<h4 class="border-color" data-event="qrcode">二维码</h4>
<img src="" data-event="qrcode">
<span class="text-color" onclick="ns.copy('h5_route_{{d.id}}')" data-event="qrcode">复制链接</span>
</div>
</div>
<input type="hidden" id="h5_route_{{d.id}}" value="{$h5_domain}{{d.wap_url}}">
</div>
</script>
<script type="text/html" id="weapp_route">
<div class="route-wrap">
<span>{{d.wap_url}}</span>
<a class="text-color" href="javascript:ns.copy('weapp_route_{{d.id}}');">复制</a>
<div class="promote-wrap">
<span class="text-color iconfont iconerweima" data-event="qrcode" data-name="{{d.name}}" data-path="{{d.wap_url}}" onclick="showQrcode(this,'weapp')"></span>
<div class="qrcode-wrap" data-event="qrcode">
<h4 class="border-color" data-event="qrcode">二维码</h4>
<img src="" data-event="qrcode">
<span class="text-color" onclick="ns.copy('weapp_route_{{d.id}}')" data-event="qrcode">复制链接</span>
</div>
</div>
<input type="hidden" id="weapp_route_{{d.id}}" value="{{d.wap_url}}">
</div>
</script>
<script>
var form,laytpl,table,element;
layui.use([ 'laytpl', 'form','element'], function () {
laytpl = layui.laytpl;
element = layui.element;
form = layui.form;
table = new Table({
elem: '#route_list',
url: ns.url("shop/diy/route"),
cols: [[{
type: 'checkbox',
width: '3%'
}, {
width: '10%',
title: '页面名称',
templet: function (res) {
var html = '';
html += `<span>${res.title}</span>`;
return html;
}
}, {
width: '45%',
title: 'H5链接',
templet: '#h5_route',
}, {
width: '30%',
title: '小程序链接',
templet: '#weapp_route',
}]],
});
/**
* 搜索功能
*/
form.on('submit(search)', function(data){
table.reload({
page: {
curr: 1
},
where: data.field
});
});
});
function showQrcode(event,type) {
$('.qrcode-wrap').hide();
promote({name: $(event).attr('data-name'), path: $(event).attr('data-path'), app_type: type}, function (data) {
if(data[type].status == 1) {
var qrcode = $(event).next();
qrcode.find('img').attr('src', ns.img(data[type].img));
qrcode.show();
}else{
layer.msg(data[type].message);
}
});
}
$(document).click(function(event) {
if ($(event.target).attr('data-event') !='qrcode' && $('.qrcode-wrap').not(':hidden').length) {
$('.qrcode-wrap').css('display', 'none');
}
});
// 推广链接
function promote(data,callback) {
$.ajax({
type: "POST",
url: ns.url("shop/diy/promoteRoute"),
data: data,
dataType: 'JSON',
success: function (res) {
if (res.code == 0) {
if(callback) callback(res.data.path);
}
}
});
}
</script>

View File

@@ -0,0 +1,85 @@
<style>
html,body {
width: 100%;
height: 100%;
background: #fff;
}
.icon-style-wrap {
padding: 15px;
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.icon-style-wrap .title {
margin-bottom: 10px;
}
.icon-style-wrap .icon-list {
flex: 1;
height: 0;
display: flex;
overflow-y: scroll;
flex-wrap: wrap;
}
.icon-style-wrap .icon-list::-webkit-scrollbar {
display: none;
}
.icon-style-wrap .icon-list .icon-block {
width: 56px;
height: 56px;
font-size: 60px;
border: 1px dashed #eee;
margin: 0 5px 5px 0;
cursor: pointer;
}
.icon-style-wrap .icon-list .icon-block:nth-child(5n+5) {
margin-right: 0;
}
.icon-style-wrap .icon-list .icon-block:hover {
border-color: var(--base-color);
}
.icon-style-wrap .icon-list .custom {
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<div class="icon-style-wrap" id="app">
<div class="title">图标风格</div>
<div class="icon-list">
<div class="icon-block" v-for="(item, index) in styleList" :key="index" @click="selectStyle(index)">
<iconfont icon="{$icon}" :value="item"></iconfont>
</div>
<div class="icon-block custom" @click="custom">
<p>自定义</p>
</div>
</div>
</div>
<script src="STATIC_JS/vue.js"></script>
{include file="diy/iconfont_component"/}
<script>
vue = new Vue({
el: "#app",
data: {
styleList: {:json_encode($icon_style)}
},
methods: {
selectStyle(index){
window.parent.postMessage({
event: 'selectIconStyle',
data: this.styleList[index],
}, location.origin);
},
custom(){
window.parent.postMessage({
event: 'selectIconStyle',
data: null,
}, location.origin);
}
}
})
</script>

View File

@@ -0,0 +1,140 @@
<link rel="stylesheet" href="STATIC_EXT/colorPicker/css/colorpicker.css" />
<link rel="stylesheet" href="STATIC_EXT/diyview/css/diyview.css?time=20240316" />
<style>
.icon-style-set{
padding: 15px 30px;
display: none;
}
</style>
<div id="app" class="layui-form icon-style-set" >
<div class="layui-form-item tag-wrap" >
<label class="layui-form-label sm">标签</label>
<div class="layui-input-block">
<div @click="labelData.control = true" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : labelData.control}">
<i class="layui-anim layui-icon">{{ labelData.control ? "&#xe643;" : "&#xe63f;" }}</i>
<div>开启</div>
</div>
<div @click="labelData.control = false" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : !labelData.control}">
<i class="layui-anim layui-icon">{{ !labelData.control ? "&#xe643;" : "&#xe63f;" }}</i>
<div>关闭</div>
</div>
</div>
</div>
<div v-show="labelData.control">
<div class="layui-form-item" >
<label class="layui-form-label sm">标签内容</label>
<div class="layui-input-block">
<input type="text" name='text' v-model="labelData.text" maxlength="3" class="layui-input len-short" autocomplete="off" />
</div>
</div>
<div class="layui-form-item flex">
<div class="flex_left">
<label class="layui-form-label sm">标签文字</label>
<slot></slot>
<div class="curr-color">
<span>{{ labelData.textColor ? labelData.textColor : "透明" }}</span>
</div>
<slot name="right"></slot>
</div>
<div class="layui-input-block flex_fill">
<div id="graphgic_nav_tag_color" class="picker colorSelector"><div :style="{ background : labelData.textColor }"></div></div>
<span class="color-selector-reset text-color" @click="reset('textColor')">重置</span>
</div>
</div>
<div class="layui-form-item flex">
<div class="flex_left">
<label class="layui-form-label sm">背景</label>
<slot></slot>
<div class="curr-color">
<span>{{ labelData.bgColorStart ? labelData.bgColorStart : "透明" }}</span>
<span>{{ labelData.bgColorEnd ? labelData.bgColorEnd : "透明" }}</span>
</div>
<slot name="right"></slot>
</div>
<div class="layui-input-block flex_fill">
<div id="bgColorStart" class="picker colorSelector"><div :style="{ background : labelData.bgColorStart }"></div></div>
<div id="bgColorEnd" class="picker colorSelector"><div :style="{ background : labelData.bgColorEnd }"></div></div>
<span class="color-selector-reset text-color" @click="reset('bgColorStart,bgColorEnd')">重置</span>
</div>
</div>
</div>
</div>
<script src="STATIC_JS/vue.js"></script>
<script src="STATIC_EXT/diyview/js/components.js"></script>
<script src="STATIC_EXT/colorPicker/js/colorpicker.js"></script>
<script>
var form,slider,colorpicker,vue, data;
data = {:json_encode($data)};
layui.use(['form', 'slider', 'colorpicker'], function() {
form = layui.form;
slider = layui.slider;
colorpicker = layui.colorpicker;
vue = new Vue({
el: "#app",
data: {
labelData: {},
defaultColor:{
'text' : '热门',
'textColor' : '#FFFFFF',
'bgColorStart' : '#F83288',
'bgColorEnd' : '#FE3523',
},
lazyLoad:false,
},
created: function (){
this.labelData = data;
this.labelData.control = this.labelData.control == 'true' ? true : false;
},
methods: {
reset: function (field) {
let self = this;
let field_arr = field.split(',');
for (let i in field_arr) {
self.labelData[field_arr[i]] = this.defaultColor[field_arr[i]];
}
},
colorRender(id, color, callback){
Colorpicker.create({
el: id,
color: color,
change: function (elem, hex) {
callback(hex)
}
});
}
},
mounted(){
var self = this;
self.colorRender('graphgic_nav_tag_color', self.labelData.textColor, function (color) {
self.labelData.textColor = color;
})
self.colorRender('bgColorStart', self.labelData.bgColorStart, function (color) {
self.labelData.bgColorStart = color;
})
self.colorRender('bgColorEnd', self.labelData.bgColorEnd, function (color) {
self.labelData.bgColorEnd = color;
})
setTimeout(function () {
self.lazyLoad = true;
$('.icon-style-set').show()
}, 100)
},
computed: {
}
})
})
function selectLabelListener(callback) {
var data = ns.deepclone(vue._data.labelData);
callback(data);
}
</script>

75
app/shop/view/diy/style.html Executable file
View File

@@ -0,0 +1,75 @@
<style>
.exchange-type{display: inline-block;min-width: 140px;height: 60px;line-height: 60px;border: 1px solid #ededed;border-radius: 4px;margin-right: 10px;position: relative;cursor: pointer;margin-bottom: 15px;}
.style{display: flex;-webkit-box-align: center;align-items: center;-webkit-box-pack: center;justify-content: center;padding: 0 10px;}
.style div{width: 50px;height: 16px;}
.style p{margin-left: 10px;font-size: 12px;color: #333;}
.preview-style img{margin-right: 64px; margin-bottom: 50px; height: 595px;width: 275px;-webkit-box-shadow: 5px 5px 20px #f5f5f5;box-shadow: 5px 5px 20px #f5f5f5;}
</style>
{notempty name="$theme_list"}
<div class="layui-form form-wrap">
<div class="layui-form-item">
<div class="layui-input-block">
{foreach $theme_list as $k=>$v}
<div class="exchange-type" data-id="{$v['id']}" data-title="{$v['title']}" data-name="{$v['name']}" data-main-color="{$v['main_color']}" data-aux-color="{$v['aux_color']}">
<div class="style">
<div style="background: url('{:img($v['color_img'])}') no-repeat;"></div>
<p>{$v['title']}</p>
</div>
</div>
{/foreach}
</div>
</div>
<div class="layui-input-block">
<div class="preview-style">
{foreach $theme_list as $k=>$v}
{foreach $v['preview'] as $ck=>$cv}
<img src="{:img($cv)}" data-name="{$v['name']}" {if $k!=0}style="display:none;"{/if}>
{/foreach}
{/foreach}
</div>
</div>
<div class="form-row">
<input type="hidden" name="style_theme" value="{$style|json_encode}">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</div>
{/notempty}
<script>
var theme = JSON.parse($("input[name='style_theme']").val());
$(".exchange-type").click(function() {
$(this).addClass("border-color").siblings("div").removeClass("border-color");
var obj = {
id: $(this).attr('data-id'),
title: $(this).attr('data-title'),
name: $(this).attr('data-name'),
main_color: $(this).attr('data-main-color'),
aux_color: $(this).attr('data-aux-color'),
};
$("input[name='style_theme']").val(JSON.stringify(obj));
$('.preview-style img').hide();
$('.preview-style img[data-name="' + obj.name + '"]').show();
});
$('.exchange-type[data-name="' + theme.name + '"]').click();
layui.use('form', function() {
var form = layui.form, repeat_flag = false; //防重复标识
form.on('submit(save)', function(data) {
if (repeat_flag) return;
repeat_flag = true;
data.field = JSON.parse(data.field.style_theme);
$.ajax({
url: ns.url("shop/diy/style"),
data: data.field,
dataType: 'JSON',
type: 'POST',
success: function(res) {
repeat_flag = false;
layer.msg(res.message);
}
});
});
});
</script>

108
app/shop/view/diy/template.html Executable file
View File

@@ -0,0 +1,108 @@
<style>
.tips {margin: 20px 0;border: 1px dashed;padding: 5px 10px;width: 90%;}
.theme-item{display: inline-block;min-width: 140px;height: 60px;line-height: 60px;border: 1px solid #ededed;border-radius: 4px;margin-right: 10px;position: relative;cursor: pointer;margin-bottom: 15px;}
.style{display: flex;-webkit-box-align: center;align-items: center;-webkit-box-pack: center;justify-content: center;padding: 0 10px;}
.style div{width: 50px;height: 16px;}
.style p{margin-left: 10px;font-size: 12px;color: #333;}
.template-list{display: flex;flex-wrap: wrap;}
.template-list li{overflow: hidden;position: relative;padding: 10px;margin-right: 30px;margin-bottom: 30px;width: 270px;height: 410px;border: 1px solid #e9e9e9;border-radius: 4px;box-sizing: border-box;}
.template-list li .item-img{overflow: hidden;width: 200px;height: 300px;margin: 0 auto;}
.template-list li .item-img img{max-width: 100%;}
.template-list li .item-hide{display: none;position: absolute;left: 0;right: 0;top: 0;bottom: 0;background-color: rgba(0,0,0,.6);text-align: center;}
.template-list li .item-name{display: block;padding-top: 7px;line-height: 22px;font-size: 14px;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}
.template-list li .item-desc{display: block;padding-top: 7px;line-height: 22px;font-size: 12px;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 1;-webkit-box-orient: vertical;color:#999;}
.template-list li .item-hide .item-btn-box{position: absolute;top: 50%;left: 50%;display: flex;flex-wrap: wrap;justify-content: center;align-items: center;transform: translate(-50%, -50%);}
.template-list li .item-hide button{border: 1px solid #fff;display: flex;justify-content: center;align-items: center;height: 33px;width: 100px;color: #fff;background: none;border-radius: 4px;cursor: pointer;}
.template-list li:hover .item-hide{display: block;}
.template-list li .item-hide button ~ button{margin-top: 15px;}
.template-list li .is-default{padding: 6px;font-size: 12px;color:#fff;border-radius: 4px;display: inline-block;margin-top: 5px;line-height: 1;}
</style>
<div class="theme-wrap">
{foreach $theme_list as $k=>$v}
<div class="theme-item {if $style['name']==$v['name']}border-color{/if}" data-id="{$v['id']}" data-title="{$v['title']}" data-name="{$v['name']}" data-main-color="{$v['main_color']}" data-aux-color="{$v['aux_color']}">
<div class="style">
<div style="background: url('{:img($v['color_img'])}') no-repeat;"></div>
<p>{$v['title']}</p>
</div>
</div>
{/foreach}
</div>
<ul class="template-list">
{foreach name="$template" item="vo"}
<li data-name="{$vo.name}" data-title="{$vo.title}" data-preview="{$vo.preview}" data-desc="{$vo.desc}">
<div class="item-img">
<img src="{:img($vo.cover)}" alt="">
</div>
<span class="item-name">{$vo.title}</span>
<span class="item-desc">{$vo.desc}</span>
{if isset($vo.is_default) && $vo.is_default == 1}
<span class="is-default bg-color">使用中</span>
{/if}
<div class="item-hide">
<div class="item-btn-box">
<button class="use" onclick="createTemplate('{$vo.goods_id}','{$vo.name}')">立即使用</button>
<button class="preview" onclick="$('#{$vo.name}').click()">预览</button>
</div>
</div>
<img id="{$vo.name}" class="layui-hide" src="{:img($vo.preview)}" layer-src>
</li>
{/foreach}
</ul>
<script>
layui.use('form', function() {
var repeat_flag = false; //防重复标识
$(".theme-item").click(function () {
$(this).addClass("border-color").siblings("div").removeClass("border-color");
var obj = {
id: $(this).attr('data-id'),
title: $(this).attr('data-title'),
name: $(this).attr('data-name'),
main_color: $(this).attr('data-main-color'),
aux_color: $(this).attr('data-aux-color'),
};
if (repeat_flag) return;
repeat_flag = true;
$.ajax({
url: ns.url("shop/diy/style"),
data: obj,
dataType: 'JSON',
type: 'POST',
success: function (res) {
repeat_flag = false;
layer.msg(res.message);
}
});
});
});
// 使用模板
function createTemplate(goods_id,name) {
$.ajax({
type: 'post',
url: ns.url("shop/diy/create"),
data: {
goods_id: goods_id,
name: name
},
dataType: 'JSON',
success: function(res) {
if (res.code >= 0){
location.hash = ns.hash("shop/diy/index");
}else{
layer.msg(res.message);
}
}
});
// var tips = `切换模版后需要重新<a href="{:href_url('shop/config/sitedeploy')}" target="_blank" class="text-color">部署</a>H5、小程序`;
// layer.confirm(tips, {
// title: '操作提示',
// btn: ['确定', '取消'],
// yes: function () {
// }
// });
}
</script>