初始上传

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,41 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\api\controller;
use addon\store\model\Config as ConfigModel;
use app\api\controller\BaseApi;
class Config extends BaseApi
{
/**
* 门店配置
* @return false|string
*/
public function config()
{
$config_model = new ConfigModel();
$business_config = $config_model->getStoreBusinessConfig($this->site_id)[ 'data' ][ 'value' ];
$withdraw_config = $config_model->getStoreWithdrawConfig($this->site_id)[ 'data' ][ 'value' ];
$res = [
'business_config' => $business_config,
'withdraw_config' => $withdraw_config
];
return $this->response($this->success($res));
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\api\controller;
use addon\store\model\Label;
use app\api\controller\BaseApi;
class Store extends BaseApi
{
/**
* 门店标签
* @return false|string
*/
public function labelPage()
{
$label_id_arr = $this->params['label_id_arr'] ?? ''; // 门店标签id集合
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($label_id_arr)) {
$condition[] = [ 'label_id', 'in', $label_id_arr ];
}
$label_model = new Label();
$res = $label_model->getStoreLabelPageList($condition, $page, $page_size, 'sort asc,label_id desc', 'label_id,label_name');
return $this->response($res);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace addon\store\component\controller;
use app\component\controller\BaseDiyView;
/**
* 门店标签·组件
*
*/
class StoreLabel extends BaseDiyView
{
/**
* 设计界面
*/
public function design()
{
return $this->fetch("store_label/design.html");
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace addon\store\component\controller;
use app\component\controller\BaseDiyView;
/**
* 门店展示·组件
*
*/
class StoreShow extends BaseDiyView
{
/**
* 设计界面
*/
public function design()
{
return $this->fetch("store_show/design.html");
}
}

View File

@@ -0,0 +1,18 @@
@CHARSET "UTF-8";
.component-store-label .preview-box ul{display: flex;align-content: center;padding: 10px 0;/*overflow-x: auto;*/overflow: hidden;}
.component-store-label .preview-box ul.between{justify-content: space-between;}
.component-store-label .preview-box ul::-webkit-scrollbar {height: 5px;}
.component-store-label .preview-box ul::-webkit-scrollbar-track {background-color: #e4e4e4;}
.component-store-label .preview-box ul::-webkit-scrollbar-thumb {background-color: #999;}
.component-store-label .preview-box ul li{display: flex;align-content: center;flex-shrink: 0;margin-right: 10px;word-break: keep-all;}
.component-store-label .preview-box ul li:last-of-type{margin-right: 0;}
.component-store-label .preview-box ul li .icon-box {width: 20px;height: 20px;font-size: 25px;margin-right: 5px;}
.component-store-label .preview-box ul li span{}
.component-store-label .diy-img {display: flex;align-items: center;}
.component-store-label .diy-img .right-wrap {display: flex;flex-direction: column;flex: 1;width: 0;}
.component-store-label .diy-img .action-box {display: flex;margin-bottom: 10px;}
.component-store-label .diy-img .action {margin-right: 10px;width: 42px;height: 28px;line-height: 28px;text-align: center;border: 1px solid #EEEEEE;cursor: pointer;}
.component-store-label .diy-img .action .iconfont {font-size: 20px;}
.component-store-label .diy-img .action:hover {border-color: var(--base-color);color: var(--base-color);}
.component-store-label .diy-img .desc{flex: 1;color: #B2B2B2;font-size: 12px;line-height: 1.6;}

View File

@@ -0,0 +1,122 @@
<nc-component :data="data[index]" class="component-store-label">
<!-- 预览 -->
<template slot="preview">
<template v-if="nc.lazyLoad">
<div class="preview-box"
:style="{
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
backgroundColor : nc.componentBgColor }">
<ul v-if="nc.previewList && Object.keys(nc.previewList).length" :class="{'between': Object.keys(nc.previewList).length == 3}">
<li v-for="(item, previewIndex) in nc.previewList" :key="previewIndex">
<div class="icon-box" v-if="nc.icon">
<iconfont :icon="nc.icon" :value="nc.style ? nc.style : ''"></iconfont>
</div>
<span :style="{color: nc.textColor ? nc.textColor : 'rgba(0,0,0,0)',fontWeight: nc.fontWeight,fontSize: nc.fontSize + 'px'}">{{item.label_name}}</span>
</li>
</ul>
</div>
</template>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<store-label-sources></store-label-sources>
<div class="template-edit-title">
<h3>风格</h3>
<div class="layui-form-item">
<label class="layui-form-label sm">风格</label>
<div class="layui-input-block">
<div @click="nc.contentStyle='style-1'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.contentStyle=='style-1') }">
<i class="layui-anim layui-icon">{{ nc.contentStyle=='style-1' ? "&#xe643;" : "&#xe63f;" }}</i>
<div>风格一</div>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label sm">图标</label>
<div class="layui-input-block diy-img">
<img-icon-upload :data="{data : nc, displayType : 'icon'}"></img-icon-upload>
<div class="right-wrap">
<div class="action-box">
<div class="action" @click="nc.tempData.methods.iconStyle($event)"><i class="iconfont iconpifu"></i></div>
<div class="action" :id="'store-label-color-' + nc.index"><i class="iconfont iconyanse"></i></div>
</div>
</div>
</div>
</div>
</div>
<div class="template-edit-title">
<h3>标签内容</h3>
<div class="layui-form-item" v-if="nc.tempData.labelSources">
<label class="layui-form-label sm">数据来源</label>
<div class="layui-input-block">
<div class="source-selected">
<div class="source">{{ nc.tempData.labelSources[nc.sources].text }}</div>
<div v-for="(item,sourcesKey) in nc.tempData.labelSources" :key="sourcesKey" class="source-item" :title="item.text" @click="nc.sources=sourcesKey" :class="{ 'text-color border-color' : (nc.sources == sourcesKey) }">
<i class='iconfont' :class='item.icon'></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-if="nc.sources == 'diy' && nc.tempData.methods">
<label class="layui-form-label sm">选择标签</label>
<div class="layui-input-block">
<div class="input-text selected-style" @click="nc.tempData.methods.addLabel()">
<span v-if="nc.labelIds.length == 0">请选择</span>
<span v-if="nc.labelIds.length > 0" class="text-color">已选{{ nc.labelIds.length }}个</span>
<i class="iconfont iconyoujiantou"></i>
</div>
</div>
</div>
<slide :data="{ field : 'count', label: '标签数量', min:1, max: 30}" v-if="nc.sources != 'diy'"></slide>
</div>
</template>
</template>
<!-- 样式编辑 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>文字设置</h3>
<slide :data="{ field : 'fontSize', label : '文字大小', min: 12, max : 20 }"></slide>
<div class="layui-form-item icon-radio">
<label class="layui-form-label sm">文字粗细</label>
<div class="layui-input-block">
<span v-for="item in nc.tempData.thicknessList" :class="[item.value == nc.fontWeight ? '' : 'layui-hide']">{{item.name}}</span>
<ul class="icon-wrap">
<li v-for="(item, index) in nc.tempData.thicknessList" :class="[item.value == nc.fontWeight ? 'text-color border-color' : '']" @click="nc.fontWeight = item.value">
<i class="iconfont" :class="[{'text-color': item.value == nc.fontWeight}, item.src]"></i>
</li>
</ul>
</div>
</div>
<color :data="{ field : 'textColor', label : '文字颜色',defaultColor: '#303133' }"></color>
</div>
</template>
</template>
<!-- 资源 -->
<template slot="resource">
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -0,0 +1,159 @@
var storeLabelHtml = '<div style="display:none;"></div>';
Vue.component("store-label-sources", {
template: storeLabelHtml,
data: function() {
return {
data: this.$parent.data,
labelSources: {
initial: {
text: "默认",
icon: "iconmofang"
},
diy: {
text: "手动选择",
icon: "iconshoudongxuanze"
},
},
thicknessList: [
{name: "加粗", src: "iconbold", value: "bold"},
{name: "常规", src: "iconbold-copy", value: "normal"}
]
}
},
created:function() {
if(!this.$parent.data.verify) this.$parent.data.verify = [];
this.$parent.data.verify.push(this.verify);//加载验证方法
this.$parent.data.ignore = ['elementAngle','elementBgColor']; //加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
if(Object.keys(this.$parent.data.previewList).length == 0) {
for (var i = 1; i < 4; i++) {
this.$parent.data.previewList["label_id_" + ns.gen_non_duplicate(i)] = {
label_name: "标签名称",
label_id:0
};
}
}
// 组件所需的临时数据
this.$parent.data.tempData = {
labelSources:this.labelSources,
thicknessList:this.thicknessList,
methods: {
addLabel: this.addLabel,
iconStyle: this.iconStyle
}
};
this.fetchIconColor();
},
methods: {
verify: function (index) {
var res = {code: true, message: ""};
return res;
},
/**
* 选择图标风格
* @param event
*/
iconStyle(event) {
var self = this;
selectIconStyle({
elem: event.currentTarget,
icon: self.data.icon,
callback: function (data) {
if (data) {
self.data.style = data;
} else {
iconStyleSet({
style: JSON.stringify(self.data.style),
query: {
icon: self.data.icon
}
}, function (style) {
self.data.style = style;
})
}
}
})
},
/**
* 渲染颜色组件
* @param id
* @param color
* @param callback
*/
colorRender(id, color, callback) {
setTimeout(function () {
Colorpicker.create({
el: id,
color: color,
change: function (elem, hex) {
callback(elem, hex)
}
});
})
},
/**
* 渲染图标颜色选择器
*/
fetchIconColor() {
var self = this;
self.colorRender('store-label-color-' + self.data.index, '', function (elem, color) {
if (self.data.style.iconBgColor.length || self.data.style.iconBgImg) {
self.data.style.iconBgColor = [color];
} else {
self.data.style.iconColor = [color];
}
self.$forceUpdate();
});
},
addLabel: function () {
var self = this;
self.labelSelect(function (res) {
self.$parent.data.labelIds = [];
self.$parent.data.previewList = {};
for (var i = 0; i < res.length; i++) {
self.$parent.data.labelIds.push(res[i].label_id);
self.$parent.data.previewList["label_id_" + ns.gen_non_duplicate(i)] = {
label_name: res[i].label_name,
label_id: res[i].label_id
};
}
}, self.$parent.data.labelIds);
},
labelSelect: function (callback, selectId) {
var self = this;
layui.use(['layer'], function () {
var url = ns.url("store://shop/store/labelSelect", {request_mode: 'iframe', select_id: selectId.toString()});
layer.open({
title: "门店标签选择",
type: 2,
area: ['1000px', '600px'],
fixed: false, //不固定
btn: ['保存', '返回'],
content: url,
yes: function (index, layero) {
var iframeWin = document.getElementById(layero.find('iframe')[0]['name']).contentWindow;//得到iframe页的窗口对象执行iframe页的方法
iframeWin.selectStoreLabelListener(function (obj) {
if (typeof callback == "string") {
try {
eval(callback + '(obj)');
layer.close(index);
} catch (e) {
console.error('回调函数' + callback + '未定义');
}
} else if (typeof callback == "function") {
callback(obj);
layer.close(index);
}
});
}
});
});
},
}
});

View File

@@ -0,0 +1,173 @@
@CHARSET "UTF-8";
.draggable-element .component-store-show-info .preview-draggable .preview-box {
}
/* 风格一 */
.component-store-show-info .style-one, .component-store-show-info .style-three {
display: flex;
justify-content: space-between;
padding: 0 10px;
}
.component-store-show-info .style-one .info-item {
flex: 1;
}
.component-store-show-info .style-one .store-name {
margin-right: 10px;
font-size: 16px;
}
.component-store-show-info .style-one .change {
font-size: 12px;
}
.component-store-show-info .style-one p {
margin-top: 10px;
font-size: 12px;
}
.component-store-show-info .style-one .img-wrap, .component-store-show-info .style-two .img-wrap, .component-store-show-info .style-three .img-wrap {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
}
.component-store-show-info .style-one .img-wrap img, .component-store-show-info .style-two .img-wrap img, .component-store-show-info .style-three .img-wrap img {
width: 100%;
height: 100%;
}
/* 风格二 */
.component-store-show-info .style-two {
display: flex;
}
.component-store-show-info .style-two .info-item {
margin-left: 10px;
}
.component-store-show-info .style-two .store-name {
font-size: 16px;
}
.component-store-show-info .style-two p {
margin-top: 10px;
font-size: 12px;
}
.component-store-show-info .style-two .change {
margin-left: auto;
align-self: center;
flex-shrink: 0;
}
/* 风格三 */
.component-store-show-info .style-three .info-item {
display: flex;
align-items: center;
}
.component-store-show-info .style-three .store-name {
margin-left: 8px;
margin-right: 15px;
font-size: 16px;
}
.component-store-show-info .style-three .change {
font-size: 12px;
}
.component-store-show-info .style-three .icon-wrap {
display: flex;
justify-content: space-between;
align-items: center;
width: 20px;
height: 20px;
align-self: center;
}
.component-store-show-info .style-three .icon-wrap img {
max-width: 100%;
max-height: 100%;
}
/* 风格四 */
.component-store-show-info .style-four {
display: flex;
justify-content: space-between;
align-items: center;
}
.component-store-show-info .style-four .store-left-wrap {
display: flex;
align-items: center;
line-height: 34px;
}
.component-store-show-info .style-four .store-left-wrap .iconweizhi {
font-size: 14px;
color: #303133;
margin-right: 3px;
}
.component-store-show-info .style-four .store-left-wrap .layui-icon-down {
font-size: 14px;
margin-left: 3px;
color: #303133;
}
.component-store-show-info .style-four .store-right-search {
width: 235px;
height: 35px;
line-height: 35px;
display: flex;
justify-content: space-between;
padding: 0 15px;
font-size: 12px;
color: #909399;
box-sizing: border-box;
background-color: #FFFFFF;
border-radius: 18px;
position: relative;
}
.component-store-show-info .style-four .store-right-search .iconsousuo2 {
position: absolute;
right: 15px;
height: 12px;
font-size: 13px;
color: #909399;
}
/* 弹窗 */
.style-list-con-store {
display: flex;
flex-wrap: wrap;
}
.style-list-con-store .item {
height: 100px;
line-height: 100px;
width: 32%;
margin-right: 2%;
margin-bottom: 15px;
cursor: pointer;
border: 1px solid #ededed;
background: #f7f8fa;
box-sizing: border-box;
}
.style-list-con-store .item img {
max-width: 100%;
}
.style-list-con-store .item:nth-child(3n) {
margin-right: 0;
}

View File

@@ -0,0 +1,94 @@
<nc-component :data="data[index]" class="component-store-show-info">
<!-- 预览 -->
<template slot="preview">
<div class="preview-box">
<div class="info-list">
<div class="info-item style-one" v-if="nc.style == 1">
<div class="info-item">
<span class="store-name" :style="{ color: nc.textColor }">门店名称</span>
<span class="change" :style="{ color: nc.textColor }">切换 ></span>
<p :style="{ color: nc.textColor }">这里展示门店地址</p>
</div>
<div class="img-wrap">
<img src="{$resource_path}/img/default_store.png" />
</div>
</div>
<div class="info-item style-three" v-if="nc.style == 2">
<div class="info-item">
<div class="img-wrap">
<img src="{$resource_path}/img/default_store.png" />
</div>
<span class="store-name" :style="{ color: nc.textColor }">门店名称</span>
<span class="change" :style="{ color: nc.textColor }">切换 ></span>
</div>
<div class="icon-wrap">
<img src="{$resource_path}/img/sousuo.png" />
</div>
</div>
<div class="info-item style-four" v-if="nc.style == 3">
<div class="store-left-wrap">
<i class="iconfont iconweizhi" :style="{ color: nc.textColor }"></i>
<span class="store-name" :style="{ color: nc.textColor }">门店名称</span>
<i class="layui-icon layui-icon-down" :style="{ color: nc.textColor }"></i>
</div>
<div class="store-right-search">
<div>商品搜索<i class="iconfont iconsousuo2"></i></div>
</div>
</div>
</div>
</div>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>门店风格</h3>
<store-show-style></store-show-style>
</div>
</template>
<!-- 风格弹框 -->
<article class="store-style" style="display: none;">
<div class="style-list-con-store">
<div class="item" :class="{'selected border-color': nc.style == 1}">
<img src="{$resource_path}/img/style1.png" />
<span class="layui-hide">风格一</span>
</div>
<div class="item" :class="{'selected border-color': nc.style == 2}">
<img src="{$resource_path}/img/style3.png" />
<span class="layui-hide">风格二</span>
</div>
<div class="item" :class="{'selected border-color': nc.style == 3}">
<img src="{$resource_path}/img/style4.png" />
<span class="layui-hide">风格三</span>
</div>
</div>
<input type="hidden" name="style">
<input type="hidden" name="style_name" />
</article>
</template>
<!-- 样式编辑 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>门店样式</h3>
<color :data="{ field : 'textColor', 'label' : '文本颜色','defaultColor': '#303133' }"></color>
</div>
</template>
</template>
<!-- 资源 -->
<template slot="resource">
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -0,0 +1,55 @@
var storeShowStyle = '<div>';
storeShowStyle += '<div class="layui-form-item">';
storeShowStyle += '<label class="layui-form-label sm">选择风格</label>';
storeShowStyle += '<div class="layui-input-block">';
storeShowStyle += '<div v-if="data.styleName" class="input-text text-color selected-style" @click="selectGoodsStyle()">{{data.styleName}} <i class="layui-icon layui-icon-right"></i></div>';
storeShowStyle += '<div v-else class="input-text selected-style" @click="selectGoodsStyle()">选择 <i class="layui-icon layui-icon-right"></i></div>';
storeShowStyle += '</div>';
storeShowStyle += '</div>';
storeShowStyle += '</div>';
Vue.component("store-show-style", {
template: storeShowStyle,
data: function() {
return {
data: this.$parent.data,
}
},
created:function() {
if(!this.$parent.data.verify) this.$parent.data.verify = [];
this.$parent.data.verify.push(this.verify);//加载验证方法
this.$parent.data.ignore = ['elementAngle','componentAngle','elementBgColor','componentBgColor']; //加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
},
methods: {
verify: function (index) {
var res = { code: true, message: "" };
return res;
},
selectGoodsStyle: function() {
var self = this;
layer.open({
type: 1,
title: '风格选择',
area:['800px','270px'],
btn: ['确定', '返回'],
content: $(".draggable-element[data-index='" + self.data.index + "'] .edit-attribute .store-style").html(),
success: function(layero, index) {
$(".layui-layer-content input[name='style']").val(self.data.style);
$(".layui-layer-content input[name='style_name']").val(self.data.styleName);
$("body").off("click", ".layui-layer-content .style-list-con-store .item").on("click", ".layui-layer-content .style-list-con-store .item", function () {
$(this).addClass("selected border-color").siblings().removeClass("selected border-color");
$(".layui-layer-content input[name='style']").val($(this).index() + 1);
$(".layui-layer-content input[name='style_name']").val($(this).find("span").text());
});
},
yes: function (index, layero) {
self.data.style = $(".layui-layer-content input[name='style']").val();
self.data.styleName = $(".layui-layer-content input[name='style_name']").val();
layer.closeAll()
}
});
},
}
});

View File

@@ -0,0 +1,8 @@
<?php
return [
'store/shopapi/store/settlement/index' => 'ADDON_STORE_SHOP_STORE_SETTLEMENT',//门店结算列表
'store/shopapi/store/settlement/info' => 'ADDON_STORE_SHOP_STORE_SETTLEMENT_INFO',//结算详情
'store/shopapi/store/settlement/settlement' => 'ADDON_STORE_SHOP_STORE_SETTLEMENT_SETTLEMENT',//门店结算
'store/shopapi/store/settlement/detail' => 'ADDON_STORE_SHOP_STORE_SETTLEMENT_INFO',//结算详情
];

View File

@@ -0,0 +1,108 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
return [
[
'name' => 'store_settlement',
'title' => '门店结算',
'type' => 'page',
'parent' => 'stat',
'url' => 'pages/store/settlement',
'children' => [
[
'name' => 'settlement_record',
'title' => '结算记录',
'type' => 'page',
'url' => 'pages/store/settlement_record',
],
[
'name' => 'settlement_apply',
'title' => '申请结算',
'type' => 'api',
'url' => 'store/storeapi/withdraw/apply',
]
]
],
[
'name' => 'store_config_root',
'title' => '门店设置',
'type' => 'page',
'url' => 'pages/store/index',
'parent' => 'config',
'children' => [
[
'name' => 'store_config',
'title' => '门店设置',
'type' => 'page',
'url' => 'pages/store/config',
],
[
'name' => 'store_operate_config',
'title' => '运营设置',
'type' => 'page',
'url' => 'pages/store/operate',
]
]
],
[
'name' => 'printer_config',
'title' => '小票打印',
'type' => 'page',
'url' => 'pages/printer/list',
'parent' => 'config',
'children' => [
[
'name' => 'add_printer',
'title' => '添加打印机',
'type' => 'api',
'url' => 'printer/storeapi/printer/add',
],
[
'name' => 'edit_printer',
'title' => '编辑打印机',
'type' => 'api',
'url' => 'printer/storeapi/printer/edit',
],
[
'name' => 'delete_printer',
'title' => '删除打印机',
'type' => 'api',
'url' => 'printer/storeapi/printer/deleteprinter',
],
]
],
[
'name' => 'store_deliver_config',
'title' => '配送员',
'type' => 'page',
'url' => 'pages/store/deliver',
'parent' => 'config',
'children' => [
[
'name' => 'add_deliver',
'title' => '添加配送员',
'type' => 'api',
'url' => 'printer/storeapi/printer/adddeliver',
],
[
'name' => 'edit_deliver',
'title' => '编辑配送员',
'type' => 'api',
'url' => 'printer/storeapi/printer/editdeliver',
],
[
'name' => 'delete_deliver',
'title' => '删除配送员',
'type' => 'api',
'url' => 'cashier/storeapi/store/deletedeliver',
],
]
],
];

81
addon/store/config/diy_view.php Executable file
View File

@@ -0,0 +1,81 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
return [
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据json格式' ]
'template' => [
[
'title' => '门店主页',
'name' => 'DIY_STORE',
'path' => '/pages/index/index',
'value' => '',
'rule' => [
'support' => [ '', 'DIY_STORE' ],
'util_type' => [ 'SYSTEM' ] // 组件类型
],
'sort' => 4
],
],
// 后台自定义组件——装修
'util' => [
[
'name' => 'StoreShow',
'title' => '门店展示',
'type' => 'SYSTEM',
'value' => '{"style":1, "styleName": "风格一"}',
'sort' => '10061',
'support_diy_view' => '',
'max_count' => 1,
'icon' => 'iconfont icondianpu'
],
[
'name' => 'StoreLabel',
'title' => '门店标签',
'type' => 'SYSTEM',
'value' => '{"style":{"fontSize":"60","iconBgColor":[],"iconBgColorDeg":0,"iconBgImg":"","bgRadius":0,"iconColor":["#000000"],"iconColorDeg":0},"sources":"initial","labelIds":[],"icon":"","contentStyle":"style-1","previewList":{},"fontSize":14,"fontWeight":"normal","count":3}',
'sort' => '10062',
'support_diy_view' => '',
'max_count' => 0,
'icon' => 'iconfont iconmendianbiaoqian'
],
],
// 自定义页面路径
'link' => [
[
'name' => 'STORE_LIST',
'title' => '门店列表',
'wap_url' => '/pages_tool/store/list',
'parent' => 'BASICS_LINK',
'web_url' => '',
'sort' => 0
]
],
// 自定义图标库
'icon_library' => [],
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ]多个逗号隔开自定义组件名称前缀必须是diy-,也可以引用第三方组件
'component' => [],
// uni-app 页面,多个逗号隔开
'pages' => [],
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
'info' => [],
// 主题风格配色格式可以自由定义扩展【在uni-app中通过this.themeStyle... 获取定义的颜色字段例如this.themeStyle.main_color】
'theme' => [],
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据json格式] ]
'data' => [
]
];

81
addon/store/config/event.php Executable file
View File

@@ -0,0 +1,81 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
return [
'bind' => [
],
'listen' => [
'ShowPromotion' => [
'addon\store\event\ShowPromotion'
],
'OrderCreateAfter' => [
'addon\store\event\OrderCreateAfter',
],
//订单关闭
'OrderClose' => [
'addon\store\event\OrderClose',
],
//订单完成
'OrderComplete' => [
'addon\store\event\OrderComplete',
'addon\store\event\StoreOrderSettlementCalculate'
],
//订单支付
'OrderPayAfter' => [
'addon\store\event\OrderPayAfter',
],
//门店结算
'StoreWithdrawPeriodCalc' => [
'addon\store\event\StoreWithdrawPeriodCalc'
],
//门店添加
'AddStore' => [
'addon\store\event\AddStore'
],
/**
* 商品编辑
*/
'GoodsEdit' => [
'addon\store\event\GoodsEdit'
],
'PointExchangeOrderCreate' => [
'addon\store\event\PointExchangeOrderCreate'
],
'GoodsSkuStock' => [
'addon\store\event\GoodsSkuStock'
],
/**
* 门店结算相关
*/
//订单项计算
'OrderGoodsCalculate' => [
'addon\store\event\OrderGoodsCalculate'
],
'OrderCreateCommonData' => [
'addon\store\event\OrderCreateCommonData'
],
'OrderRefundMoneyFinish' => [
'addon\store\event\StoreOrderRefundSettlementCalculate'
],
//转账结果通知
'PayTransferNotify' => [
'addon\store\event\WithdrawTransferNotify',
],
'PayTransferCheck' => [
'addon\store\event\WithdrawTransferCheck',
],
],
'subscribe' => [
],
];

21
addon/store/config/info.php Executable file
View File

@@ -0,0 +1,21 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
return [
'name' => 'store',
'title' => '门店管理',
'description' => '门店管理功能',
'type' => 'tool', //插件类型 system :系统插件 promotion:营销插件 tool:工具插件
'status' => 1,
'author' => '',
'version' => '5.5.3',
'version_no' => '553250709001',
'content' => '',
];

300
addon/store/config/menu_shop.php Executable file
View File

@@ -0,0 +1,300 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
return [
[
'name' => 'ADDON_STORE_BASE',
'title' => '门店',
'url' => 'store://shop/store/index',
'parent' => '',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 3,
'picture' => 'iconmendianzhuye',
'picture_selected' => '',
'child_list' => [
[
'name' => 'ADDON_STORE_INDEX',
'title' => '门店概况',
'url' => 'store://shop/store/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 1,
],
[
'name' => 'ADDON_STORE_MANAGE',
'title' => '门店管理',
'url' => 'store://shop/store/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 2,
'child_list' => [
[
'name' => 'ADDON_STORE_MANAGE_LIST',
'title' => '门店列表',
'url' => 'store://shop/store/lists',
'is_show' => 1,
'parent' => 'CONFIG_BASE',
'is_control' => 1,
'is_icon' => 0,
'sort' => 1,
'picture' => 'app/shop/view/public/img/icon_new/store_new.png',
'picture_selected' => 'app/shop/view/public/img/icon_new/store_select.png',
'child_list' => [
[
'name' => 'STORE_ADD',
'title' => '添加门店',
'url' => 'store://shop/store/addstore',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
'type' => 'button',
],
[
'name' => 'STORE_EDIT',
'title' => '基础设置',
'url' => 'store://shop/store/editstore',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
'type' => 'button',
],
[
'name' => 'STORE_DELETE',
'title' => '删除门店',
'url' => 'store://shop/store/deletestore',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
'type' => 'button',
],
[
'name' => 'STORE_FROZEN',
'title' => '关闭门店',
'url' => 'store://shop/store/frozenStore',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
'type' => 'button',
],
[
'name' => 'STORE_MODIFY_PASSWORD',
'title' => '重置密码',
'url' => 'store://shop/store/modifyPassword',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
'type' => 'button',
],
[
'name' => 'STORE_OPERATE',
'title' => '运营设置',
'url' => 'store://shop/store/operate',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 2,
'type' => 'button',
],
[
'name' => 'STORE_DELIVERY',
'title' => '同城配送',
'url' => 'store://shop/store/local',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 4,
'type' => 'button',
],
[
'name' => 'STORE_SETTLEMENT',
'title' => '结算设置',
'url' => 'store://shop/store/settlement',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 3,
'type' => 'button',
],
[
'name' => 'STORE_DELIVER',
'title' => '配送员',
'url' => 'store://shop/store/deliverlists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 5,
'type' => 'button',
],
[
'name' => 'STORE_DELIVER_ADD',
'title' => '配送员添加',
'url' => 'store://shop/store/addDeliver',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 2,
'type' => 'button',
],
[
'name' => 'STORE_DELIVER_EDIT',
'title' => '配送员编辑',
'url' => 'store://shop/store/editDeliver',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 2,
'type' => 'button',
],
]
],
[
'name' => 'ADDON_STORE_CATEGORY',
'title' => '门店分类',
'url' => 'store://shop/store/category',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 2,
],
[
'name' => 'ADDON_STORE_TAG',
'title' => '门店标签',
'url' => 'store://shop/store/tag',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 3,
]
]
],
[
'name' => 'ADDON_STORE_SHOP_STORE_CONFIG',
'title' => '门店设置',
'url' => 'store://shop/config/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 3,
],
[
'name' => 'ADDON_STORE_SHOP_STORE_ACCOUNT',
'title' => '门店账户',
'url' => 'store://shop/account/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 4,
'child_list' => [
[
'name' => 'ADDON_STORE_SHOP_STORE_ACCOUNT_EXPORT_ADD',
'title' => '账户导出',
'url' => 'store://shop/account/addexport',
'is_show' => 0,
'is_control' => 1,
'sort' => 1,
'type' => 'button',
],
[
'name' => 'ADDON_STORE_SHOP_STORE_ACCOUNT_EXPORT_LIST',
'title' => '导出记录',
'url' => 'store://shop/account/exportlist',
'is_show' => 0,
'is_control' => 1,
'sort' => 1,
'type' => 'button',
],
[
'name' => 'ADDON_STORE_SHOP_STORE_ACCOUNT_EXPORT_DELETE',
'title' => '导出删除',
'url' => 'store://shop/account/deleteexport',
'is_show' => 0,
'is_control' => 1,
'sort' => 1,
'type' => 'button',
],
]
],
[
'name' => 'ADDON_STORE_SHOP_STORE_WITHDRAW',
'title' => '门店结算',
'url' => 'store://shop/withdraw/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 5,
'child_list' => [
[
'name' => 'ADDON_STORE_SHOP_STORE_WITHDRAW_INFO',
'title' => '结算详情',
'url' => 'store://shop/withdraw/detail',
'is_show' => 0,
'is_control' => 1,
'sort' => 1,
'type' => 'button',
],
]
],
]
],
[
'name' => 'STORE_STAT',
'title' => '门店数据',
'parent' => 'STAT_SHOP',
'url' => 'store://shop/stat/store',
'picture' => '',
'picture_selected' => '',
'is_show' => 1,
],
[
'name' => 'STORE_DIY',
'title' => '门店装修',
'parent' => 'SHOP_DIY',
'url' => 'store://shop/store/diy',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 20,
'picture' => '',
'picture_selected' => '',
'child_list' => []
],
];

238
addon/store/config/menu_store.php Executable file
View File

@@ -0,0 +1,238 @@
<?php
// +----------------------------------------------------------------------
// | 平台端菜单设置
// +----------------------------------------------------------------------
return [
[
'name' => 'ADDON_STORE_INDEX',
'title' => '概况',
'url' => 'store://store/index/index',
'is_show' => 1,
'is_control' => 0,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/intro.png',
'sort' => 1,
],
[
'name' => 'ADDON_STORE_GOODS',
'title' => '商品管理',
'url' => 'store://store/goods/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/goods.png',
'sort' => 2,
],
[
'name' => 'STORE_STOCK_IMPORT',
'title' => '批量入库',
'url' => 'store://store/storestockimport/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/stock_import.png',
'sort' => 3,
'child_list' => [
[
'name' => 'STORE_STOCK_IMPORT_DETAIL',
'title' => '详情',
'url' => 'store://store/storestockimport/detail',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'sort' => 2,
'child_list' => []
],
]
],
[
'name' => 'ADDON_STORE_ORDER',
'title' => '订单管理',
'url' => 'store://store/order/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/order.png',
'sort' => 4,
'child_list' => [
[
'name' => 'ADDON_STORE_ORDER_MANAGE',
'title' => '订单列表',
'url' => 'store://store/order/lists',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 1,
'child_list' => [
[
'name' => 'ADDON_STORE_ORDER_DETAIL',
'title' => '自提订单详情',
'url' => 'store://store/order/detail',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
],
],
],
[
'name' => 'ADDON_STORE_ORDER_VERIFY',
'title' => '核销台',
'url' => 'store://store/verify/verifycard',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'sort' => 2,
'child_list' => []
],
]
],
[
'name' => 'ADDON_STORE_CASH',
'title' => '收银台',
'url' => 'store://store/cash/cash',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/sellte.png',
'sort' => 5,
'child_list' => []
],
[
'name' => 'ADDON_STORE_ACCOUNT',
'title' => '结算管理',
'url' => 'store://store/settlement/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/settlement.png',
'sort' => 6,
'child_list' => []
],
[
'name' => 'ADDON_STORE_MEMBER',
'title' => '会员管理',
'url' => 'store://store/member/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/member.png',
'sort' => 7,
'child_list' => [
[
'name' => 'ADDON_STORE_MEMBER_INDEX',
'title' => '会员概况',
'url' => 'store://store/member/index',
'sort' => 1,
'is_show' => 1
],
[
'name' => 'ADDON_STORE_MEMBER_LIST',
'title' => '会员列表',
'url' => 'store://store/member/lists',
'sort' => 2,
'is_show' => 1,
'child_list' => [
[
'name' => 'ADDON_STORE_MEMBER_DETAIL',
'title' => '会员详情',
'url' => 'store://store/member/detail',
'sort' => 1,
'is_show' => 0
]
]
],
]
],
[
'name' => 'ADDON_STORE_USER',
'title' => '员工管理',
'url' => 'store://store/user/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/user.png',
'sort' => 8,
'child_list' => [
[
'name' => 'ADDON_STORE_USER_LIST',
'title' => '员工管理',
'url' => 'store://store/user/index',
'sort' => 1,
'is_show' => 1,
'child_list' => [
[
'name' => 'ADDON_STORE_USER_ADD',
'title' => '添加员工',
'url' => 'store://store/user/addUser',
'sort' => 1,
'is_show' => 0
],
[
'name' => 'ADDON_STORE_USER_EDIT',
'title' => '修改员工',
'url' => 'store://store/user/editUser',
'sort' => 1,
'is_show' => 0
],
]
],
[
'name' => 'ADDON_STORE_USERLOG',
'title' => '操作日志',
'url' => 'store://store/user/userlog',
'sort' => 2,
'is_show' => 1
],
[
'name' => 'ADDON_STORE_USER_GROUP',
'title' => '角色管理',
'url' => 'store://store/user/group',
'sort' => 3,
'is_show' => 1,
'child_list' => [
[
'name' => 'ADDON_STORE_USER_GROUP_ADD',
'title' => '添加角色',
'url' => 'store://store/user/addGroup',
'sort' => 1,
'is_show' => 0
],
[
'name' => 'ADDON_STORE_USER_GROUP_EDIT',
'title' => '修改角色',
'url' => 'store://store/user/editGroup',
'sort' => 1,
'is_show' => 0
],
]
],
]
],
[
'name' => 'ADDON_STORE_INFO',
'title' => '门店设置',
'url' => 'store://store/store/config',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/info.png',
'sort' => 9,
'child_list' => []
],
[
'name' => 'ADDON_STORE_DIY',
'title' => '主页装修',
'url' => 'store://store/diy/index',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => 'addon/store/store/view/public/img/store_icon/diy.png',
'sort' => 10,
'child_list' => []
]
];

22
addon/store/event/AddStore.php Executable file
View File

@@ -0,0 +1,22 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
/**
*添加门店
*/
class AddStore
{
public function handle($data)
{
}
}

27
addon/store/event/GoodsEdit.php Executable file
View File

@@ -0,0 +1,27 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreGoods;
/**
* 商品编辑之后
*/
class GoodsEdit
{
public function handle($data)
{
$goods = new StoreGoods();
$goods->goodsEditAfter($data['goods_id'], $data['site_id']);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreGoodsSku;
class GoodsSkuStock
{
public function handle($params)
{
//todo 优化
$order_object = $params['order_object'];
$store_goods_sku_model = new StoreGoodsSku();
foreach ($params[ 'goods_list' ] as $v) {
$condition = array (
[ 'store_id', '=', $order_object->delivery[ 'store_id' ] ],
[ 'sku_id', '=', $v[ 'sku_id' ] ]
);
$store_sku_info = model('store_goods_sku')->getInfo($condition, 'id, goods_id, stock');
if (empty($store_sku_info)) {
return $store_goods_sku_model->error([ 'error_code' => 11 ], '当前门店库存不足,请选择其他门店');
}
$store_sku_info[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if (( $store_sku_info[ 'stock' ] - $v[ 'num' ] ) < 0) {
return $store_goods_sku_model->error([ 'error_code' => 11 ], '当前门店库存不足,请选择其他门店');
}
}
}
}

32
addon/store/event/Install.php Executable file
View File

@@ -0,0 +1,32 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use app\model\system\Menu;
/**
* 应用安装
*/
class Install
{
/**
* 执行安装
*/
public function handle()
{
$menu = new Menu();
$menu->refreshMenu("store", "store");
$menu->refreshCashierAuth('store');
return success();
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreGoodsSku;
use app\model\order\OrderCommon;
/**
* 关闭订单返还门店库存
*/
class OrderClose
{
public function handle($data)
{
// $order_model = new OrderCommon();
// $order_info_result = $order_model->getOrderInfo([['order_id', '=', $data['order_id']]], 'site_id,member_id,delivery_store_id');
// $order_info = $order_info_result['data'];
//
// if ($order_info["delivery_store_id"] > 0) {
// //减少库存
// $order_goods_list_result = $order_model->getOrderGoodsList([['order_id', '=', $data['order_id']]], "num,sku_id");
// $order_goods_list = $order_goods_list_result["data"];
// foreach ($order_goods_list as $k => $v) {
// $store_goods_sku_model = new StoreGoodsSku();
// $stock_result = $store_goods_sku_model->incStock(["store_id" => $order_info["delivery_store_id"], "sku_id" => $v["sku_id"], 'stock' => $v["num"]]);
// if ($stock_result["code"] < 0) {
// return $stock_result;
// }
// }
// }
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreOrder;
/**
* 添加下单用户为门店用户
*/
class OrderComplete
{
public function handle($order)
{
$store_order = new StoreOrder();
$res = $store_order->orderComplete($order[ 'order_id' ]);
return $res;
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreMember as StoreMemberModel;
use app\model\order\OrderCommon;
/**
* 添加下单用户为门店用户
*/
class OrderCreateAfter
{
public function handle($data)
{
$order_data = $data['create_data'] ?? [];
$delivery_store_id = $order_data['delivery_store_id'] ?? 0;
$member_id = $order_data['member_id'] ?? 0;
if ($delivery_store_id > 0 && $member_id > 0) {
//添加门店关注记录
$shop_member_model = new StoreMemberModel();
$res = $shop_member_model->addStoreMember($delivery_store_id, $member_id);
if ($res["code"] < 0) {
return $res;
}
}
return true;
}
}

View File

@@ -0,0 +1,229 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\event;
use addon\cashier\model\order\CashierOrderPay;
use app\model\express\Express;
use app\model\express\Local;
use app\model\order\OrderCommon;
use app\model\order\OrderCreateTool;
use app\model\store\Store;
/**
* 订单创建相关
*/
class OrderCreateCommonData
{
use OrderCreateTool;
// 行为扩展的执行入口必须是run
public function handle($params)
{
/** @var \app\model\order\OrderCreate $order_object */
$order_object = $params['order_object'];
$type = $params['type'];
$store_id = $order_object->store_id ?? 0;
$site_id = $order_object->site_id;
if($store_id == 0)
return null;
$store_model = new Store();
$store_condition = array(
['store_id', '=', $store_id]
);
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
$store_is_express = $store_info['is_express'];
$store_is_o2o = $store_info['is_o2o'];
$store_is_pickup = $store_info['is_pickup'];
$store_config_model = new \addon\store\model\Config();
$store_config = $store_config_model->getStoreBusinessConfig($site_id)['data']['value'] ?? [];
$deliver_type_sort = $order_object->config('delivery_type_sort');
$deliver_sort_list = explode(',', $deliver_type_sort['value']['deliver_type']);
// $deliver_sort_list = $params['deliver_sort_list'];
$latitude = $order_object->param[ 'latitude' ] ?? 0;
$longitude= $order_object->param[ 'longitude' ] ?? 0;
$order_model = new OrderCommon();
switch($type){
case 'trade':
//必须是连锁模式 还需要判断某一个插件是否存在
if($store_id > 0 && $store_config['store_business'] == 'store'){
foreach ($deliver_sort_list as $type) {
// 物流
if ($type == 'express') {
$store_is_express = $store_is_express ?? 0;
if($store_is_express == 1){
$title = $order_object->config('express')[ 'value' ][ 'express_name' ];
if ($title == '') {
$title = Express::express_type[ 'express' ][ 'title' ];
}
$express_type[] = [ 'title' => $title, 'name' => 'express' ];
}
}
// 自提
if ($type == 'store') {
$store_is_pickup = $store_is_pickup ?? 0;
if($store_is_pickup == 1){
//根据坐标查询门店
$store_model = new Store();
$store_condition = array (
[ 'site_id', '=', $site_id ],
[ 'is_pickup', '=', 1 ],
[ 'status', '=', 1 ],
[ 'is_frozen', '=', 0 ],
);
$store_condition[] = ['store_id', '=', $store_id];
$latlng = array (
'lat' => $latitude,
'lng' => $longitude,
);
$store_list = $store_model->getLocationStoreList($store_condition, '*', $latlng)['data'] ?? [];
$title = $order_object->config('store')[ 'value' ][ 'store_name' ];
if ($title == '') {
$title = Express::express_type[ 'store' ][ 'title' ];
}
$express_type[] = [ 'title' => $title, 'name' => 'store', 'store_list' => $store_list ];
}
}
// 外卖
if ($type == 'local') {
$store_is_o2o = $store_is_o2o ?? 0;
if($store_is_o2o == 1){
//查询本店的通讯地址
$title = $order_object->config('local')[ 'value' ][ 'local_name' ];
if ($title == '') {
$title = '外卖配送';
}
$store_model = new Store();
$local_condition = array (
[ 'site_id', '=', $site_id ],
);
// if (addon_is_exit('store', $site_id)) {
$local_condition[] = [ 'is_o2o', '=', 1 ];
$local_condition[] = [ 'status', '=', 1 ];
$local_condition[] = [ 'is_frozen', '=', 0 ];
// } else {
// $store_condition[] = ['is_default', '=', 1];
// }
$local_condition[] = ['store_id', '=', $store_id];
$latlng = array (
'lat' => $latitude,
'lng' => $longitude,
);
$local_store_list = $store_model->getLocationStoreList($local_condition, '*', $latlng)['data'] ?? [];
$express_type[] = [ 'title' => $title, 'name' => 'local', 'store_list' => $local_store_list ];
}
}
}
return $order_model->success($express_type ?? []);
}
break;
case 'trade_calc':
if($store_id > 0 && $store_config['store_business'] == 'store'){
//如果本地配送开启, 则查询出本地配送的配置
$local_model = new Local();
$local_info = $local_model->getLocalInfo([ [ 'site_id', '=', $site_id ], ['store_id', '=', $store_id ] ])['data'] ?? [];
$order_object->delivery[ 'local' ][ 'info' ] = $local_info;
$delivery_array = $order_object->param[ 'delivery' ] ?? [];
$delivery_type = $delivery_array[ 'delivery_type' ] ?? 'express';
if ($delivery_type == 'store') {
//门店自提
$delivery_money = 0;
$order_object->delivery[ 'delivery_type' ] = 'store';
if ($store_is_pickup == 0) {
$error = ['error_msg' => '门店自提方式未开启!'];
}
$order_object->delivery[ 'store_id' ] = $delivery_array[ 'store_id' ] ?? 0;
// $order_object->delivery[ 'buyer_ask_delivery_time' ] = $delivery_array[ 'buyer_ask_delivery_time' ] ?? [];
//同步门店信息
$order_object->storeOrderData();
} else {
if (empty($order_object->delivery[ 'member_address' ])) {
$delivery_money = 0;
$order_object->delivery[ 'delivery_type' ] = 'express';
$error = ['error_msg' => '未配置默认收货地址!'];
} else {
if ($delivery_type == 'express') {
if ($store_is_express == 1) {
//物流配送
$express = new Express();
$express_fee_result = $express->calculate(['order_object' => $order_object]);
if ($express_fee_result[ 'code' ] < 0) {
$error = ['error_msg' => $express_fee_result[ 'message' ]];
$delivery_fee = 0;
} else {
$delivery_fee = $express_fee_result[ 'data' ][ 'delivery_fee' ];
}
} else {
$error = ['error_msg' => '物流配送方式未开启!'];
$delivery_fee = 0;
}
$order_object->delivery_money = $delivery_fee;
$order_object->delivery[ 'delivery_type' ] = 'express';
} else if ($delivery_type == 'local') {
//外卖配送
$delivery_money = 0;
$order_object->delivery[ 'delivery_type' ] = 'local';
if ($store_is_o2o == 0) {
$error = ['error_msg' => '外卖配送方式未开启!'];
} else {
if (empty($delivery_array[ 'store_id' ])) {
$error = ['error_msg' => '门店未选择!'];
}
// $local_delivery_time = $delivery_array[ 'buyer_ask_delivery_time' ] ?? [];
// $order_object->delivery[ 'buyer_ask_delivery_time' ] = $local_delivery_time;
$local_model = new Local();
$local_result = $local_model->calculate(['order_object' => $order_object]);
$order_object->delivery[ 'start_money' ] = 0;
if ($local_result[ 'code' ] < 0) {
$order_object->delivery[ 'start_money' ] = $local_result[ 'data' ][ 'start_money_array' ][ 0 ] ?? 0;
$error = ['error_msg' => $local_result[ 'message' ], 'priority' => 1, 'error' => $local_result[ 'data' ][ 'code' ]];
} else {
$order_object->delivery_money = $local_result[ 'data' ][ 'delivery_money' ];
if (!empty($local_result[ 'data' ][ 'error_code' ])) {
$error = ['error_msg' => $local_result[ 'data' ][ 'error' ], 'priority' => 1, 'error' => $local_result[ 'data' ][ 'error' ]];
}
}
$order_object->delivery[ 'error' ] = $error['error'] ?? 0;
$order_object->delivery[ 'error_msg' ] = $error['error_msg'] ?? '';
}
}
}
}
if(!empty($error)){
$order_object->setError($error['error'] ?? 1, $error['error_msg'] ?? '', $error['priority'] ?? 0);
}
return true;
// return $order_model->success(['shop_goods' => $shop_goods, 'delivery_money' => $delivery_money, 'error' => $error ?? []]);
}
break;
}
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\event;
use addon\cashier\model\order\CashierOrderPay;
/**
* 订单项计算
*/
class OrderGoodsCalculate
{
public function handle($data)
{
/** @var \app\model\order\OrderCreate $order_object */
$order_object = $data['order_object'];
$store_id = $order_object->store_id;
if($store_id > 0){
$site_id = $order_object->site_id;
// $delivery_array = $data[ 'delivery' ] ?? [];
// $delivery_type = $delivery_array[ 'delivery_type' ] ?? 'express';
$store_config_model = new \addon\store\model\Config();
$store_config = $store_config_model->getStoreBusinessConfig($site_id)[ 'data' ][ 'value' ] ?? [];
// if ($store_config[ 'store_business' ] == 'shop' && !in_array($delivery_type, [ 'local', 'store' ])) {
// return null;
// }
//只要是平台运营模式,就不参与商品设置的门店,所在门店的上下架状态
if ($store_config[ 'store_business' ] == 'shop') {
return true;
}
if(!empty($order_object->goods_list)) {
$sku_ids = array_column($order_object->goods_list, 'sku_id');
$store_sku_condition = array(
['sku_id', 'in', $sku_ids],
['store_id', '=', $store_id]
);
$store_sku_column = model('store_goods_sku')->getColumn($store_sku_condition, 'sku_id, price, stock, status', 'sku_id');
foreach ($order_object->goods_list as &$goods_v) {
$sale_store = $goods_v[ 'sale_store' ] ?? '';
if ($sale_store != 'all') {
$sale_store_ids = explode(',', $sale_store);
if (!in_array($store_id, $sale_store_ids)) {
$error = array (
'message' => '当前门店暂不支持销售此项商品'
);
$goods_v[ 'error' ] = $error;
$order_object->setError(1, '存在商品不支持在当前门店销售!');
continue;
}
}
//门店sku信息
$store_sku_info = $store_sku_column[$goods_v['sku_id']] ?? [];
if (!empty($store_sku_info)) {
$is_unify_price = $goods_v[ 'is_unify_price' ];
if ($is_unify_price == 1) {
//表逻辑,无实际意义
} else {
$goods_v[ 'price' ] = $store_sku_info[ 'price' ];
}
$goods_v[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if ($store_sku_info[ 'status' ] != 1) {
$goods_v[ 'error' ] = array (
'message' => '当前门店暂不支持销售此项商品'
);
$order_object->setError(1, '存在商品不支持在当前门店销售!');
}
} else {
$goods_v[ 'error' ] = array (
'message' => '当前门店暂不支持销售此项商品'
);
$order_object->setError(1, '存在商品不支持在当前门店销售!');
}
}
}
}
// $store_id = $data[ 'store_id' ] ?? 0;
// if ($store_id > 0) {
//
//
// $site_id = $data[ 'site_id' ];
// //还需要判断配送方式(平台运营模式如果是 同城 门店自提的话 才有可能传入store_id)
// $delivery_array = $data[ 'delivery' ] ?? [];
// $delivery_type = $delivery_array[ 'delivery_type' ] ?? 'express';
// $store_config_model = new \addon\store\model\Config();
// $store_config = $store_config_model->getStoreBusinessConfig($site_id)[ 'data' ][ 'value' ] ?? [];
// if ($store_config[ 'store_business' ] == 'shop' && !in_array($delivery_type, [ 'local', 'store' ])) {
// return null;
// }
//
// $goods_id = $data[ 'goods_id' ];
// $goods_info = model('goods')->getInfo([ [ 'goods_id', '=', $goods_id ] ], 'sale_store');
// $sale_store = $goods_info[ 'sale_store' ] ?? '';
//
// if ($sale_store != 'all') {
// $sale_store_ids = explode(',', $sale_store);
// if (!in_array($store_id, $sale_store_ids)) {
// $error = array (
//// 'code' => '',//暂无映射关系
// 'message' => '当前门店暂不支持销售此项商品'
// );
// $data[ 'error' ] = $error;
// return ( new CashierOrderPay() )->success($data);
// }
// }
//
// $sku_id = $data[ 'sku_id' ];
// $store_sku_condition = array (
// [ 'sku_id', '=', $sku_id ],
// [ 'store_id', '=', $store_id ]
// );
// $store_sku_info = model('store_goods_sku')->getInfo($store_sku_condition);
// if (!empty($store_sku_info)) {
// $is_unify_price = $data[ 'is_unify_price' ];
// if ($is_unify_price == 1) {
// //表逻辑,无实际意义
// } else {
// $data[ 'price' ] = $store_sku_info[ 'price' ];
// }
// $data[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
//
// if ($store_sku_info[ 'status' ] != 1) {
// $error = array (
//// 'code' => '',//暂无映射关系
// 'message' => '当前门店暂不支持销售此项商品'
// );
// }
// } else {
// $error = array (
//// 'code' => '',//暂无映射关系
// 'message' => '当前门店暂不支持销售此项商品'
// );
// }
//
//
// if (!empty($error)) {
// $data[ 'error' ] = $error;
// }
// return ( new CashierOrderPay() )->success($data);
// }
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreOrder;
/**
* 添加下单用户为门店用户(todo 为兼容已存在但未完成的旧数据先保留)
*/
class OrderPayAfter
{
public function handle($order)
{
$store_order = new StoreOrder();
$res = $store_order->orderPay($order);
return $res;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\StoreMember as StoreMemberModel;
/**
* 积分兑换订单创建之后
*/
class PointExchangeOrderCreate
{
// 行为扩展的执行入口必须是run
public function handle($data)
{
$order_data = $data['create_data'];
$delivery_store_id = $order_data['delivery'][ 'delivery_store_id' ] ?? 0;
if ($delivery_store_id > 0) {
//添加店铺关注记录
$shop_member_model = new StoreMemberModel();
$res = $shop_member_model->addStoreMember($delivery_store_id, $order_data[ 'member_id' ]);
if ($res[ "code" ] < 0) {
return $res;
}
return true;
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\event;
/**
* 活动展示
*/
class ShowPromotion
{
/**
* 活动展示
* @return array
*/
public function handle()
{
$data = [
'shop' => [
[
//插件名称
'name' => 'store',
//店铺端展示分类 shop:营销活动 member:互动营销
'show_type' => 'tool',
//展示主题
'title' => '门店管理',
//展示介绍
'description' => '门店管理功能',
//展示图标
'icon' => 'addon/store/icon.png',
//跳转链接
'url' => 'store://shop/store/lists',
]
]
];
return $data;
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\settlement\OrderSettlement;
/**
* 门店分成结算
*/
class StoreOrderRefundSettlementCalculate
{
public function handle($data)
{
$order_settlement_model = new OrderSettlement();
$order_settlement_model->orderRefundSettlementAccount($data);
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\settlement\OrderSettlement;
/**
* 门店分成结算
*/
class StoreOrderSettlementCalculate
{
public function handle($data)
{
$order_settlement_model = new OrderSettlement();
$order_settlement_model->orderSettlementAccount($data);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\Settlement;
use Carbon\Carbon;
/**
* 门店结算
*/
class StoreWithdrawPeriodCalc
{
public function handle($params)
{
$model = new Settlement();
$time = Carbon::today()->timestamp;
$res = $model->settlement($params[ 'relate_id' ], $time);
return $res;
}
}

30
addon/store/event/UnInstall.php Executable file
View File

@@ -0,0 +1,30 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
use addon\store\model\Menu;
/**
* 应用卸载
*/
class UnInstall
{
/**
* 执行卸载
*/
public function handle()
{
$menu = new Menu();
$res = $menu->uninstall();
return $res;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
/**
* 提现通知
*/
class WithdrawTransferCheck
{
public function handle($param)
{
if($param['from_type'] == 'store_withdraw'){
$model = new \addon\store\model\StoreWithdraw();
return $model->transferCheck($param['relate_tag']);
}
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\event;
/**
* 提现通知
*/
class WithdrawTransferNotify
{
public function handle($param)
{
if($param['from_type'] == 'store_withdraw'){
$model = new \addon\store\model\StoreWithdraw();
return $model->transferNotify($param);
}
}
}

BIN
addon/store/icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

141
addon/store/model/Category.php Executable file
View File

@@ -0,0 +1,141 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use think\facade\Cache;
use app\model\BaseModel;
use app\model\system\Config;
/**
* 门店分类
*/
class Category extends BaseModel
{
/**
* 门店分类设置
* @param $data
* @param $site_id
* @return array
*/
public function setCategoryConfig($data, $site_id)
{
return ( new Config() )->setConfig($data, '门店分类设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STORE_CATEGORY' ] ]);
}
/**
* 获取门店分类设置
* @param $site_id
* @return array
*/
public function getCategoryConfig($site_id)
{
$data = ( new Config() )->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STORE_CATEGORY' ] ]);
if (empty($data[ 'data' ][ 'value' ])) {
$data[ 'data' ][ 'value' ] = [
'status' => 0
];
}
return $data;
}
/**
* 添加门店分类
*
* @param array $data
*/
public function addStoreCategory($data)
{
$res = model('store_category')->add($data);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 修改门店分类
*
* @param array $data
* @param array $condition
*/
public function editStoreCategory($data, $condition)
{
$check_condition = array_column($condition, 2, 0);
$category_id = $check_condition['category_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($category_id)) return $this->error('', 'category_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_category')->update($data, $condition);
if (isset($data[ 'category_name' ]) && !empty($data[ 'category_name' ])) model('store')->update([ 'category_name' => $data[ 'category_name' ] ], [ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 删除门店分类
* @param array $condition
*/
public function deleteStoreCategory($condition)
{
$check_condition = array_column($condition, 2, 0);
$category_id = isset($check_condition[ 'category_id' ]) ? array_filter(explode(',', $check_condition[ 'category_id' ])) : [];
$site_id = $check_condition['site_id'] ?? 0;
if (empty($category_id)) return $this->error('', 'category_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_category')->delete($condition);
model('store')->update([ 'category_name' => '', 'category_id' => '' ], [ [ 'category_id', 'in', $category_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 获取门店分类信息
*
* @param array $condition
* @param string $field
*/
public function getStoreCategoryInfo($condition = [], $field = '*')
{
$info = model('store_category')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取门店分类列表
*
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreCategoryList($condition = [], $field = '*', $order = 'sort asc, category_id asc', $limit = null)
{
$list = model('store_category')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取门店分类分页列表
*
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getStoreCategoryPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'category_id desc', $field = '*')
{
$list = model('store_category')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

150
addon/store/model/Config.php Executable file
View File

@@ -0,0 +1,150 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\order\OrderCommon as OrderCommonModel;
use app\model\system\Config as ConfigModel;
use app\model\BaseModel;
use Carbon\Carbon;
use app\model\system\Cron;
/**
* 店铺设置信息
*/
class Config extends BaseModel
{
/**
* 门店结算相关设置
* @param $site_id
* @return array
*/
public function getStoreWithdrawConfig($site_id)
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
//数据格式化
if (addon_is_exit('cashier') == 1) {
$order_common_model = new OrderCommonModel();
$pay_type = $order_common_model->getPayType([ 'order_type' => 5 ]);
} else {
$pay_type = [];
}
$data = [
//是否进行门店结算
'is_settlement' => $res[ 'data' ][ 'value' ][ 'is_settlement' ] ?? 0,
//结算周期 1 按天 2. 按周 3. 按月 4. 立即结算
'period_type' => $res[ 'data' ][ 'value' ][ 'period_type' ] ?? 4,
//结算比率
'settlement_rate' => $res[ 'data' ][ 'value' ][ 'settlement_rate' ] ?? 0,
// 结算付款控制
'settlement_pay_type' => $res[ 'data' ][ 'value' ][ 'settlement_pay_type' ] ?? implode(',', array_keys($pay_type)),
//结算成本控制 cuppon,point,balance,fenxiao_commission
'settlement_cost' => $res[ 'data' ][ 'value' ][ 'settlement_cost' ] ?? '',//'cuppon,point,balance,fenxiao_commission'
//是否允许提现
'is_withdraw' => $res[ 'data' ][ 'value' ][ 'is_withdraw' ] ?? 0,
//是否提现审核
'is_audit' => $res[ 'data' ][ 'value' ][ 'is_audit' ] ?? 0,
//是否自动转账
'is_auto_transfer' => $res[ 'data' ][ 'value' ][ 'is_auto_transfer' ] ?? 0,
//可提现账户类型 wechatalipay bank
'withdraw_type' => $res[ 'data' ][ 'value' ][ 'withdraw_type' ] ?? '',
'withdraw_least' => $res[ 'data' ][ 'value' ][ 'withdraw_least' ] ?? 0, // 提现最低金额
];
$res[ 'data' ][ 'value' ] = $data;
return $res;
}
/**
* 门店结算相关设置
*/
public function setStoreWithdrawConfig($site_id, $data)
{
$config = new ConfigModel();
$res = $config->setConfig($data, '门店结算设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
$cron = new Cron();
$execute_time = 0;
switch ( $data[ 'period_type' ] ) {
case 1://
$date = strtotime(date('Y-m-d 00:00:00'));
$execute_time = strtotime('+1day', $date);
break;
case 2://
$execute_time = Carbon::parse('next monday')->timestamp;
break;
case 3://
$execute_time = Carbon::now()->addMonth()->firstOfMonth()->timestamp;
break;
}
if ($execute_time > 0) {
$cron->deleteCron([ [ 'event', '=', 'StoreWithdrawPeriodCalc' ], [ 'relate_id', '=', $site_id ] ]);
$cron->addCron('2', '1', '门店周期结算', 'StoreWithdrawPeriodCalc', $execute_time, $site_id, $data[ 'period_type' ]);
}
return $res;
}
/**
* 获取门店运营相关设置
* @param $site_id
*/
public function getStoreBusinessConfig($site_id)
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_BUSINESS' ] ]);
//数据格式化
$data = [
//门店运营模式 shop店铺整体运营 store连锁门店运营模式
'store_business' => $res[ 'data' ][ 'value' ][ 'store_business' ] ?? 'shop',
//是否允许切换门店
'is_allow_change' => $res[ 'data' ][ 'value' ][ 'is_allow_change' ] ?? 1,
'confirm_popup_control' => $res[ 'data' ][ 'value' ][ 'confirm_popup_control' ] ?? 1, // 门店确认弹窗
//门店控制权限
'store_auth' => $res[ 'data' ][ 'value' ][ 'store_auth' ] ?? '',//'config,balance,point,coupon,adjust'
];
$res[ 'data' ][ 'value' ] = $data;
return $res;
}
/**
* 门店结算相关设置
*/
public function setStoreBusinessConfig($site_id, $data)
{
$config = new ConfigModel();
$res = $config->setConfig($data, '门店功能设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_BUSINESS' ] ]);
return $res;
}
/**
* addSettlementCron 添加门店结算计划任务 默认为3 - 月
*/
public function addSettlementCron($site_id)
{
$config = new ConfigModel();
$config->setConfig([ 'period_type' => 3 ], '门店结算设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
$cron = new Cron();
$execute_time = Carbon::now()->addMonth()->firstOfMonth()->timestamp;
$cron->deleteCron([ [ 'event', '=', 'StoreWithdrawPeriodCalc' ], [ 'relate_id', '=', $site_id ] ]);
$res = $cron->addCron('2', '1', '门店周期结算', 'StoreWithdrawPeriodCalc', $execute_time, $site_id, 3);
return $this->success($res);
}
}

145
addon/store/model/Label.php Executable file
View File

@@ -0,0 +1,145 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use think\facade\Db;
use think\facade\Cache;
use app\model\BaseModel;
/**
* 门店标签
*/
class Label extends BaseModel
{
/**
* 添加门店标签
*
* @param array $data
*/
public function addStoreLabel($data)
{
$count = model('store_label')->getCount([ [ 'label_name', '=', $data[ 'label_name' ] ], [ 'site_id', '=', $data[ 'site_id' ] ] ]);
if ($count) return $this->error('', '该标签名称已存在');
$res = model('store_label')->add($data);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 修改门店标签
*
* @param array $data
* @param array $condition
*/
public function editStoreLabel($data, $condition)
{
$check_condition = array_column($condition, 2, 0);
$label_id = $check_condition['label_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($label_id)) return $this->error('', 'label_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$count = model('store_label')->getCount([ [ 'label_id', '<>', $label_id ], [ 'label_name', '=', $data[ 'label_name' ] ], [ 'site_id', '=', $site_id ] ]);
if ($count) return $this->error('', '该标签名称已存在');
$old_label_name = model('store_label')->getValue($condition, 'label_name');
$res = model('store_label')->update($data, $condition);
model('store')->update([ 'label_name' => Db::raw("REPLACE(label_name, ',{$old_label_name},', ',{$data['label_name']},')") ], [ [ 'site_id', '=', $site_id ], [ 'label_id', 'like', "%,$label_id,%" ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 修改排序
* @param $sort
* @param $label_id
* @param $site_id
* @return array
*/
public function modifySort($sort, $label_id, $site_id)
{
$site_id = $site_id ?? '';
if ($site_id === '') {
return $this->error('', 'REQUEST_SITE_ID');
}
$res = model('store_label')->update([ 'sort' => $sort ], [ [ 'label_id', '=', $label_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 删除门店标签
* @param $condition
* @return array
*/
public function deleteStoreLabel($condition)
{
$check_condition = array_column($condition, 2, 0);
$label_id = $check_condition['label_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($label_id)) return $this->error('', 'label_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_label')->delete($condition);
$old_label_name = model('store_label')->getValue($condition, 'label_name');
model('store')->update([ 'label_name' => Db::raw("REPLACE(label_name, ',{$old_label_name},', '')") ], [ [ 'site_id', '=', $site_id ], [ 'label_id', 'like', "%,$label_id,%" ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 获取门店标签信息
* @param array $condition
* @param string $field
* @return array
*/
public function getStoreLabelInfo($condition = [], $field = '*')
{
$info = model('store_label')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取门店标签列表
*
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreLabelList($condition = [], $field = '*', $order = 'sort asc,label_id desc', $limit = null)
{
$list = model('store_label')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取门店标签分页列表
*
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getStoreLabelPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'sort asc,label_id desc', $field = '*')
{
$list = model('store_label')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

27
addon/store/model/Menu.php Executable file
View File

@@ -0,0 +1,27 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
/**
* 菜单管理
* @author Administrator
*
*/
class Menu extends BaseModel
{
public function uninstall()
{
$res = model("menu")->delete([ [ 'app_module', '=', 'store' ] ]);
return $this->success($res);
}
}

233
addon/store/model/Settlement.php Executable file
View File

@@ -0,0 +1,233 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\dict\order\OrderPayDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
/**
* 门店订单与结算
*/
class Settlement extends BaseModel
{
/**
* 店铺门店结算
* @param $site_id
* @param $end_time
* @return array
*/
public function settlement($site_id, $end_time)
{
//获取最近的店铺结算时间
$last_time = model('shop')->getInfo([ [ 'site_id', '=', $site_id ] ], 'store_settlement_time');
$start_time = $last_time[ 'store_settlement_time' ];
//查询门店结算配置
$config_model = new Config();
$config = $config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
if ($config[ 'is_settlement' ] != 1) {
return $this->success();
}
$period_type = $config[ 'period_type' ];
//结算周期为4的话是立即结算
if ($period_type == 4)
return $this->success();
$period_type = array ( 1 => 'day', 2 => 'week', 3 => 'month' )[ $period_type ] ?? 'day';
//只有开启周期性结算开关,才会进行
if (( $end_time - $start_time ) < ( 3600 * 20 )) {
return $this->success();
}
//店铺列表
$store_list = model('store')->getList([ [ 'site_id', '=', $site_id ] ], 'site_name, store_id, store_name, account');
model('store_settlement')->startTrans();
try {
$store_withdraw_model = new StoreWithdraw();
//循环各个店铺数据
foreach ($store_list as $store) {
$store_id = $store[ 'store_id' ];
//周期性结算会将所有抽成全部提现
$store_commission = $store[ 'account' ];
$withdraw_id = 0;
if ($store_commission > 0) {
$apply_params = array (
'site_id' => $site_id,
'store_id' => $store_id,
'money' => $store_commission,
'settlement_type' => $period_type
);
$withdraw_result = $store_withdraw_model->apply($apply_params);
$withdraw_id = $withdraw_result[ 'data' ];
}
$this->addSettlement([
'site_id' => $site_id,
'store_id' => $store_id,
'start_time' => $start_time,
'end_time' => $end_time,
'store_commission' => $store_commission,
'withdraw_id' => $withdraw_id,
])['data'];
}
model('shop')->update([ 'store_settlement_time' => $end_time ], [ [ 'site_id', '=', $site_id ] ]);
model('store_settlement')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_settlement')->rollback();
return $this->error($e->getMessage());
}
}
/**
* 添加结算
* @param $param
* @return array
*/
public function addSettlement($param)
{
$site_id = $param['site_id'];
$store_id = $param['store_id'];
$start_time = $param['start_time'];
$end_time = $param['end_time'];
$store_commission = $param['store_commission'];
$withdraw_id = $param['withdraw_id'];
$store_info = model('store')->getInfo([['store_id', '=', $store_id]], 'store_name,site_name');
$online_settlement = model('order')->getInfo([
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
[ 'pay_type', '<>', OrderPayDict::offline_pay ],//todo 支付方式应该都可以
], 'sum(pay_money) as order_money, sum(refund_money) as refund_money, sum(commission) as commission');
$offline_settlement = model('order')->getInfo([
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
[ 'pay_type', '=', 'offlinepay' ],
], 'sum(pay_money) as offline_order_money, sum(refund_money) as offline_refund_money');
$settlement = [
'settlement_no' => date('YmdHi') . $store_id . rand(1111, 9999),
'site_id' => $site_id,
'site_name' => $store_info[ 'site_name' ],
'store_id' => $store_id,
'store_name' => $store_info[ 'store_name' ],
'order_money' => $online_settlement[ 'order_money' ] ?? 0,
'refund_money' => $online_settlement[ 'refund_money' ] ?? 0,
'commission' => $online_settlement[ 'commission' ] ?? 0,
'offline_order_money' => $offline_settlement[ 'offline_order_money' ] ?? 0,
'offline_refund_money' => $offline_settlement[ 'offline_refund_money' ] ?? 0,
'create_time' => $end_time,
'start_time' => $start_time,
'end_time' => $end_time,
'store_commission' => $store_commission,
'withdraw_id' => $withdraw_id,
];
$store_settlement_id = model('store_settlement')->add($settlement);
model('order')->update([ 'store_settlement_id' => $store_settlement_id, 'is_settlement' => 1 ], [
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
]);
return $this->success($store_settlement_id);
}
/**
* 获取详情
* @param $condition
* @param string $fields
* @return array
*/
public function getSettlementInfo($condition, $fields = '*')
{
$res = model('store_settlement')->getInfo($condition, $fields);
return $this->success($res);
}
/**
* 修改结算记录
* @param $data
* @param $condition
* @return array
*/
public function editSettlement($data, $condition)
{
$res = model('store_settlement')->update($data, $condition);
return $this->success($res);
}
/**
* 获取店铺待结算订单金额
* @param array $condition
* @return array|mixed
*/
public function getStoreSettlementData($condition = [])
{
$money_info = model('order')->getInfo($condition, 'sum(order_money) as order_money, sum(refund_money) as refund_money, sum(shop_money) as shop_money, sum(platform_money) as platform_money, sum(refund_shop_money) as refund_shop_money, sum(refund_platform_money) as refund_platform_money, sum(commission) as commission');
if (empty($money_info) || $money_info == null) {
$money_info = [
'order_money' => 0,
'refund_money' => 0,
'shop_money' => 0,
'platform_money' => 0,
'refund_shop_money' => 0,
'refund_platform_money' => 0,
'commission' => 0
];
}
return $money_info;
}
/**
* 获取店铺结算周期结算分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreSettlementPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$list = model('store_settlement')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
/**
* 拒绝提现后的处理
* @param $withdraw_id
* @return array
*/
public function refuseWithdraw($withdraw_id)
{
$settlement_info = model('store_settlement')->getInfo([['withdraw_id', '=', $withdraw_id]]);
if(!empty($settlement_info)){
$store_settlement_id = $settlement_info['id'];
model('order')->update(['is_settlement' => 0, 'store_settlement_id' => 0], [['store_settlement_id', '=', $store_settlement_id]]);
}
return $this->success();
}
}

51
addon/store/model/Stat.php Executable file
View File

@@ -0,0 +1,51 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
/**
* 门店订单与结算
*/
class Stat extends BaseModel
{
/**
* 统计
* @param $params
*/
public function getStoreAccountSum($condition, $field)
{
$sum = model('store')->getSum($condition, $field);
return $this->success($sum);
}
/**
* 门店订单的销售额和销售量排行
* @param $params
*/
public function getStoreOrderRank($params)
{
$site_id = $params[ 'site_id' ];
$join = [
[ 'order o', '(o.store_id = s.store_id and o.pay_status = 1 and o.is_delete = 0) || o.store_id is null ', 'left' ]
];
$group = 's.store_id';
$limit = 5;
$order = $params[ 'order' ] == 'num' ? 'order_num desc' : 'order_money desc';
$field = 'ifnull(count(o.order_id), 0) as order_num, ifnull(sum(o.order_money), 0) as order_money,s.store_name';
$condition = array (
[ 's.site_id', '=', $site_id ],
);
$list = model('store')->getList($condition, $field, $order, 's', $join, $group, $limit);
return $this->success($list);
}
}

View File

@@ -0,0 +1,304 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\system\Export as ExportModel;
use think\facade\Db;
class StoreAccount extends BaseModel
{
public $period_types = [ 1, 2, 3 ];//转账周期类型1.天 2. 周 3. 月
public $from_type = [
'order' => [
'type_name' => '订单结算',
'type_url' => '',
],
'refund' => [
'type_name' => '订单退款',
'type_url' => '',
],
'withdraw' => [
'type_name' => '门店提现',
'type_url' => '',
],
];
/**
* 获取门店转账设置
*/
public function getStoreWithdrawConfig($site_id)
{
$config = new Config();
$res = $config->getStoreWithdrawConfig($site_id);
return $res;
}
/**
* 获取门店待结算订单金额
*/
public function getWaitSettlementInfo($store_id)
{
$money_info = model('order')->getInfo([
[ 'store_id', '=', $store_id ],
[ 'order_status', '=', 10 ],
[ 'store_settlement_id', '=', 0 ]
], 'sum(order_money) as order_money, sum(refund_money) as refund_money, sum(shop_money) as shop_money, sum(platform_money) as platform_money, sum(refund_shop_money) as refund_shop_money, sum(refund_platform_money) as refund_platform_money, sum(commission) as commission');
if (empty($money_info) || $money_info == null) {
$money_info = [
'order_money' => 0,
'refund_money' => 0,
'shop_money' => 0,
'platform_money' => 0,
'refund_shop_money' => 0,
'refund_platform_money' => 0,
'commission' => 0
];
}
return $money_info;
}
/**
* 门店账户记录操作
* @param $params
*/
public function addStoreAccount($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ];
$account_data = $params[ 'account_data' ];
$remark = $params[ 'remark' ];
$from_type = $params[ 'from_type' ];
$related_id = $params[ 'related_id' ];
$is_limit = $params[ 'is_limit' ] ?? 1;//是否限制不能小于0
model('store_account')->startTrans();
try {
//账户检测
$store_account = Db::name('store')->where([
[ 'store_id', '=', $store_id ],
[ 'site_id', '=', $site_id ]
])->field('account')->lock(true)->find();
$account_new_data = round((float) $store_account[ 'account' ] + (float) $account_data, 2);
if ($is_limit == 1 && (float) $account_new_data < 0) {
model('store_account')->rollback();
$msg = '账户余额不足';
return $this->error('', $msg);
}
//添加记录
$type_info = $this->from_type[ $from_type ];
$data = array (
'site_id' => $site_id,
'store_id' => $store_id,
'account_data' => $account_data,
'from_type' => $from_type,
'type_name' => $type_info[ 'type_name' ],
'create_time' => time(),
'remark' => $remark,
'related_id' => $related_id,
);
model('store_account')->add($data);
//账户更新
model('store')->update([
'account' => $account_new_data
], [
[ 'store_id', '=', $store_id ]
]);
model('store_account')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_account')->rollback();
return $this->error('', $e->getMessage());
}
}
public function getStoreAccountInfo($condition, $field = '*', $alias = 'a', $join = [])
{
$info = model('store_account')->getInfo($condition, $field, $alias, $join);
return $this->success($info);
}
/**
* 获取账户分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array|\multitype
*/
public function getStoreAccountPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'create_time desc,id desc', $field = '*', $alias = 'a', $join = [])
{
$list = model('store_account')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取账户列表
* @param array $condition
* @param string $field
* @param string $order
* @param null $limit
* @return array|\multitype
*/
public function getStoreAccountList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_account')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 添加门店账户导出
* @param $input
* @return array
*/
public function addStoreAccountExport($input, $export_store_id = 0)
{
$remark = $input['remark'] ?? '';
$start_date = $input['start_date'] ?? '';
$end_date = $input['end_date'] ?? '';
$from_type = $input['from_type'] ?? '';
$store_id = $input['store_id'] ?? 0;
$site_id = $input['site_id'];
$account_model = new StoreAccount();
$store_model = new \app\model\store\Store();
//组装条件和条件说明
$condition = [ [ 'sa.site_id', '=', $site_id ] ];
$condition_desc = [];
if (!empty($remark)) {
$condition[] = [ 'sa.remark', 'like', '%' . $remark . '%' ];
$condition_desc[] = ['name' => '备注信息', 'value' => $remark];
}
if (!empty($from_type)) {
$condition[] = [ 'sa.from_type', '=', $from_type ];
$from_type_list = $account_model->from_type;
$condition_desc[] = ['name' => '来源类型', 'value' => $from_type_list[$from_type]['type_name']];
}
if ($store_id > 0) {
$condition[] = [ 'sa.store_id', '=', $store_id ];
$store_info = $store_model->getStoreInfo([['store_id', '=', $store_id]], 'store_name')['data'];
$condition_desc[] = ['name' => '门店名称', 'value' => $store_info['store_name']];
}
$time_name = '';
if (!empty($start_date) && empty($end_date)) {
$condition[] = [ 'sa.create_time', '>=', date_to_time($start_date) ];
$time_name = $start_date . '起';
} elseif (empty($start_date) && !empty($end_date)) {
$condition[] = [ 'sa.create_time', '<=', date_to_time($end_date) ];
$time_name = '至' . $end_date;
} elseif (!empty($start_date) && !empty($end_date)) {
$condition[] = [ 'sa.create_time', 'between', [ date_to_time($start_date), date_to_time($end_date) ] ];
$time_name = $start_date . ' 至 ' . $end_date;
}
if($time_name) $condition_desc[] = [ 'name' => '发生时间', 'value' => $time_name ];
$param = [
'site_id' => $site_id,
'store_id' => $export_store_id,
'from_type' => 'store_account',
'from_type_name' => '门店账户',
'condition_desc' => $condition_desc,
'query' => [
'table' => 'store_account',
'alias' => 'sa',
'join' => [
['store s', 'sa.store_id = s.store_id', 'inner'],
],
'condition' => $condition,
'field' => 'sa.*,s.store_name',
'chunk_field' => 'sa.id',
'chunk_order' => 'asc',
],
'export_field' => [
['field' => 'store_name', 'name' => '门店名称'],
['field' => 'type_name', 'name' => '来源方式'],
['field' => 'account_data', 'name' => '记录金额'],
['field' => 'create_time', 'name' => '发生时间'],
['field' => 'remark', 'name' => '备注'],
['field' => 'related_no', 'name' => '关联编号'],
],
'handle' => function($item_list){
foreach($item_list as &$item){
$item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
}
return $this->getRelatedInfo($item_list);
},
];
$export_model = new ExportModel();
return $export_model->export($param);
}
/**
* 获取关联单号
* @param $item_list
* @return mixed
*/
public function getRelatedInfo($item_list)
{
$order_ids = $refund_ids = $withdraw_ids = [];
$order_list = $refund_list = $withdraw_list = [];
foreach($item_list as $item){
switch($item['from_type']){
case 'order':
$order_ids[] = $item['related_id'];
break;
case 'refund':
$refund_ids[] = $item['related_id'];
break;
case 'withdraw':
$withdraw_ids[] = $item['related_id'];
break;
}
}
if(!empty($order_ids)){
$order_list = model('order')->getList([['order_id', 'in', $order_ids]], 'order_id,order_no,order_from');
$order_list = array_column($order_list, null, 'order_id');
}
if(!empty($refund_ids)){
$alias = 'og';
$join = [
['order o', 'o.order_id = og.order_id', 'inner'],
];
$field = 'og.order_goods_id,og.refund_no,o.order_id,o.order_no,o.order_from';
$refund_list = model('order_goods')->getList([['og.order_goods_id', 'in', $refund_ids]], $field, '', $alias, $join);
$refund_list = array_column($refund_list, null, 'order_goods_id');
}
if(!empty($withdraw_ids)){
$withdraw_list = model('store_withdraw')->getList([['withdraw_id', 'in', $withdraw_ids]], 'withdraw_id,withdraw_no');
$withdraw_list = array_column($withdraw_list, null, 'withdraw_id');
}
foreach($item_list as &$item){
switch($item['from_type']){
case 'order':
$item['related_no'] = $order_list[$item['related_id']]['order_no'] ?? '';
$item['related_info'] = $order_list[$item['related_id']] ?? null;
break;
case 'refund':
$item['related_no'] = $refund_list[$item['related_id']]['refund_no'] ?? '';
$item['related_info'] = $refund_list[$item['related_id']] ?? null;
break;
case 'withdraw':
$item['related_no'] = $withdraw_list[$item['related_id']]['withdraw_no'] ?? '';
$item['related_info'] = $withdraw_list[$item['related_id']] ?? null;
break;
}
}
return $item_list;
}
}

100
addon/store/model/StoreGoods.php Executable file
View File

@@ -0,0 +1,100 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
class StoreGoods extends BaseModel
{
/**
* 商品编辑之后
*/
public function goodsEditAfter($goods_id, $site_id)
{
// $store_list = model('store')->getList([ [ 'site_id', '=', $site_id ] ], 'store_id');
// if (!empty($store_list)) {
// $goods_sku = model('goods_sku')->getColumn([ [ 'goods_id', '=', $goods_id ] ], 'sku_id');
// model('store_goods_sku')->startTrans();
// try {
// foreach ($store_list as $v) {
// $store_id = $v[ 'store_id' ];
// $store_goods_sku = model('store_goods_sku')->getColumn([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ], 'sku_id');
// if (!empty($store_goods_sku)) {
//
// model('store_goods_sku')->delete([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ], [ 'sku_id', 'not in', $goods_sku ] ]);
// $stock = model('store_goods_sku')->getSum([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ], 'stock');
// model('store_goods')->update([ 'stock' => $stock ], [ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ]);
// }
// }
//
// model('store_goods_sku')->commit();
return $this->success();
// } catch (\Exception $e) {
// model('store_goods_sku')->rollback();
// return $this->error('', $e->getMessage());
// }
// }
}
/**
* 门店详情
* @param $condition
* @param string $fields
* @return array
*/
public function getStoreGoodsInfo($condition, $fields = '*')
{
$info = model('store_goods')->getInfo($condition, $fields);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'sale_num' ])) {
$info[ 'sale_num' ] = numberFormat($info[ 'sale_num' ]);
}
if (isset($info[ 'real_stock' ])) {
$info[ 'real_stock' ] = numberFormat($info[ 'real_stock' ]);
}
}
return $this->success($info);
}
/**
* 获取门店商品列表
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreGoodsList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_goods')->getList($condition, $field, $order, '', '', '', $limit);
foreach ($list as &$v) {
$v[ 'store_goods_skus' ] = model('store_goods_sku')->getList([
[ 'store_id', '=', $v[ 'store_id' ] ],
[ 'goods_id', '=', $v[ 'goods_id' ] ]
], 'sku_id,goods_id,stock,sale_num');
if (isset($v[ 'stock' ])) {
$v[ 'stock' ] = numberFormat($v[ 'stock' ]);
}
if (isset($v[ 'sale_num' ])) {
$v[ 'sale_num' ] = numberFormat($v[ 'sale_num' ]);
}
if (isset($v[ 'real_stock' ])) {
$v[ 'real_stock' ] = numberFormat($v[ 'real_stock' ]);
}
}
return $this->success($list);
}
}

View File

@@ -0,0 +1,315 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\goods\Goods;
class StoreGoodsSku extends BaseModel
{
/**
* 添加店铺sku
* @param $data
* @return array
*/
public function addStoreGoodsSku($data)
{
$res = model('store_goods_sku')->add($data);
//判断当前有没有store_goods
$store_goods_info = model('store_goods')->getInfo([ [ 'goods_id', '=', $data[ 'goods_id' ] ], [ 'store_id', '=', $data[ 'store_id' ] ] ], 'id');
if (empty($store_goods_info)) {
$store_goods_data = [
'goods_id' => $data[ 'goods_id' ],
'store_id' => $data[ 'store_id' ],
'create_time' => time(),
];
model('store_goods')->add($store_goods_data);
}
return $this->success($res);
}
/**
* 获取门店商品sku详情
* @param $condition
* @param string $field
* @return array
*/
public function getStoreGoodsSkuInfo($condition, $field = '*')
{
$res = model('store_goods_sku')->getInfo($condition, $field);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'sale_num' ])) {
$info[ 'sale_num' ] = numberFormat($info[ 'sale_num' ]);
}
if (isset($info[ 'real_stock' ])) {
$info[ 'real_stock' ] = numberFormat($info[ 'real_stock' ]);
}
}
return $this->success($res);
}
/**
* 增加库存
* @param param
*/
public function incStock($param)
{
$condition = array (
[ 'store_id', '=', $param[ 'store_id' ] ],
[ 'sku_id', '=', $param[ 'sku_id' ] ]
);
$num = $param[ 'stock' ];
$store_sku_info = model('store_goods_sku')->getInfo($condition, 'id, goods_id');
if (empty($store_sku_info))
return $this->error(-1, "");
//编辑sku库存
$result = model('store_goods_sku')->setInc($condition, 'stock', $num);
model('store_goods')->setInc([ [ 'goods_id', '=', $store_sku_info[ 'goods_id' ] ], [ 'store_id', '=', $param[ 'store_id' ] ] ], 'stock', $num);
return $this->success($result);
}
/**
* 减少库存
* @param $param
* @return array
*/
public function decStock($param)
{
$condition = array (
[ 'store_id', '=', $param[ 'store_id' ] ],
[ 'sku_id', '=', $param[ 'sku_id' ] ]
);
$num = $param[ 'stock' ];
$store_sku_info = model('store_goods_sku')->getInfo($condition, 'id, goods_id, stock');
if (empty($store_sku_info)) {
return $this->error(-1, '库存不足!');
}
$store_sku_info[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if (( $store_sku_info[ 'stock' ] - $num ) < 0) {
return $this->error(-1, '库存不足!');
}
//编辑sku库存
$result = model('store_goods_sku')->setDec($condition, 'stock', $num);
model('store_goods')->setDec([ [ 'goods_id', '=', $store_sku_info[ 'goods_id' ] ], [ 'store_id', '=', $param[ 'store_id' ] ] ], 'stock', $num);
return $this->success($result);
}
/**
* 编辑门店商品库存信息
* @param $goods_sku_array
*/
public function editStock($store_goods_sku_array)
{
model('store_goods_sku')->startTrans();
try {
foreach ($store_goods_sku_array as $item) {
$sku_info_result = $this->getStoreGoodsSkuInfo([ [ "store_id", "=", $item[ "store_id" ] ], [ "sku_id", "=", $item[ "sku_id" ] ] ], "sku_id");
$sku_info = $sku_info_result[ "data" ];
if (empty($sku_info)) {
$sku_data = array (
"goods_id" => $item[ "goods_id" ],
"sku_id" => $item[ "sku_id" ],
"store_id" => $item[ "store_id" ],
);
$this->addStoreGoodsSku($sku_data);
}
if ($item[ 'stock' ] > 0) {
$item_result = $this->incStock($item);
} else {
$item[ 'stock' ] = abs($item[ 'stock' ]);
$item_result = $this->decStock($item);
}
if ($item_result[ "code" ] < 0) {
model('store_goods_sku')->rollback();
return $item_result;
}
}
model('store_goods_sku')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_goods_sku')->rollback();
return $this->error($e->getMessage());
}
}
/**
* 门店库存批量修改导入excel
* @param $param
* @param $site_id
* @return array
*/
public function importStoreGoodsStock($param, $site_id, $store_id)
{
$PHPReader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
//载入文件
$PHPExcel = $PHPReader->load($param[ 'path' ]);
//获取表中的第一个工作表如果要获取第二个把0改为1依次类推
$currentSheet = $PHPExcel->getSheet(0);
//获取总行数
$allRow = $currentSheet->getHighestRow();
if ($allRow < 2) {
return $this->error('', '导入了一个空文件');
}
//添加文件上传记录
$error_num = 0;
$data = [
'site_id' => $site_id,
'store_id' => $store_id,
'filename' => $param[ 'filename' ],
'path' => $param[ 'path' ],
'sku_num' => $allRow - 1,
'create_time' => time()
];
$res = model('store_stock_import')->add($data);
if (!$res) {
return $this->error('', '上传文件失败');
}
model('store_stock_import')->startTrans();
try {
for ($i = 2; $i <= $allRow; $i++) {
//商品id
$goods_id = $PHPExcel->getActiveSheet()->getCell('A' . $i)->getValue();
$goods_id = trim($goods_id, ' ');
//商品名称
$goods_name = $PHPExcel->getActiveSheet()->getCell('B' . $i)->getValue();
$goods_name = trim($goods_name, ' ');
//sku_id
$sku_id = $PHPExcel->getActiveSheet()->getCell('C' . $i)->getValue();
$sku_id = trim($sku_id, ' ');
//sku名称
$sku_name = $PHPExcel->getActiveSheet()->getCell('D' . $i)->getValue();
$sku_name = trim($sku_name, ' ');
//库存(增/减)
$stock = $PHPExcel->getActiveSheet()->getCell('F' . $i)->getValue();
$stock = trim($stock, ' ');
if (empty($goods_id) || empty($sku_id) || empty($stock)) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => '商品编号、sku编号或者库存为空'
]
);
continue;
}
$goods_model = new Goods();
$sku_info = $goods_model->getGoodsSkuInfo([ [ 'sku_id', '=', $sku_id ], [ 'goods_id', '=', $goods_id ], [ 'site_id', '=', $site_id ] ]);
if (empty($sku_info[ 'data' ])) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => '商品不存在'
]
);
continue;
}
$sku_info_result = $this->getStoreGoodsSkuInfo([ [ "store_id", "=", $store_id ], [ "sku_id", "=", $sku_id ] ], "sku_id");
$sku_info = $sku_info_result[ "data" ];
if (empty($sku_info)) {
$sku_data = array (
"goods_id" => $goods_id,
"sku_id" => $sku_id,
"store_id" => $store_id,
);
$this->addStoreGoodsSku($sku_data);
}
$store_data = [
'store_id' => $store_id,
'sku_id' => $sku_id,
'stock' => $stock
];
if ($stock > 0) {
$item_result = $this->incStock($store_data);
} else {
$store_data[ 'stock' ] = abs($store_data[ 'stock' ]);
$item_result = $this->decStock($store_data);
}
if ($item_result[ "code" ] < 0) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => $item_result[ 'message' ]
]
);
continue;
}
//添加记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => 0, 'reason' => ''
]
);
}
model('store_stock_import')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_stock_import')->rollback();
model('store_stock_import')->update([ 'error_num' => $allRow - 1 ], [ [ 'id', '=', $res ] ]);
return $this->error('', $e->getMessage());
}
}
/**
* 核验门店库存是否足够
* @param $params
*/
public function checkStoreGoodsSkuStock($params)
{
$store_id = $params[ 'store_id' ];
$goods_id = $params[ 'goods_id' ];
$sku_id = $params[ 'sku_id' ];
$site_id = $params[ 'site_id' ];
$num = $params[ 'num' ];
$sku_condition = array (
[ 'goods_id', '=', $goods_id ],
[ 'sku_id', '=', $sku_id ],
[ 'store_id', '=', $store_id ],
);
$store_sku_info = model('store_goods_sku')->getInfo($sku_condition, 'stock');
if (empty($store_sku_info)) {
return $this->error(-1, '库存不足!');
}
$store_sku_info[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if (( $store_sku_info[ 'stock' ] - $num ) < 0) {
return $this->error(-1, '库存不足!');
}
return $this->success();
}
}

224
addon/store/model/StoreMember.php Executable file
View File

@@ -0,0 +1,224 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use think\facade\Db;
use app\model\system\Address;
/**
* 店铺会员表
*/
class StoreMember extends BaseModel
{
/**
* 添加店铺关注会员
* @param $site_id
* @param $member_id
* @param int $is_subscribe
* @return array
*/
public function addStoreMember($store_id, $member_id)
{
$shop_member_info = model("store_member")->getInfo([ [ 'store_id', '=', $store_id ], [ 'member_id', '=', $member_id ] ], 'id');
if (!empty($shop_member_info)) {
return $this->success();
} else {
$data = [
'store_id' => $store_id,
'member_id' => $member_id,
'create_time' => time(),
];
$res = model("store_member")->add($data);
}
return $this->success($res);
}
/**
* 获取店铺会员分页列表
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getStoreMemberPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '')
{
$field = 'nm.member_id, nm.source_member, nm.username, nm.nickname, nm.mobile, nm.email, nm.headimg, nm.status, nm.member_level,nm.member_level_name,nm.balance,nm.balance_money,nsm.store_id, nsm.create_time';
$alias = 'nsm';
$join = [
[
'member nm',
'nsm.member_id = nm.member_id',
'inner'
],
];
$list = model("store_member")->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取会员店铺分页列表
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getMemberShopPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'nsm.subscribe_time desc', $field = 'ns.site_id, ns.site_name, ns.is_own, ns.logo, ns.telephone,ns.sub_num, nsm.subscribe_time,ns.seo_description,ns.shop_desccredit,ns.shop_servicecredit,ns.shop_deliverycredit,ns.shop_sales,ns.shop_sales,ns.is_own')
{
$alias = 'nsm';
$join = [
[
'shop ns',
'nsm.site_id = ns.site_id',
'inner'
],
];
$list = model("shop_member")->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取门店会员数量
* @param $condition
* @param string $alias
* @param array $join
* @param null $group
* @return array
*/
public function getMemberCount($condition, $alias = 'a', $join = [], $group = null)
{
$db = Db::name('store_member')->where($condition);
if (!empty($join)) {
$db = $this->parseJoin($db->alias($alias), $join);
}
if (!empty($group)) {
$db = $db->group($group);
}
$count = $db->count();
return $this->success($count);
}
/**
* 获取门店已购会员数
*/
public function getPurchasedMemberCount($store_id)
{
$prefix = config("database")[ "connections" ][ "mysql" ][ "prefix" ];
$res = model("store_member")->query("SELECT GROUP_CONCAT(member_id) as member_id FROM {$prefix}store_member WHERE store_id = {$store_id}");
if (isset($res[ 0 ]) && isset($res[ 0 ][ 'member_id' ]) && !empty($res[ 0 ][ 'member_id' ])) {
$condition = [
[ 'delivery_store_id', '=', $store_id ],
[ 'member_id', 'in', $res[ 0 ][ 'member_id' ] ]
];
$res = model('order')->getList($condition, 'order_id', '', 'a', [], 'member_id');
return $this->success(count($res));
}
return $this->success(0);
}
/**
* 按地域分布查询会员数量
* @param $site_id
* @param bool $handle
* @return array
*/
public function getMemberCountByArea($site_id, $handle = false)
{
$total_count = $this->getMemberCount([ [ 'site_id', '=', $site_id ] ]);
$address = new Address();
$list = $address->getAreaList([ [ 'pid', '=', 0 ] ], 'id,shortname', 'sort asc');
$data = [];
if ($total_count[ 'data' ]) {
foreach ($list[ 'data' ] as $item) {
$count = $this->getMemberCount([ [ 'nsm.site_id', '=', $site_id ], [ 'nma.is_default', '=', 1 ], [ 'nma.province_id', '=', $item[ 'id' ] ] ], 'nsm', [ [ 'member_address nma', 'nsm.member_id = nma.member_id', 'left' ] ], 'nma.member_id');
if ($handle) {
if ($count[ 'data' ] > 0) {
$data[] = [
'name' => $item['shortname'],
'value' => $count['data'],
'ratio' => $count['data'] > 0 ? sprintf("%.2f", $count['data'] / $total_count['data'] * 100) : 0
];
}
} else {
$data[] = [
'name' => $item['shortname'],
'value' => $count['data'],
'ratio' => $count['data'] > 0 ? sprintf("%.2f", $count['data'] / $total_count['data'] * 100) : 0
];
}
}
}
if ($handle) {
array_multisort(array_column($data, 'value'), SORT_DESC, $data);
}
return $this->success([
'page_count' => 1,
'count' => $total_count[ 'data' ],
'list' => $data
]);
}
/**
* 处理表连接
* @param unknown $db_obj
* @param unknown $join
*/
protected function parseJoin($db_obj, $join)
{
foreach ($join as $item) {
list($table, $on, $type) = $item;
$type = strtolower($type);
switch ( $type ) {
case "left":
$db_obj = $db_obj->leftJoin($table, $on);
break;
case "inner":
$db_obj = $db_obj->join($table, $on);
break;
case "right":
$db_obj = $db_obj->rightjoin($table, $on);
break;
case "full":
$db_obj = $db_obj->fulljoin($table, $on);
break;
default:
break;
}
}
return $db_obj;
}
/**
* 查询会员信息
* @param unknown $where
* @param string $field
* @param string $alias
* @param string $join
* @param string $data
*/
public function getMemberInfo($where = [], $field = true, $alias = 'a', $join = null, $data = null)
{
$info = model("store_member")->getInfo($where, $field, $alias, $join, $data);
if (empty($info)) return $this->error('MEMBER_NOT_EXIST', 'MEMBER_NOT_EXIST');
else return $this->success($info);
}
}

102
addon/store/model/StoreOrder.php Executable file
View File

@@ -0,0 +1,102 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\verify\Verify;
class StoreOrder extends BaseModel
{
/**
* 基础支付方式(不考虑实际在线支付方式或者货到付款方式)
* @var unknown
*/
public $pay_type = [
'offlinepay' => '现金'
];
/**
* 获取支付方式
*/
public function getPayType($site_id)
{
//获取订单基础的其他支付方式
$pay_type = $this->pay_type;
//获取当前所有在线支付方式
$onlinepay = event('PayType', [ "app_type" => "pc", 'site_id' => $site_id ]);
if (!empty($onlinepay)) {
foreach ($onlinepay as $k => $v) {
$pay_type[ $v[ 'pay_type' ] ] = $v[ 'pay_type_name' ];
}
}
return $pay_type;
}
/**
* 订单支付后操作
* @param $order
*/
public function orderPay($order)
{
if (empty($order[ 'delivery_store_id' ])) {
return $this->success();
}
model('store')->startTrans();
try {
model('store')->setInc([ [ 'store_id', '=', $order[ 'delivery_store_id' ] ] ], 'order_num');
model('store')->setInc([ [ 'store_id', '=', $order[ 'delivery_store_id' ] ] ], 'order_money', $order[ 'order_money' ]);
model('store_member')->setInc([ [ 'member_id', '=', $order[ 'member_id' ] ] ], 'order_num');
model('store_member')->setInc([ [ 'member_id', '=', $order[ 'member_id' ] ] ], 'order_money', $order[ 'order_money' ]);
//如果是否门店收银订单,订单会自动核销
if ($order[ 'promotion_type' ] == 'store') {
//主动调用核销流程
$verifier_info = array (
'verifier_id' => 0,
'verifier_name' => '收银台订单自动核销',
"verify_from" => 'store',
'verify_remark' => '门店名称:' . $order[ 'delivery_store_name' ],
);
$verify_model = new Verify();
$result = $verify_model->verify($verifier_info, $order[ 'delivery_code' ]);
if ($result[ 'code' ] < 0) {
model('store')->rollback();
return $result;
}
}
model('store')->commit();
return $this->success();
} catch (\Exception $e) {
model('store')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 门店订单完成后操作 todo 应该删除
* @param $order
*/
public function orderComplete($order_id)
{
// $order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
// if (empty($order_info['delivery_store_id'])) {
// return $this->success();
// }
// model('store')->setInc([['store_id', '=', $order_info['delivery_store_id']]], 'order_complete_num');
// model('store')->setInc([['store_id', '=', $order_info['delivery_store_id']]], 'order_complete_money', $order_info['order_money']);
// model('store_member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_num');
// model('store_member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_money', $order_info['order_money']);
// Cache::tag("store")->clear();
return $this->success();
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
class StoreStockImport extends BaseModel
{
/**
* 详情
* @param array $condition
* @param string $field
* @return array
*/
public function getStoreStockImportInfo($condition = [], $field = '*')
{
$info = model('store_stock_import')->getInfo($condition, $field);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'error_num' ])) {
$info[ 'error_num' ] = numberFormat($info[ 'error_num' ]);
}
}
return $this->success($info);
}
/**
* 删除
* @param $id
* @param $store_id
* @return array
*/
public function deleteStoreStockImport($id, $store_id)
{
model('store_stock_import')->startTrans();
try {
model('store_stock_import')->delete([ [ 'id', '=', $id ], [ 'store_id', '=', $store_id ] ]);
model('store_stock_import_log')->delete([ [ 'file_id', '=', $id ] ]);
model('store_stock_import')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_stock_import')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreStockImportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('store_stock_import')->pageList($condition, $field, $order, $page, $page_size);
foreach ($list as $k => $v) {
if (isset($v[ 'stock' ])) {
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
}
if (isset($v[ 'error_num' ])) {
$list[ $k ][ 'error_num' ] = numberFormat($list[ $k ][ 'error_num' ]);
}
}
return $this->success($list);
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreStockImportPageLogList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('store_stock_import_log')->pageList($condition, $field, $order, $page, $page_size);
foreach ($list as $k => $v) {
if (isset($v[ 'stock' ])) {
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
}
}
return $this->success($list);
}
}

View File

@@ -0,0 +1,647 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\member\MemberAccount;
use app\model\member\Withdraw as MemberWithdraw;
use app\model\store\Store;
use app\model\system\Pay;
use app\model\system\PayTransfer;
use think\facade\Cache;
class StoreWithdraw extends BaseModel
{
const STATUS_WAIT_AUDIT = 0;//待审核
const STATUS_WAIT_TRANSFER = 1;//待转账
const STATUS_SUCCESS = 2;//已转账
const STATUS_IN_PROCESS = 3;//转账中
const STATUS_FAIL = -2;//转账失败
const STATUS_REFUSE = -1;//已拒绝
public $status = array (
self::STATUS_WAIT_AUDIT => '待审核',
self::STATUS_WAIT_TRANSFER => '待转账',
self::STATUS_SUCCESS => '已转账',
self::STATUS_IN_PROCESS => '转账中',
self::STATUS_FAIL => '转账失败',
self::STATUS_REFUSE => '已拒绝',
);
public $settlement_type = array (
'apply' => '申请结算',
'day' => '每日结算',
'week' => '每周结算',
'month' => '每月结算',
);
/**
* 门店账户提现
* @param $params
*/
public function apply($params)
{
$money = $params[ 'money' ] ?? 0;
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ];
$settlement_type = $params[ 'settlement_type' ] ?? 'apply';
$store_config_model = new Config();
$config = $store_config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
$is_audit = $config[ 'is_audit' ];
$is_settlement = $config[ 'is_settlement' ];
if ($is_settlement == 0)
return $this->error([], '门店结算未开启');
$withdraw_least = $config[ 'withdraw_least' ];
$store_model = new Store();
$store_condition = array (
[ 'site_id', '=', $site_id ],
[ 'store_id', '=', $store_id ]
);
$store_info = $store_model->getStoreInfoByAccount($store_condition)[ 'data' ] ?? [];
if (empty($store_info))
return $this->error([], '找不到可结算的门店');
if ($settlement_type == 'apply') {
if ($money < $withdraw_least) {
return $this->error([], '门店最低结算金额为' . $withdraw_least . '元');
}
}
if ($money > $store_info[ 'account' ]) {
return $this->error([], '申请结算金额不能大于门店最大可结算金额');
}
$bank_type = $store_info[ 'bank_type' ];
if ($bank_type == 0)
return $this->error([], '当前门店未配置结算账户,无法结算');
$transfer_type = array ( 3 => 'bank', 2 => 'alipay', 1 => 'wechatpay' )[ $store_info[ 'bank_type' ] ];//转账方式
$transfer_type_list = $this->getTransferType($site_id);
$transfer_type_name = $transfer_type_list[ $transfer_type ] ?? '';
switch ( $transfer_type ) {
case 'bank':
$bank_name = $store_info[ 'bank_type_name' ];
$realname = $store_info[ 'bank_user_name' ];//户头
$account_number = $store_info[ 'bank_type_account' ];
break;
case 'alipay':
$realname = $store_info[ 'bank_user_name' ];
$account_number = $store_info[ 'bank_type_account' ];
break;
case 'wechatpay':
$realname = $store_info[ 'bank_user_name' ];
$account_number = $store_info[ 'bank_type_account' ];
break;
}
$data = array (
'site_id' => $site_id,
'withdraw_no' => $this->createWithdrawNo(),
'store_name' => $store_info[ 'store_name' ],
'store_id' => $store_id,
'transfer_type' => $transfer_type,
'transfer_type_name' => $transfer_type_name,
'money' => $money,
'apply_time' => time(),
'status' => 0,
'status_name' => $this->status[ 0 ],
'realname' => $realname ?? '',
'bank_name' => $bank_name ?? '',
'account_number' => $account_number ?? '',
'settlement_type' => $settlement_type,
'settlement_type_name' => $this->settlement_type[ $settlement_type ]
);
model('store_withdraw')->startTrans();
try {
$withdraw_id = model('store_withdraw')->add($data);
//添加转账记录
$pay_transfer_model = new PayTransfer();
$info = model('store_withdraw')->getInfo([['withdraw_id', '=', $withdraw_id]]);
$pay_transfer_model->add([
"out_trade_no" => $info[ "withdraw_no" ],
"real_name" => $info[ "realname" ],
"amount" => $info[ "money" ],
"desc" => "门店申请提现",
"transfer_type" => $info[ "transfer_type" ],
"account_number" => $info[ "account_number" ],
"site_id" => $info[ "site_id" ],
"is_weapp" => 0,
"member_id" => $info[ 'store_id' ],
'from_type' => 'store_withdraw',
"relate_tag" => $info['withdraw_id'],
]);
//如果是申请提现,也同时生成一个结算单
if($settlement_type == 'apply'){
$start_time = 0;
$last_withdraw_info = model('store_withdraw')->getFirstData([['store_id', '=', $store_id]], '*', 'apply_time desc');
if(!empty($last_withdraw_info)) $start_time = $last_withdraw_info['apply_time'];
$settlement_model = new Settlement();
$settlement_model->addSettlement([
'site_id' => $site_id,
'store_id' => $store_id,
'start_time' => $start_time,
'end_time' => $data['apply_time'],
'store_commission' => $money,
'withdraw_id' => $withdraw_id,
]);
}
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => -$money,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '门店申请结算,结算金额' . $money,
'related_id' => $withdraw_id
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//增加结算中余额
model('store')->setInc([ [ 'store_id', '=', $store_id ] ], 'account_apply', $money);
//结算无需审核的话,就直接结算
if ($is_audit == 0) {
$result = $this->agree([ 'withdraw_id' => $withdraw_id, 'site_id' => $site_id, 'store_id' => $store_id ]);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
}
model('store_withdraw')->commit();
return $this->success($withdraw_id);
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 同意结算申请
* @param $condition
*/
public function agree($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ],
[ 'status', '=', 0 ]
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error(null, '未获取到提现信息');
$data = array (
'status' => 1,
'status_name' => $this->status[ 1 ],
'audit_time' => time(),
);
model('store_withdraw')->update($data, $condition);
$store_config_model = new Config();
$config = $store_config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ];
if($config['is_auto_transfer'] == 1){
$this->transfer($info['withdraw_id']);
}
return $this->success();
}
/**
* 拒绝结算申请
* @param $condition
*/
public function refuse($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ],
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error(null, '提现信息不存在');
if(!in_array($info['status'], [self::STATUS_WAIT_AUDIT, self::STATUS_WAIT_TRANSFER])){
return $this->error(null, '提现状态有误');
}
model('store_withdraw')->startTrans();
try {
$data = array (
'status' => -1,
'status_name' => $this->status[ -1 ],
'refuse_reason' => $params[ 'refuse_reason' ],
'audit_time' => time(),
);
model('store_withdraw')->update($data, $condition);
$money = $info[ 'money' ];
//增加现金余额
$store_id = $info[ 'store_id' ];
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => $money,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '门店结算拒绝,返还金额' . $money.',拒绝原因:'.$params[ 'refuse_reason' ],
'related_id' => $withdraw_id
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//减少结算中余额
model('store')->setDec([ [ 'store_id', '=', $store_id ] ], 'account_apply', $money);
//如果关联结算要把订单的结算状态和结算id清除
$settlement_model = new Settlement();
$settlement_model->refuseWithdraw($withdraw_id);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 结算转账完成
* @param $id
*/
public function transferFinish($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ]
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error();
$transfer_time = time();
model('store_withdraw')->startTrans();
try {
$store_id = $info[ 'store_id' ];
$data = [
'status' => 2,
'status_name' => $this->status[ 2 ],
'transfer_time' => $transfer_time,
'voucher_img' => $params[ 'voucher_img' ] ?? '',
'voucher_desc' => $params[ 'voucher_desc' ] ?? ''
];
model('store_withdraw')->update($data, $condition);
$store_condition = array (
[ 'store_id', '=', $store_id ]
);
$money = $info[ 'money' ];
//增加已结算余额
model('store')->setInc($store_condition, 'account_withdraw', $money);
//减少结算中余额
model('store')->setDec($store_condition, 'account_apply', $money);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 转账
* @param $condition
*/
public function transfer($withdraw_id)
{
$info_result = $this->getStoreWithdrawInfo([ [ "withdraw_id", "=", $withdraw_id ] ]);
if (empty($info_result[ "data" ]))
return $this->error(null, '提现信息有误');
$info = $info_result[ "data" ];
if (!in_array($info[ "transfer_type" ], [ "wechatpay", "alipay" ]))
return $this->error('', "当前提现方式不支持在线转账");
$pay_transfer_model = new PayTransfer();
$transfer_res = $pay_transfer_model->transfer('store_withdraw', $info['withdraw_id']);
return $transfer_res;
}
/**
* 转账结果通知
* @param $param
* @return array
* @throws \think\db\exception\DbException
*/
public function transferNotify($param)
{
$withdraw_id = $param['relate_tag'];
$site_id = $param['site_id'];
$withdraw_info = $this->getStoreWithdrawInfo([
['withdraw_id', '=', $withdraw_id ],
['site_id', '=', $site_id],
], "*")['data'];
if(empty($withdraw_info)){
return $this->error(null, '提现信息有误');
}
//成功的处理
switch($param['status']){
case PayTransfer::STATUS_IN_PROCESS:
return $this->transferInProcess([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
]);
break;
case PayTransfer::STATUS_SUCCESS:
return $this->transferFinish([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
]);
break;
case PayTransfer::STATUS_FAIL:
$resp_data = json_decode($param['resp_data'], true);
$fail_reason = $resp_data['fail_reason'] ?? '';
return $this->transferFail([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
'fail_reason' => $fail_reason,
]);
break;
default:
return $this->error(null, '转账结果状态有误');
}
}
/**
* 转账失败
* @param $param
* @return array
*/
public function transferFail($param)
{
$withdraw_id = $param['withdraw_id'];
$site_id = $param['site_id'];
$fail_reason = $param['fail_reason'];
$condition = [
[ 'withdraw_id', '=', $withdraw_id ],
[ 'site_id', '=', $site_id ],
[ 'status', 'in', [self::STATUS_WAIT_TRANSFER, self::STATUS_IN_PROCESS] ],
];
$info = $this->getStoreWithdrawInfo($condition)['data'];
if (empty($info)) return $this->error(null, '提现信息有误');
model('store_withdraw')->startTrans();
try {
$data = [
'status' => self::STATUS_FAIL,
'status_name' => $this->status[self::STATUS_FAIL],
'refuse_reason' => $fail_reason,
];
model("store_withdraw")->update($data, $condition);
//增加现金余额
$store_id = $info[ 'store_id' ];
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => $info['money'],
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '提现失败返还,原因:'.$fail_reason,
'related_id' => $info['withdraw_id']
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//减少结算中余额
model('store')->setDec([ [ 'store_id', '=', $store_id ] ], 'account_apply', $info['money']);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error(['file' => $e->getFile(), 'line' => $e->getLine(), 'message' => $e->getMessage()], $e->getMessage());
}
}
/**
* 转账中
* @param $param
* @return array
*/
public function transferInProcess($param)
{
$withdraw_id = $param['withdraw_id'];
$site_id = $param['site_id'];
$condition = [
[ 'withdraw_id', '=', $withdraw_id ],
[ 'site_id', '=', $site_id ],
[ 'status', '=', self::STATUS_WAIT_TRANSFER ]
];
$info = $this->getStoreWithdrawInfo($condition)['data'];
if (empty($info)) return $this->error(null, '提现信息有误');
model("store_withdraw")->update([
'status' => self::STATUS_IN_PROCESS,
'status_name' => $this->status[self::STATUS_IN_PROCESS],
], [['withdraw_id', '=', $withdraw_id]]);
return $this->success();
}
/**
* 转账方式
*/
public function getTransferType($site_id = 0)
{
$pay_model = new Pay();
$transfer_type_list = $pay_model->getTransferType($site_id);
$data = [];
foreach ($transfer_type_list as $k => $v) {
$data[ $k ] = $v;
}
return $data;
}
/**
* 结算
* @param $condition
*/
public function getStoreWithdrawInfo($condition, $field = '*')
{
$info = model('store_withdraw')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 结算记录
* @param $condition
* @param string $field
*/
public function getStoreWithdrawList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_withdraw')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取账户分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array|\multitype
*/
public function getStoreWithdrawPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'apply_time desc', $field = '*', $alias = 'a', $join = [])
{
$list = model('store_withdraw')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取结算单数量
* @param $condition
* @return array
*/
public function getStoreWithdrawCount($condition)
{
$data = model('store_withdraw')->getCount($condition);
return $this->success($data);
}
/**
* 获取结算单字段总和
* @param $condition
* @return array
*/
public function getStoreWithdrawSum($condition, $field)
{
$data = model('store_withdraw')->getSum($condition, $field);
return $this->success($data);
}
/**
* 结算详情
* @param $params
* @return array
*/
public function detail($params)
{
$withdraw_id = $params[ 'withdraw_id' ];
$site_id = $params[ 'site_id' ] ?? 0;
$store_id = $params[ 'store_id' ] ?? 0;
$condition = array (
[ 'withdraw_id', '=', $withdraw_id ]
);
if ($site_id > 0) {
$condition[] = [ 'site_id', '=', $site_id ];
}
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error();
$settlement_type = $info[ 'settlement_type' ];
//非主动申请的结算,会有周期性结算信息
if ($settlement_type != 'apply') {
$settlement_model = new Settlement();
$settlement_condition = array (
[ 'withdraw_id', '=', $withdraw_id ]
);
$settlement_info = $settlement_model->getSettlementInfo($settlement_condition)[ 'data' ] ?? [];
if (!empty($settlement_info))
$info[ 'settlement_info' ] = $settlement_info;
}
return $this->success($info);
}
/**
* 翻译
* @param $data
*/
// public function translate($data){
// $settlement_type = $data['settlement_type'] ?? '';
// if(!empty($settlement_type)){
// $data['settlement_type_name'] = $settlement_type;
// }
//
// return $data;
// }
/**
* 结算流水号
*/
private function createWithdrawNo()
{
$cache = Cache::get('store_withdraw_no' . time());
if (empty($cache)) {
Cache::set('niutk' . time(), 1000);
$cache = Cache::get('store_withdraw_no' . time());
} else {
$cache = $cache + 1;
Cache::set('store_withdraw_no' . time(), $cache);
}
$no = date('Ymdhis', time()) . rand(1000, 9999) . $cache;
return $no;
}
/**
* 转账检测
* @param $id
*/
public function transferCheck($id)
{
$info_result = $this->getStoreWithdrawInfo([ [ "withdraw_id", "=", $id ] ]);
if (empty($info_result["data"]))
return $this->error(null, '提现信息缺失');
$info = $info_result["data"];
if(!in_array($info["transfer_type"], ["wechatpay","alipay"]))
return $this->error('', "当前提现方式不支持在线转账");
if($info['status'] != self::STATUS_WAIT_TRANSFER){
return $this->error('', "当前提现单非待转账状态");
}
return $this->success();
}
}

View File

@@ -0,0 +1,368 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model\settlement;
use app\model\BaseModel;
use addon\store\model\Config;
use addon\store\model\StoreAccount;
use app\model\store\Store;
use think\facade\Log;
class OrderSettlement extends BaseModel
{
const ACTION_EXECUTE = 1;
const ACTION_RETURN_DATA = 2;
/**
* 门店订单分成计算
* @param $data
* @param $action
*/
public function orderSettlementAccount($data, $action = self::ACTION_EXECUTE)
{
$order_id = $data[ 'order_id' ];
$order_info = model('order')->getInfo([ [ 'order_id', '=', $order_id ] ]);
if(empty($order_info)) return null;
if(empty($order_info['store_id'])) return null;
$store_id = $order_info[ 'store_id' ];
$site_id = $order_info[ 'site_id' ];
$config_model = new Config();
$config = $config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
$is_settlement = $config[ 'is_settlement' ];//结算模式 todo 系统配置的门店计算开关是否会对门店结算开关造成影响
if ($is_settlement > 0) {
$store_model = new Store();
$store_condition = array (
[ 'site_id', '=', $site_id ],
[ 'store_id', '=', $store_id ]
);
$store_info = $store_model->getStoreInfoByAccount($store_condition)[ 'data' ] ?? [];
$is_settlement = $store_info[ 'is_settlement' ];
if ($is_settlement > 0) {
$settlement_pay_type = $config['settlement_pay_type'] ?? [];//参与结算的支付方式
if(!empty($settlement_pay_type)){
if(in_array($order_info['pay_type'], explode(',', $settlement_pay_type))){
$store_settlement_rate = $store_info[ 'settlement_rate' ];
if ($store_settlement_rate > 0) {
$settlement_rate = $store_settlement_rate;
} else {
$settlement_rate = $config[ 'settlement_rate' ];
}
if ($settlement_rate > 0) {
$settlement_rate_calc = $settlement_rate / 100;//计算门店抽成比例
$order_money = $order_info[ 'order_money' ];
//todo 可能还有退款
$settlement_cost = $config[ 'settlement_cost' ];
$settlement_cost_array = explode(',', $settlement_cost);
//总金额
$base_money = $order_money;
$remark = '订单编号:'.$order_info['order_no'].';结算佣金=([订单金额]'.$base_money;
//退款金额
if(!empty($order_info[ 'refund_money' ])){
$base_money -= $order_info[ 'refund_money' ];//todo 这儿涉及到一个问题,退款的金额里面包含一部分余额,可能结算金额不太一致
if($order_info['refund_money'] > 0){
$remark .= '-[退款金额]'.$order_info['refund_money'];
}
}
//余额抵扣
if($order_info['balance_money'] > 0){
$balance_money = $order_info[ 'balance_money' ];
$base_money -= $balance_money;
$remark .= '-[余额抵扣]'.$order_info['balance_money'];
}
//分销佣金
if (in_array('fenxiao_commission', $settlement_cost_array)) {
$commission = $order_info[ 'commission' ];
$base_money -= $commission;
if($order_info['commission'] > 0){
$remark .= '-[分销佣金]'.$order_info['commission'].')';
}
}
//积分抵扣
if (in_array('point', $settlement_cost_array)) {
$point_money = $order_info[ 'point_money' ];
$base_money += $point_money;
if($order_info['point_money'] > 0){
$remark .= '+[积分抵扣]'.$order_info['point_money'];
}
}
//优惠券比较特殊, 不过不扣除要价格优惠券抵扣金额加回去
if (!in_array('coupon', $settlement_cost_array)) {
$coupon_money = $order_info[ 'coupon_money' ];
$base_money += $coupon_money;
if($order_info['coupon_money'] > 0){
$remark .= '+[优惠券券金额]'.$order_info['coupon_money'];
}
}
if ($base_money > 0) {
$store_commission_rate = $settlement_rate;
$store_commission = round($base_money * $settlement_rate_calc, 2);
$remark .= ')*'.$store_commission_rate.'%='.$store_commission;
$order_data = array (
'store_commission_rate' => $store_commission_rate,
'store_commission' => $store_commission
);
$order_condition = array (
[ 'order_id', '=', $order_id ]
);
model('order')->update($order_data, $order_condition);
$store_account_model = new StoreAccount();
//门店账户金额增加
$store_account_data = array (
'account_data' => $store_commission,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'order',
'remark' => $remark,
'related_id' => $order_id
);
if($action == self::ACTION_EXECUTE){
//防止重复添加
$store_account_info = $store_account_model->getStoreAccountInfo([['from_type', '=', 'order'], ['related_id', '=', $order_id]])['data'];
if(empty($store_account_info)){
$store_account_model->addStoreAccount($store_account_data);
}
}else{
return $store_account_data;
}
}
}
}
}
}
}
}
/**
*
* @param $data
* @param $action
*/
public function orderRefundSettlementAccount($data, $action = self::ACTION_EXECUTE)
{
// $order_goods_id = $data[ 'order_goods_id' ];
$order_goods_info = $data['order_goods_info'];
if (empty($order_goods_info))
return null;
$order_goods_id = $order_goods_info['order_goods_id'];
// $order_id = $order_goods_info[ 'order_id' ];
$order_info = $data['order_info'];
if (empty($order_info))
return null;
$site_id = $order_info[ 'site_id' ];
$store_id = $order_info[ 'store_id' ];
$order_scene = $order_info[ 'order_scene' ];
//只有收银台订单会有这种情况
if ($store_id == 0 || $order_scene != 'cashier')
return null;
$refund_money = sprintf("%.2f", $data['refund_money']);
$order_money = $order_info[ 'order_money' ];
if($order_money <= 0)
return null;
if($refund_money <= 0){
return null;
}
$store_commission = $order_info[ 'store_commission' ];
$refund_store_commission = round($store_commission * ( $refund_money / $order_money ), 2);
$store_account_model = new StoreAccount();
//门店账户金额减少
$store_account_data = array (
'account_data' => -$refund_store_commission,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'refund',
'remark' => "订单编号:{$order_info['order_no']};退款编号:{$order_goods_info['refund_no']};扣除结算佣金=[结算佣金]{$store_commission}*([退款金额]{$refund_money}/[订单金额]{$order_money})={$refund_store_commission}",
'related_id' => $order_goods_id,
'is_limit' => 0
);
if($action == self::ACTION_EXECUTE){
$store_account_model->addStoreAccount($store_account_data);
}else{
return $store_account_data;
}
}
/**
* 矫正任务
* @param array $param
* @return array
*/
public function correctStoreAccountTask($param = [])
{
$last_order_id = $param['last_order_id'] ?? 0;
$store_id = $param['store_id'] ?? 0;
$start_time = time();
$max_exec_time = 50;
$res_list = [];
$is_end = false;
while (true){
if(time() - $start_time > $max_exec_time){
break;
}
$order_info = model('order')->getFirstData([
['order_id', '>', $last_order_id],
['store_id', '=', $store_id],
]);
if(empty($order_info)){
$is_end = true;
break;
}
$res = $this->correctStoreAccount($order_info);
if(!empty($res)) $res_list[$order_info['order_id']] = $res;
$last_order_id = $order_info['order_id'];
}
$account = model('store_account')->getSum([['store_id', '=', $store_id]], 'account_data');
model('store')->update(['account' => $account], [['store_id', '=', $store_id]]);
return [
'res_list' => $res_list,
'last_order_id' => $last_order_id,
'is_end' => $is_end,
'account' => $account,
];
}
/**
* 矫正方法
* @param $order_info
* @return array
*/
public function correctStoreAccount($order_info)
{
$deal_res = [];
$store_account_model = new StoreAccount();
$from_type_list = $store_account_model->from_type;
//矫正退款总额
$order_goods_list = model('order_goods')->getList([
['order_id', '=', $order_info['order_id']],
]);
$refund_money = 0;
foreach($order_goods_list as $order_goods){
if(in_array($order_goods['refund_status'], [3,-3])){
$refund_money += $order_goods['refund_real_money'] + $order_goods['shop_active_refund_money'];
}
}
if($order_info['refund_money'] != $refund_money){
model('order')->update(['refund_money' => $refund_money], [['order_id', '=', $order_info['order_id']]]);
$deal_res[] = "矫正退款总额,{$order_info['refund_money']}=>$refund_money";
}
//清空数据
model('store_account')->delete([['from_type', '=', 'order'], ['related_id', '=', $order_info['order_id']]]);
if(!empty($order_goods_list)){
model('store_account')->delete([['from_type', '=', 'refund'], ['related_id', 'in', array_column($order_goods_list, 'order_goods_id')]]);
}
//重新计算
if($order_info['order_status'] == 10){
$store_account_data = $this->orderSettlementAccount(['order_id' => $order_info['order_id']], self::ACTION_RETURN_DATA);
if(!empty($store_account_data)){
$store_account_data['from_type_name'] = $from_type_list['order']['type_name'];
$store_account_data['create_time'] = time();
model('store_account')->add($store_account_data);
$deal_res[] = $store_account_data['remark'];
}
}
if(!empty($deal_res)){
Log::write('订单结算数据矫正:order_id=>'.$order_info['order_id']);
Log::write($deal_res);
}
return $deal_res;
}
public function findStoreAccountErrorDataTask($param)
{
$last_order_id = $param['last_order_id'] ?? 0;
$store_id = $param['store_id'] ?? 0;
$start_time = time();
$max_exec_time = 50;
$res_list = [];
$is_end = false;
while (true){
if(time() - $start_time > $max_exec_time){
break;
}
$order_info = model('order')->getFirstData([
['order_id', '>', $last_order_id],
['store_id', '=', $store_id],
]);
if(empty($order_info)){
$is_end = true;
break;
}
$res = $this->findStoreAccountErrorData($order_info);
if(!empty($res)) $res_list[$order_info['order_id']] = $res;
$last_order_id = $order_info['order_id'];
}
return [
'res_list' => $res_list,
'last_order_id' => $last_order_id,
'is_end' => $is_end,
];
}
public function findStoreAccountErrorData($order_info)
{
$deal_res = [];
//矫正退款总额
$order_goods_list = model('order_goods')->getList([
['order_id', '=', $order_info['order_id']],
]);
$refund_money = 0;
foreach($order_goods_list as $order_goods){
if(in_array($order_goods['refund_status'], [3,-3])){
$refund_money += $order_goods['refund_real_money'] + $order_goods['shop_active_refund_money'];
}
}
if($order_info['refund_money'] != $refund_money){
model('order')->update(['refund_money' => $refund_money], [['order_id', '=', $order_info['order_id']]]);
$deal_res[] = "矫正退款总额,{$order_info['refund_money']}=>$refund_money";
}
//比对数据库数据和计算数据
$order_goods_ids = join(',', array_column($order_goods_list, 'order_goods_id'));
if(empty($order_goods_ids)) $order_goods_ids = '0';
$store_account_list = model('store_account')->getList([
['', 'exp', \think\facade\Db::raw("(from_type = 'order' and related_id = {$order_info['order_id']}) or (from_type = 'refund' and related_id in ({$order_goods_ids}))")],
]);
$db_store_account = array_sum(array_column($store_account_list, 'account_data'));
if($order_info['order_status'] == 10){
$store_account_data = $this->orderSettlementAccount(['order_id' => $order_info['order_id']], self::ACTION_RETURN_DATA);
}
$calc_store_account = $store_account_data['account_data'] ?? 0;
if($db_store_account <> $calc_store_account){
$deal_res[] = [
"数据库记录:{$db_store_account},实时计算:{$calc_store_account}",
$store_account_list,
];
}
return $deal_res;
}
}

View File

@@ -0,0 +1,131 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\shop\controller;
use addon\store\model\StoreAccount;
use app\model\system\Export as ExportModel;
use app\shop\controller\BaseShop;
/**
* 门店账户
*/
class Account extends BaseShop
{
/**
* 门店提现列表
* @return mixed
*/
public function lists()
{
$account_model = new StoreAccount();
if (request()->isJson()) {
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$remark = input('remark', '');
$start_date = input('start_date', '');
$end_date = input('end_date', '');
$from_type = input('from_type', '');
$store_id = input('store_id', 0);//门店
$alias = 'sa';
$join = [
['store s', 'sa.store_id = s.store_id', 'inner'],
];
$condition = [ [ 'sa.site_id', '=', $this->site_id ] ];
if (!empty($remark)) {
$condition[] = [ 'sa.remark', 'like', '%' . $remark . '%' ];
}
if (!empty($from_type)) {
$condition[] = [ 'sa.from_type', '=', $from_type ];
}
if ($store_id > 0) {
$condition[] = [ 'sa.store_id', '=', $store_id ];
}
if ($start_date != '' && $end_date != '') {
$condition[] = [ 'sa.create_time', 'between', [ strtotime($start_date), strtotime($end_date) ] ];
} else if ($start_date != '' && $end_date == '') {
$condition[] = [ 'sa.create_time', '>=', strtotime($start_date) ];
} else if ($start_date == '' && $end_date != '') {
$condition[] = [ 'sa.create_time', '<=', strtotime($end_date) ];
}
$field = 'sa.*,s.store_name';
$order = 'sa.id desc';
$res = $account_model->getStoreAccountPageList($condition, $page, $page_size, $order, $field, $alias, $join);
//账户金额累加
$account_info = $account_model->getStoreAccountInfo($condition, 'sum(sa.account_data) as account_data_sum', $alias, $join)['data'];
$res['data']['account_data_sum'] = $account_info['account_data_sum'] ?? 0;
return $res;
} else {
//门店列表
$store_model = new \app\model\store\Store();
$store_list = $store_model->getStoreList([ [ 'site_id', '=', $this->site_id ] ], '*', 'is_default desc,store_id desc')[ 'data' ] ?? [];
$this->assign('store_list', $store_list);
//门店相关统计
$stat_model = new \addon\store\model\Stat();
$stat_condition = array (
[ 'site_id', '=', $this->site_id ]
);
$total_account = $stat_model->getStoreAccountSum($stat_condition, 'account')[ 'data' ] ?? 0;
$total_account_apply = $stat_model->getStoreAccountSum($stat_condition, 'account_apply')[ 'data' ] ?? 0;
$total_account_withdraw = $stat_model->getStoreAccountSum($stat_condition, 'account_withdraw')[ 'data' ] ?? 0;
$this->assign('stat', [
'total_account' => $total_account,
'total_account_apply' => $total_account_apply,
'total_account_withdraw' => $total_account_withdraw,
]);
//来源方式
$from_type_list = $account_model->from_type;
$this->assign('from_type_list', $from_type_list);
return $this->fetch('account/lists');
}
}
/**
* 添加导出
*/
public function addExport()
{
$input = input();
$input['site_id'] = $this->site_id;
$account_model = new StoreAccount();
return $account_model->addStoreAccountExport($input);
}
/**
* 导出列表
*/
public function exportList()
{
$param = [
'from_type_list' => [
['id' => 'store_account', 'name' => '门店账户'],
],
'lists_url' => 'store://shop/account/exportList',
'delete_url' => 'store://shop/account/deleteExport',
];
$export_controller = new \app\shop\controller\Export();
return $export_controller->lists($param);
}
/**
* 删除导出
*/
public function deleteExport()
{
$export_controller = new \app\shop\controller\Export();
return $export_controller->delete('store_account');
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\shop\controller;
use addon\store\model\Config as ConfigModel;
use app\model\order\OrderCommon as OrderCommonModel;
use app\shop\controller\BaseShop;
use think\App;
/**
* 门店设置控制器
*/
class Config extends BaseShop
{
public function __construct(App $app = null)
{
$this->replace = [
'STORE_IMG' => __ROOT__ . '/addon/store/shop/view/public/img',
'STORE_JS' => __ROOT__ . '/addon/store/shop/view/public/js',
'STORE_CSS' => __ROOT__ . '/addon/store/shop/view/public/css',
];
parent::__construct($app);
}
/**
* 门店结算周期配置
*/
public function index()
{
$config_model = new ConfigModel();
if (request()->isJson()) {
if(env('IS_RELEASE_WEAPP')){
return error(-1, '发布小程序期间禁止操作');
}
//门店结算与提现设置
$withdraw_config = [
'is_settlement' => input('is_settlement', 0), // 是否进行门店结算
'period_type' => input('period_type', 4), // 结算方式 1 按天 2. 按周 3. 按月 4. 门店申请结算
'settlement_rate' => input('settlement_rate', 0), // 结算比率
'settlement_pay_type' => input('settlement_pay_type', ''), // 结算付款控制
'settlement_cost' => input('settlement_cost', ''), // 结算成本控制 coupon,point,balance,fenxiao_commission
'is_withdraw' => input('is_withdraw', 0), // 是否允许提现
'is_audit' => input('is_audit', 0), // 是否需要提现审核
'is_auto_transfer' => input('is_auto_transfer', 0), // 是否自动转账
'withdraw_type' => input('withdraw_type', ''), // 可提现账户类型 wechatalipay bank
'withdraw_least' => input('withdraw_least', 0), // 提现最低金额
];
$config_model->setStoreWithdrawConfig($this->site_id, $withdraw_config);
$business_config = [
'store_business' => input('store_business', 'shop'), // 门店运营模式 shop店铺整体运营 store连锁门店运营模式
'is_allow_change' => input('is_allow_change', 1), // 是否允许切换门店
'confirm_popup_control' => input('confirm_popup_control', 0), // 门店确认弹窗
'store_auth' => input('store_auth', ''), // 门店控制权限
];
$res = $config_model->setStoreBusinessConfig($this->site_id, $business_config);
return $res;
} else {
$business_config = $config_model->getStoreBusinessConfig($this->site_id)[ 'data' ][ 'value' ];
$this->assign('business_config', $business_config);
$withdraw_config = $config_model->getStoreWithdrawConfig($this->site_id)[ 'data' ][ 'value' ];
$this->assign('withdraw_config', $withdraw_config);
if (addon_is_exit('cashier') == 1) {
$order_common_model = new OrderCommonModel();
$pay_type = $order_common_model->getPayType([ 'order_type' => 5 ]);
if (isset($pay_type[ 'BALANCE' ])) unset($pay_type[ 'BALANCE' ]);
if (isset($pay_type[ 'ONLINE_PAY' ])) unset($pay_type[ 'ONLINE_PAY' ]);
$this->assign('pay_type_list', $pay_type);
}
return $this->fetch('config/index');
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\shop\controller;
use app\model\order\OrderCommon as OrderCommonModel;
use app\model\store\Store;
use app\shop\controller\BaseShop;
use addon\store\model\Settlement as SettlementModel;
/**
* 门店结算控制器
*/
class Settlement extends BaseShop
{
/**
* 门店结算列表
*/
public function index()
{
if (request()->isJson()) {
$model = new SettlementModel();
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$store_id = input('store_id', '');
if (!empty($store_id)) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$condition[] = [ 'site_id', '=', $this->site_id ];
$start_time = input('start_time', '');
$end_time = input('end_time', '');
if (!empty($start_time) && empty($end_time)) {
$condition[] = [ 'start_time', '>=', $start_time ];
} elseif (empty($start_time) && !empty($end_time)) {
$condition[] = [ 'end_time', '<=', $end_time ];
} elseif (!empty($start_time) && !empty($end_time)) {
$condition[] = [ 'start_time', '>=', $start_time ];
$condition[] = [ 'end_time', '<=', $end_time ];
}
$order = 'id desc';
$field = 'id,settlement_no,site_id,site_name,store_name,order_money,shop_money,refund_platform_money,platform_money,refund_shop_money,
refund_money,create_time,commission,is_settlement,offline_refund_money,offline_order_money,start_time,end_time, store_commission, withdraw_id';
$list = $model->getStoreSettlementPageList($condition, $page, $page_size, $order, $field);
return $list;
}
//门店列表
$store_model = new Store();
$store_list = $store_model->getStoreList([ [ 'site_id', '=', $this->site_id ] ]);
$this->assign('store_list', $store_list[ 'data' ]);
return $this->fetch('settlement/index');
}
/**
* 已结算
* @return array
*/
public function settlement()
{
if (request()->isJson()) {
$remark = input('remark', '');
$settlement_id = input('settlement_id', 0);
if (empty($remark)) {
return error(-1, '请填写备注!');
}
$settlement_model = new SettlementModel();
$res = $settlement_model->editSettlement([ 'is_settlement' => 1, 'remark' => $remark ], [ [ 'id', '=', $settlement_id ] ]);
return $res;
}
}
/**
* detail 结算详情
*/
public function detail()
{
$settlement_id = input('settlement_id', 0);
$order_model = new OrderCommonModel();
if (request()->isJson()) {
$condition[] = [ 'store_settlement_id', '=', $settlement_id ];
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$field = 'order_id,order_no,pay_type,order_money,pay_type_name,order_status,refund_money,commission,finish_time,store_commission';
$list = $order_model->getOrderPageList($condition, $page, $page_size, 'finish_time desc', $field);
return $list;
}
$settlement_model = new SettlementModel();
$settlement_info = $settlement_model->getSettlementInfo([ [ 'id', '=', $settlement_id ] ]);
$store_model = new Store();
$store_info = $store_model->getStoreInfoByAccount([ [ 'store_id', '=', $settlement_info[ 'data' ][ 'store_id' ] ] ], 'create_time');
$this->assign('store_info', $store_info[ 'data' ]);
$this->assign('info', $settlement_info[ 'data' ]);
return $this->fetch('settlement/detail');
}
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
*/
namespace addon\store\shop\controller;
use app\model\store\Stat as StatModel;
use app\model\store\Store as StoreModel;
use app\shop\controller\BaseShop;
use Carbon\Carbon;
class Stat extends BaseShop
{
/**
* 门店统计数据
*/
public function store()
{
$store_list = ( new StoreModel() )->getStoreList([ [ 'site_id', '=', $this->site_id ] ], 'store_id,store_name');
$this->assign('store_list', $store_list[ 'data' ]);
$this->assign('today', Carbon::today()->toDateString());
$this->assign('yesterday', Carbon::yesterday()->toDateString());
return $this->fetch('stat/store');
}
/**
* 统计数据总和
*/
public function statTotal()
{
if (request()->isJson()) {
$store_id = input('store_id', 0);
$start_time = $end_time = input('start_time', strtotime(date('Y-m-d', time())));
$end_time = input('end_time', time());
if ($start_time > $end_time) {
$start_time = input('end_time');
$end_time = input('start_time');
}
$stat_model = new StatModel();
$data = $stat_model->getShopStatSum($this->site_id, $start_time, $end_time, $store_id);
return $data;
}
}
/**
* 获取天统计趋势数据
*/
public function dayStatData()
{
if (request()->isJson()) {
$store_id = input('store_id', 0);
$start_time = input('start_time', strtotime(date('Y-m-d', strtotime('-6 day'))));
$end_time = input('end_time', time());
if ($start_time > $end_time) {
$start_time = input('end_time');
$end_time = input('start_time');
}
$stat_model = new StatModel();
$fields = $stat_model->getStatField();
$fields[] = 'expected_earnings_total_money';
$stat_list = $stat_model->getShopStatList($this->site_id, $start_time, $end_time, $store_id)[ 'data' ];
$temp_stat_list = [];
foreach ($stat_list as $v){
$temp_day = date('Y-m-d', $v[ 'day_time' ]);
$v['day_time'] = $temp_day;
$temp_stat_list[$temp_day][] = $v;
}
// $stat_list = array_map(function($item) {
// $item[ 'day_time' ] = date('Y-m-d', $item[ 'day_time' ]);
// return $item;
// }, $stat_list);
// $stat_list = array_column($stat_list, null, 'day_time');
$day = ceil(( $end_time - $start_time ) / 86400);
foreach ($fields as $field) {
$value = [];
$time = [];
for ($i = 0; $i < $day; $i++) {
$date = date('Y-m-d', $start_time + $i * 86400);
$time[] = $date;
$temp_day_stat_list = $temp_stat_list[$date] ?? [];
$field_value = 0;
if(!empty($temp_day_stat_list)){
foreach($temp_day_stat_list as $temp_v){
$field_value += $temp_v ? $temp_v[ $field ] : 0;
}
}
$value[] += $field_value;
}
$data[ $field ] = $value;
$data[ 'time' ] = $time;
}
return success(0, '', $data);
}
}
/**
* 获取小时统计趋势数据
*/
public function hourStatData()
{
if (request()->isJson()) {
$time = input('start_time', time());
$store_id = input('store_id', 0);
$carbon = Carbon::createFromTimestamp($time);
$stat_model = new StatModel();
$fields = $stat_model->getStatHourField();
$fields[] = 'expected_earnings_total_money';
$stat_list = $stat_model->getShopStatHourList($this->site_id, $carbon->year, $carbon->month, $carbon->day, $store_id)[ 'data' ];
$data = [];
$empty = array_map(function() { return 0; }, range(0, 23, 1));
if (!empty($stat_list)) {
// $stat_list = array_column($stat_list, null, 'hour');
$temp_stat_list = [];
foreach($stat_list as $v){
$temp_stat_list[$v['hour']][] = $v;
}
foreach ($fields as $field) {
$value = [];
for ($i = 0; $i < 24; $i++) {
$value[ $i ] = 0;
$temp_item_stat_list = $temp_stat_list[ $i ] ?? [];
if(!empty($temp_item_stat_list)){
foreach($temp_item_stat_list as $temp_v){
$value[ $i ] += $temp_v ? $temp_v[ $field ] : 0;
}
}
}
$data[ $field ] = $value;
}
} else {
foreach ($fields as $field) {
$data[ $field ] = $empty;
}
}
$data[ 'time' ] = array_map(function($value) { return $value . '时'; }, range(0, 23, 1));
return success(0, '', $data);
}
}
}

View File

@@ -0,0 +1,863 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\shop\controller;
use addon\store\model\Category;
use addon\store\model\Label;
use addon\store\model\StoreWithdraw;
use app\model\express\Config as ExpressConfig;
use app\model\express\ExpressDeliver;
use app\model\express\Local as LocalModel;
use app\model\order\Order;
use app\model\shop\ShopApply as ShopApplyModel;
use app\model\store\Store as StoreModel;
use app\model\system\Address as AddressModel;
use app\model\system\User;
use app\model\web\Config as ConfigModel;
use app\model\web\Config as WebConfig;
use app\shop\controller\BaseShop;
use addon\store\model\Config as StoreConfig;
use think\facade\Cache;
use think\facade\Session;
/**
* 门店
* Class Store
* @package app\shop\controller
*/
class Store extends BaseShop
{
/**
* 门店首页
*/
public function index()
{
if (request()->isJson()) {
$store_model = new StoreModel();
$order_model = new Order();
$withdrawal_model = new StoreWithdraw();
$data = [
'store_num' => $store_model->getStoreCount([ [ 'site_id', '=', $this->site_id ] ])[ 'data' ],
'in_business_num' => $store_model->getStoreCount([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 1 ] ])[ 'data' ],
'total_order_num' => $order_model->getOrderCount([ [ 'site_id', '=', $this->site_id ], [ 'store_id', '>', 0 ], [ 'is_delete', '=', 0 ], [ 'pay_status', '=', 1 ] ])[ 'data' ],
'total_order_money' => $order_model->getOrderMoneySum([ [ 'site_id', '=', $this->site_id ], [ 'store_id', '>', 0 ], [ 'is_delete', '=', 0 ], [ 'pay_status', '=', 1 ] ])[ 'data' ],
'account_apply' => $store_model->getStoreSum([ [ 'site_id', '=', $this->site_id ] ], 'account_apply')[ 'data' ],
'wait_audit_num' => $withdrawal_model->getStoreWithdrawCount([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 0 ] ])[ 'data' ],
'wait_audit_money' => $withdrawal_model->getStoreWithdrawSum([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 0 ] ], 'money')[ 'data' ],
'wait_transfer_num' => $withdrawal_model->getStoreWithdrawCount([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 1 ] ])[ 'data' ],
'wait_transfer_money' => $withdrawal_model->getStoreWithdrawSum([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 1 ] ], 'money')[ 'data' ],
];
return $store_model->success($data);
}
return $this->fetch('store/index');
}
/**
* 门店排行
*/
public function storeRanking()
{
if (request()->isJson()) {
$order = input('order', 'num');
$stat_model = new \addon\store\model\Stat();
$data = $stat_model->getStoreOrderRank([
'site_id' => $this->site_id,
'order' => $order,
]);
return $data;
}
}
/**
* 商品排行
*/
public function goodsRanking()
{
if (request()->isJson()) {
$order_model = new Order();
$order = input('order', 'num');
$condition = [
[ 'og.site_id', '=', $this->site_id ],
[ 'og.store_id', '>', 0 ],
[ 'o.pay_status', '=', 1 ],
[ 'o.is_delete', '=', 0 ]
];
$join = [
[ 'order o', 'o.order_id = og.order_id', 'inner' ],
[ 'store s', 's.store_id = o.store_id', 'inner' ]
];
$order = $order == 'num' ? 'goods_num desc' : 'goods_money desc';
$res = $order_model->getOrderGoodsList($condition, 'sum(og.num) as goods_num, sum(o.goods_money) as goods_money,og.goods_name', $order, 5, 'og.goods_id', 'og', $join);
return $res;
}
}
/**
* 门店列表
* @return mixed
*/
public function lists()
{
if (request()->isJson()) {
$store_model = new StoreModel();
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
// $order = input("order", "create_time desc");
$keyword = input('search_text', '');
$status = input('status', '');
$type = input('type', '');
$condition = [];
if ($type == 1) {
if ($status != null) {
$condition[] = [ 'status', '=', $status ];
$condition[] = [ 'is_frozen', '=', 0 ];
}
} else if ($type == 2) {
$condition[] = [ 'is_frozen', '=', $status ];
}
$condition[] = [ 'site_id', '=', $this->site_id ];
//关键字查询
if (!empty($keyword)) {
$condition[] = ['store_name', 'like', '%' . $keyword . '%'];
}
$order = 'is_default desc,store_id desc';
$list = $store_model->getStorePageListByAccount($condition, $page, $page_size, $order);
return $list;
} else {
//判断门店插件是否存在
$store_is_exit = addon_is_exit('store', $this->site_id);
$this->assign('store_is_exit', $store_is_exit);
$this->assign('title', $store_is_exit ? '门店' : '自提点');
$this->assign('store_type', ( new StoreModel() )->getStoreType());
$config_model = new ConfigModel();
$default_img = $config_model->getDefaultImg($this->site_id, $this->app_module)[ 'data' ][ 'value' ];
$this->assign('default_img', $default_img);
return $this->fetch('store/lists');
}
}
/**
* 添加门店
* @return mixed
*/
public function addStore()
{
$is_store = addon_is_exit('store');
if (request()->isJson()) {
$store_name = input('store_name', '');
$telphone = input('telphone', '');
$store_image = input('store_image', '');
$province_id = input('province_id', 0);
$city_id = input('city_id', 0);
$district_id = input('district_id', 0);
$community_id = input('community_id', 0);
$address = input('address', '');
$full_address = input('full_address', '');
$longitude = input('longitude', 0);
$latitude = input('latitude', 0);
$is_pickup = input('is_pickup', 0);
$is_o2o = input('is_o2o', 0);
$start_time = input('start_time', 0);
$end_time = input('end_time', 0);
$time_type = input('time_type', 0);
$time_week = input('time_week', '');
$stock_type = input('stock_type', '');
if (!empty($time_week)) {
$time_week = implode(',', $time_week);
}
$data = [
'store_name' => $store_name,
'telphone' => $telphone,
'store_image' => $store_image,
'province_id' => $province_id,
'city_id' => $city_id,
'district_id' => $district_id,
'community_id' => $community_id,
'address' => $address,
'full_address' => $full_address,
'longitude' => $longitude,
'latitude' => $latitude,
'open_date' => '全天营业',
'site_id' => $this->site_id,
'start_time' => $start_time,
'end_time' => $end_time,
'time_type' => $time_type,
'time_week' => $time_week,
'stock_type' => $stock_type,
'is_pickup' => $is_pickup,
'is_o2o' => $is_o2o,
'store_type' => input('store_type', ''),
'category_id' => input('category_id', 0),
'category_name' => input('category_name', ''),
'label_id' => input('label_id', ''),
'label_name' => input('label_name', ''),
'store_images' => input('store_images', ''),
'store_introduce' => input('store_introduce', '')
];
//判断是否开启多门店
if ($is_store == 1) {
$user_data = [
'uid' => input('uid', ''),
];
} else {
$user_data = [];
}
$store_model = new StoreModel();
$result = $store_model->addStore($data, $user_data, $is_store);
return $result;
} else {
//查询省级数据列表
$address_model = new AddressModel();
$list = $address_model->getAreaList([ ['pid', '=', 0 ], ['level', '=', 1 ] ]);
$this->assign('province_list', $list['data']);
$this->assign('is_exit', $is_store);
$this->assign('title', $is_store ? '门店' : '自提点');
$this->assign('http_type', get_http_type());
$config_model = new ConfigModel();
$mp_config = $config_model->getMapConfig($this->site_id);
$this->assign('tencent_map_key', $mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
//效验腾讯地图KEY
$check_map_key = $config_model->checkQqMapKey($mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
$this->assign('check_map_key', $check_map_key);
$express_type = ( new ExpressConfig() )->getEnabledExpressType($this->site_id);
if (isset($express_type[ 'express' ])) unset($express_type[ 'express' ]);
$this->assign('express_type', $express_type);
$this->assign('store_type', ( new StoreModel() )->getStoreType());
$user_list = ( new User() )->getUserList([ [ 'site_id', '=', $this->site_id ],['app_module', '=', 'shop'],['is_admin', '=', 0] ], 'uid,username')[ 'data' ];
$this->assign('user_list', $user_list);
$category = new Category();
$category_config = $category->getCategoryConfig($this->site_id)[ 'data' ][ 'value' ];
if ($category_config[ 'status' ]) {
$category_list = $category->getStoreCategoryList([ [ 'site_id', '=', $this->site_id ] ], 'category_id,category_name')[ 'data' ];
$this->assign('category_list', $category_list);
}
$this->assign('category_status', $category_config[ 'status' ]);
$label_list = ( new Label() )->getStoreLabelList([ [ 'site_id', '=', $this->site_id ] ], 'label_id,label_name')[ 'data' ];
$this->assign('label_list', $label_list);
return $this->fetch('store/add_store');
}
}
/**
* 编辑门店
* @return mixed
*/
public function editStore()
{
$is_exit = addon_is_exit('store');
$store_id = input('store_id', 0);
$condition = [
['site_id', '=', $this->site_id ],
['store_id', '=', $store_id ]
];
$store_model = new StoreModel();
if (request()->isJson()) {
$store_name = input('store_name', '');
$telphone = input('telphone', '');
$store_image = input('store_image', '');
$province_id = input('province_id', 0);
$city_id = input('city_id', 0);
$district_id = input('district_id', 0);
$community_id = input('community_id', 0);
$address = input('address', '');
$full_address = input('full_address', '');
$longitude = input('longitude', 0);
$latitude = input('latitude', 0);
$is_pickup = input('is_pickup', 0);
$is_o2o = input('is_o2o', 0);
$start_time = input('start_time', 0);
$end_time = input('end_time', 0);
$time_type = input('time_type', 0);
$time_week = input('time_week', '');
$stock_type = input('stock_type', '');
if (!empty($time_week)) {
$time_week = implode(',', $time_week);
}
$data = [
'store_name' => $store_name,
'telphone' => $telphone,
'store_image' => $store_image,
'province_id' => $province_id,
'city_id' => $city_id,
'district_id' => $district_id,
'community_id' => $community_id,
'address' => $address,
'full_address' => $full_address,
'longitude' => $longitude,
'latitude' => $latitude,
'start_time' => $start_time,
'end_time' => $end_time,
'time_type' => $time_type,
'time_week' => $time_week,
'stock_type' => $stock_type,
'is_pickup' => $is_pickup,
'is_o2o' => $is_o2o,
'store_type' => input('store_type', ''),
'category_id' => input('category_id', 0),
'category_name' => input('category_name', ''),
'label_id' => input('label_id', ''),
'label_name' => input('label_name', ''),
'store_images' => input('store_images', ''),
'store_introduce' => input('store_introduce', '')
];
$result = $store_model->editStore($data, $condition, [], $is_exit, 1);
return $result;
} else {
//查询省级数据列表
$address_model = new AddressModel();
$list = $address_model->getAreaList([ ['pid', '=', 0 ], ['level', '=', 1 ] ]);
$this->assign('province_list', $list['data']);
$info_result = $store_model->getStoreDetail($condition);//门店信息
$info = $info_result['data'];
if (empty($info)) $this->error('未获取到门店数据', href_url('store://shop/store/lists'));
$this->assign('info', $info);
$this->assign('store_id', $store_id);
$this->assign('is_exit', $is_exit);
$this->assign('title', $is_exit ? '门店' : '自提点');
$this->assign('http_type', get_http_type());
$config_model = new ConfigModel();
$mp_config = $config_model->getMapConfig($this->site_id);
$this->assign('tencent_map_key', $mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
//效验腾讯地图KEY
$check_map_key = $config_model->checkQqMapKey($mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
$this->assign('check_map_key', $check_map_key);
$express_type = ( new ExpressConfig() )->getEnabledExpressType($this->site_id);
if (isset($express_type[ 'express' ])) unset($express_type[ 'express' ]);
$this->assign('express_type', $express_type);
$this->assign('store_type', ( new StoreModel() )->getStoreType());
$category = new Category();
$category_config = $category->getCategoryConfig($this->site_id)[ 'data' ][ 'value' ];
if ($category_config[ 'status' ]) {
$category_list = $category->getStoreCategoryList([ [ 'site_id', '=', $this->site_id ] ], 'category_id,category_name')[ 'data' ];
$this->assign('category_list', $category_list);
}
$this->assign('category_status', $category_config[ 'status' ]);
$label_list = ( new Label() )->getStoreLabelList([ [ 'site_id', '=', $this->site_id ] ], 'label_id,label_name')[ 'data' ];
$this->assign('label_list', $label_list);
return $this->fetch('store/edit_store');
}
}
/**
* @return mixed
*/
public function operate()
{
$store_id = input('store_id', 0);
$condition = [
['site_id', '=', $this->site_id ],
['store_id', '=', $store_id ]
];
$store_model = new StoreModel();
if (request()->isJson()) {
$status = input('status', 0);
$is_pickup = input('is_pickup', 0);
$is_o2o = input('is_o2o', 0);
$start_time = input('start_time', 0);
$end_time = input('end_time', 0);
$time_type = input('time_type', 0);
$time_week = input('time_week', '');
$stock_type = input('stock_type', '');
if (!empty($time_week)) {
$time_week = implode(',', $time_week);
}
$data = [
'status' => $status,
'start_time' => $start_time,
'end_time' => $end_time,
'time_type' => $time_type,
'time_week' => $time_week,
'stock_type' => $stock_type,
'is_pickup' => $is_pickup,
'is_o2o' => $is_o2o,
'time_interval' => input('time_interval', 30),
'delivery_time' => input('delivery_time', ''),
'advance_day' => input('advance_day', 0),
'most_day' => input('most_day', 7),
'is_express' => input('is_express', 0),
'open_date_config' => input('open_date_config', '[]'),
'open_date' => input('open_date', ''),
'out_open_date_o2o_pay' => input('out_open_date_o2o_pay', 1),
'close_show' => input('close_show', 0),
'close_desc' => input('close_desc', ''),
];
$result = $store_model->editStore($data, $condition, [], 1, 1);
return $result;
}
$store_info = $store_model->getStoreDetail($condition)[ 'data' ];//门店信息
if (empty($store_info)) $this->error('未获取到门店信息');
$this->assign('info', $store_info);
$this->assign('store_id', $store_id);
$business_config = ( new StoreConfig() )->getStoreBusinessConfig($this->site_id);
$this->assign('business_config', $business_config[ 'data' ][ 'value' ]);
return $this->fetch('store/operate');
}
public function frozenStore()
{
if (request()->isJson()) {
$store_id = input('store_id', 0);
$is_frozen = input('is_frozen', 0);
$condition = [
['site_id', '=', $this->site_id ],
['store_id', '=', $store_id ]
];
$store_model = new StoreModel();
$res = $store_model->frozenStore($condition, $is_frozen);
return $res;
}
}
/**
* 重置密码
*/
public function modifyPassword()
{
if (request()->isJson()) {
$store_id = input('store_id', '');
$password = input('password', '123456');
$store_model = new StoreModel();
return $store_model->resetStorePassword($password, [ [ 'store_id', '=', $store_id ] ]);
}
}
/**
* 同城配送
*/
public function local()
{
$store_id = input('store_id', 0);
$store_model = new StoreModel();
$info_result = $store_model->getStoreInfo([ [ 'site_id', '=', $this->site_id ], [ 'store_id', '=', $store_id ] ]);//门店信息
$info = $info_result['data'];
if (empty($info)) {
$this->error([], '门店未找到');
}
$local_model = new LocalModel();
if (request()->isJson()) {
$data = [
'type' => input('type', 'default'),//配送方式 default 商家自配送 other 第三方配送
'area_type' => input('area_type', 1),//配送区域
'local_area_json' => input('local_area_json', ''),//区域及业务集合json
'time_is_open' => input('time_is_open', 0),
'time_type' => input('time_type', 0),//时间选取类型 0 全天 1 自定义
'time_week' => input('time_week', ''),
'start_time' => input('start_time', 0),
'end_time' => input('end_time', 0),
'update_time' => time(),
'is_open_step' => input('is_open_step', 0),
'start_distance' => input('start_distance', 0),
'start_delivery_money' => input('start_delivery_money', 0),
'continued_distance' => input('continued_distance', 0),
'continued_delivery_money' => input('continued_delivery_money', 0),
'start_money' => input('start_money', 0),
'delivery_money' => input('delivery_money', 0),
'area_array' => input('area_array', ''),//地域集合
'man_money' => input('man_money', ''),
'man_type' => input('man_type', ''),
'man_discount' => input('man_discount', ''),
'time_interval' => input('time_interval', 30),
'delivery_time' => input('delivery_time', ''),
'advance_day' => input('advance_day', 0),
'most_day' => input('most_day', 7)
];
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'store_id', '=', $store_id ],
];
return $local_model->editLocal($data, $condition);
} else {
$this->assign('store_detail', $info);
$local_result = $local_model->getLocalInfo([ [ 'site_id', '=', $this->site_id ], [ 'store_id', '=', $store_id ] ]);
$district_list = [];
if ($info[ 'province_id' ] > 0 && $info[ 'city_id' ] > 0) {
//查询省级数据列表
$address_model = new AddressModel();
$list = $address_model->getAreaList([ ['pid', '=', $info[ 'city_id' ] ], ['level', '=', 3 ] ]);
$district_list = $list['data'];
}
$this->assign('district_list', $district_list);
$this->assign('local_info', $local_result[ 'data' ]);
$config_model = new WebConfig();
$mp_config = $config_model->getMapConfig($this->site_id);
$this->assign('tencent_map_key', $mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
//效验腾讯地图KEY
$check_map_key = $config_model->checkQqMapKey($mp_config[ 'data' ][ 'value' ][ 'tencent_map_key' ]);
$this->assign('check_map_key', $check_map_key);
$this->assign('store_id', $store_id);
return $this->fetch('store/local');
}
}
/**
* 结算设置
*/
public function settlement()
{
$store_id = input('store_id', 0);
if (empty($store_id)) {
$this->error('未获取到门店信息');
}
$store_model = new StoreModel();
if (request()->isJson()) {
$is_settlement = input('is_settlement', 0);
if (empty($is_settlement)) {
$data = [
'is_settlement' => 0,
'settlement_rate' => 0
];
} else {
$data = [
'is_settlement' => 1,
'settlement_rate' => input('settlement_rate', 0),//跟随系统传入0独立设置大于0
'bank_type' => input('bank_type', 0),//1微信 2.支付宝 3银行卡
'bank_type_name' => input('bank_type_name', ''), //账户类型名称 微信默认为微信 支付宝默认是支付宝 银行卡需要传银行名称
'bank_user_name' => input('bank_user_name', ''), //账户所属人姓名 针对银行卡需要传入
'bank_type_account' => input('bank_type_account', ''), //具体账户信息,微信需要传入微信名称
];
}
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'store_id', '=', $store_id ],
];
$result = $store_model->editStore($data, $condition, [], 1, 1);
return $result;
}
$store_info = $store_model->getStoreInfo([ [ 'site_id', '=', $this->site_id ], [ 'store_id', '=', $store_id ] ]);//门店信息
if (empty($store_info)) $this->error('未获取到门店信息');
$this->assign('info', $store_info[ 'data' ]);
$this->assign('store_id', $store_id);
$withdraw_config = ( new StoreConfig() )->getStoreWithdrawConfig($this->site_id);
$this->assign('withdraw_config', $withdraw_config[ 'data' ][ 'value' ]);
return $this->fetch('store/settlement');
}
/**
* 微信授权二维码
*/
public function createWechatAuthQrcode()
{
$cache_key = 'wechat_auth_' . md5(uniqid(null, true));
$model = new \app\model\system\Qrcode();
$url = addon_url("wechat://api/auth/getAuthInfo", [ "cache_key" => $cache_key ]);
$qrcode = $model->createBase64Qrcode($url)['data'];
return $model->success([
'cache_key' => $cache_key,
'qrcode' => $qrcode,
]);
}
/**
* 获取微信授权数据
*/
public function getWechatAuthData()
{
$cache_key = input('cache_key', '');
$data = Cache::get($cache_key);
$model = new StoreModel();
return $model->success($data);
}
/**
* 配送员列表
*/
public function deliverLists()
{
$store_id = input('store_id', 0);
$deliver_model = new ExpressDeliver();
if (request()->isJson()) {
$page = input('page', '1');
$page_size = input('page_size', PAGE_LIST_ROWS);
$condition = [
[
'site_id', '=', $this->site_id,
],
[
'store_id', '=', $store_id,
]
];
$search_text = input('search_text', '');
if (!empty($search_text)) {
$condition[] = [ 'deliver_name', 'like', '%' . $search_text . '%' ];
}
$deliver_lists = $deliver_model->getDeliverPageLists($condition, '*', 'create_time desc', $page, $page_size);
return $deliver_lists;
} else {
$this->assign('store_id', $store_id);
return $this->fetch('store/deliverlists');
}
}
/**
* 添加配送员
*/
public function addDeliver()
{
$store_id = input('store_id', 0);
$this->assign('store_id', $store_id);
return $this->fetch('store/adddeliver');
}
/**
* 编辑配送员
*/
public function editDeliver()
{
$store_id = input('store_id', 0);
$this->assign('store_id', $store_id);
$deliver_model = new ExpressDeliver();
$deliver_id = input('deliver_id', 0);
$this->assign('deliver_id', $deliver_id);
$deliver_info = $deliver_model->getDeliverInfo($deliver_id, $this->site_id);
$this->assign('deliver_info', $deliver_info[ 'data' ]);
return $this->fetch('store/editdeliver');
}
/**
* 选择门店
* @return mixed
*/
public function selectStore()
{
$store_list = ( new StoreModel() )->getStoreList([ [ 'site_id', '=', $this->site_id ] ], 'store_id,store_name,status,address,full_address,is_frozen');
$this->assign('store_list', $store_list[ 'data' ]);
$store_id = explode(',', input('store_id', ''));
$this->assign('store_id', $store_id);
return $this->fetch('store/select');
}
/**
* 门店主页装修
*/
public function diy()
{
$data = [
'site_id' => $this->site_id,
'name' => 'DIY_STORE'
];
$edit_view = event('DiyViewEdit', $data, true);
return $edit_view;
}
/**
* 门店分类
* @return mixed
*/
public function category()
{
$category = new Category();
if (request()->isJson()) {
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($search_text)) $condition[] = [ 'category_name', 'like', "%{$search_text}%" ];
return $category->getStoreCategoryPageList($condition, $page, $page_size);
}
$config = $category->getCategoryConfig($this->site_id)[ 'data' ][ 'value' ];
$this->assign('status', $config[ 'status' ]);
return $this->fetch('store/category');
}
/**
* 添加分类
* @return array
*/
public function addCategory()
{
if (request()->isJson()) {
$data = [
'category_name' => input('category_name', ''),
'site_id' => $this->site_id
];
return ( new Category() )->addStoreCategory($data);
}
}
/**
* 编辑分类
* @return array
*/
public function editCategory()
{
if (request()->isJson()) {
$category_id = input('category_id', 0);
$data = [
'category_name' => input('category_name', ''),
'sort' => input('sort', 0)
];
return ( new Category() )->editStoreCategory($data, [ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ]);
}
}
/**
* 删除分类
* @return array
*/
public function deleteCategory()
{
if (request()->isJson()) {
$category_id = input('category_id', 0);
return ( new Category() )->deleteStoreCategory([ [ 'category_id', 'in', $category_id ], [ 'site_id', '=', $this->site_id ] ]);
}
}
/**
* 门店分类是否启用
*/
public function categoryConfig()
{
if (request()->isJson()) {
$status = input('status', 0);
return ( new Category() )->setCategoryConfig([ 'status' => $status ], $this->site_id);
}
}
/**
* 门店标签
* @return mixed
*/
public function tag()
{
if (request()->isJson()) {
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$search_text = input('search_text', '');
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($search_text)) $condition[] = [ 'label_name', 'like', "%{$search_text}%" ];
return ( new Label() )->getStoreLabelPageList($condition, $page, $page_size);
}
return $this->fetch('store/tag');
}
/**
* 添加标签
* @return array
*/
public function addLabel()
{
if (request()->isJson()) {
$data = [
'label_name' => input('label_name', ''),
'site_id' => $this->site_id,
'create_time' => time()
];
return ( new Label() )->addStoreLabel($data);
}
}
/**
* 编辑标签
* @return array
*/
public function editLabel()
{
if (request()->isJson()) {
$label_id = input('label_id', 0);
$data = [
'label_name' => input('label_name', ''),
'sort' => input('sort', 0)
];
return ( new Label() )->editStoreLabel($data, [ [ 'label_id', '=', $label_id ], [ 'site_id', '=', $this->site_id ] ]);
}
}
/**
* 删除标签
* @return array
*/
public function deleteLabel()
{
if (request()->isJson()) {
$label_id = input('label_id', 0);
return ( new Label() )->deleteStoreLabel([ [ 'label_id', '=', $label_id ], [ 'site_id', '=', $this->site_id ] ]);
}
}
/**
* 门店标签选择框
* @return mixed
*/
public function labelSelect()
{
if (request()->isJson()) {
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$search_text = input('search_text', '');
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($search_text)) $condition[] = [ 'label_name', 'like', "%{$search_text}%" ];
return ( new Label() )->getStoreLabelPageList($condition, $page, $page_size);
} else {
$select_id = input('select_id', '');
$this->assign('select_id', $select_id);
return $this->fetch('store/label_select');
}
}
/**
* 修改排序
*/
public function modifySort()
{
if (request()->isJson()) {
$sort = input('sort', 0);
$label_id = input('label_id', 0);
$label_model = new Label();
$res = $label_model->modifySort($sort, $label_id, $this->site_id);
return $res;
}
}
}

View File

@@ -0,0 +1,202 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\shop\controller;
use addon\mobileshop\model\Config as ConfigModel;
use addon\store\model\StoreWithdraw;
use addon\wechatpay\model\Config as WechatPayConfig;
use app\shop\controller\BaseShop;
/**
* 门店提现控制器
*/
class Withdraw extends BaseShop
{
/**
* 转账
*/
public function transferFinish()
{
if (request()->isJson()) {
$withdraw_id = input('withdraw_id', 0);
$voucher_img = input('voucher_img', '');
$voucher_desc = input('voucher_desc', '');
$withdraw_model = new StoreWithdraw();
$data = array (
'withdraw_id' => $withdraw_id,
'site_id' => $this->site_id,
'voucher_desc' => $voucher_desc,
'voucher_img' => $voucher_img,
);
$result = $withdraw_model->transferFinish($data);
return $result;
}
}
/**
* 门店提现列表
* @return mixed
*/
public function lists()
{
$withdraw_model = new StoreWithdraw();
if (request()->isJson()) {
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$withdraw_no = input('withdraw_no', '');
$start_date = input('start_date', '');
$end_date = input('end_date', '');
$status = input('status', 'all');//提现状态
$transfer_type = input('transfer_type', '');//提现转账方式
$store_id = input('store_id', 0);//门店
$transfer_start_date = input('transfer_start_date', '');
$transfer_end_date = input('transfer_end_date', '');
$settlement_type = input('settlement_type', '');
$condition = [ [ 'sw.site_id', '=', $this->site_id ] ];
if (!empty($withdraw_no)) {
$condition[] = [ 'withdraw_no', 'like', '%' . $withdraw_no . '%' ];
}
if (!empty($transfer_type)) {
$condition[] = [ 'transfer_type', '=', $transfer_type ];
}
if ($store_id > 0) {
$condition[] = [ 'sw.store_id', '=', $store_id ];
}
if (!empty($settlement_type)) {
$condition[] = [ 'settlement_type', '=', $settlement_type ];
}
if ($status != 'all') {
$condition[] = [ 'sw.status', '=', $status ];
}
if ($start_date != '' && $end_date != '') {
$condition[] = [ 'apply_time', 'between', [ strtotime($start_date), strtotime($end_date) ] ];
} else if ($start_date != '' && $end_date == '') {
$condition[] = [ 'apply_time', '>=', strtotime($start_date) ];
} else if ($start_date == '' && $end_date != '') {
$condition[] = [ 'apply_time', '<=', strtotime($end_date) ];
}
if ($transfer_start_date != '' && $transfer_end_date != '') {
$condition[] = [ 'transfer_time', 'between', [ strtotime($transfer_start_date), strtotime($transfer_end_date) ] ];
} else if ($transfer_start_date != '' && $transfer_end_date == '') {
$condition[] = [ 'transfer_time', '>=', strtotime($transfer_start_date) ];
} else if ($transfer_start_date == '' && $transfer_end_date != '') {
$condition[] = [ 'transfer_time', '<=', strtotime($transfer_end_date) ];
}
$order = 'apply_time desc';
$join = [
[ 'store s', 's.store_id = sw.store_id', 'left' ]
];
return $withdraw_model->getStoreWithdrawPageList($condition, $page, $page_size, $order, 'sw.*,s.telphone', 'sw', $join);
} else {
$this->assign('settlement_type_list', $withdraw_model->settlement_type);
$transfer_type_list = $withdraw_model->getTransferType($this->site_id);
$this->assign('transfer_type_list', $transfer_type_list);
$store_model = new \app\model\store\Store();
$store_list = $store_model->getStoreList([ [ 'site_id', '=', $this->site_id ] ])[ 'data' ] ?? [];
$this->assign('store_list', $store_list);
$stat_model = new \addon\store\model\Stat();
$stat_condition = array (
[ 'site_id', '=', $this->site_id ]
);
$total_account = $stat_model->getStoreAccountSum($stat_condition, 'account')[ 'data' ] ?? 0;
$total_account_apply = $stat_model->getStoreAccountSum($stat_condition, 'account_apply')[ 'data' ] ?? 0;
$total_account_withdraw = $stat_model->getStoreAccountSum($stat_condition, 'account_withdraw')[ 'data' ] ?? 0;
$this->assign('stat', [
'total_account' => $total_account,
'total_account_apply' => $total_account_apply,
'total_account_withdraw' => $total_account_withdraw,
]);
$this->assign('status_list', $withdraw_model->status);
$config_model = new WechatPayConfig();
$config = $config_model->getPayConfig($this->site_id)[ 'data' ][ 'value' ];;
$transfer_v3_type = $config['transfer_type'] == 'v3' && $config['transfer_v3_type'] == $config_model::TRANSFER_V3_TYPE_USER ;
$this->assign("transfer_v3_type",$transfer_v3_type);
return $this->fetch('withdraw/lists');
}
}
/**
* 提现详情
* @return mixed
*/
public function detail()
{
$withdraw_id = input('withdraw_id', 0);
$withdraw_model = new StoreWithdraw();
$withdraw_info = $withdraw_model->detail([ 'site_id' => $this->site_id, 'withdraw_id' => $withdraw_id ])[ 'data' ] ?? [];
if (empty($withdraw_info))
$this->error('找不到此项提现记录!');
$this->assign('withdraw_info', $withdraw_info);
return $this->fetch('withdraw/detail');
}
/**
* 同意
* @return array
*/
public function agree()
{
if (request()->isJson()) {
$withdraw_id = input('withdraw_id', 0);
$withdraw_model = new StoreWithdraw();
$params = array (
'site_id' => $this->site_id,
'withdraw_id' => $withdraw_id,
'status' => 0
);
$result = $withdraw_model->agree($params);
return $result;
}
}
/**
* 拒绝
* @return array
*/
public function refuse()
{
if (request()->isJson()) {
$withdraw_id = input('withdraw_id', 0);
$refuse_reason = input('refuse_reason', '');
$withdraw_model = new StoreWithdraw();
$params = array (
'site_id' => $this->site_id,
'withdraw_id' => $withdraw_id,
'refuse_reason' => $refuse_reason
);
$result = $withdraw_model->refuse($params);
return $result;
}
}
/**
* 转账
*/
public function transfer()
{
if (request()->isJson()) {
$withdraw_id = input('withdraw_id', 0);
$withdraw_model = new StoreWithdraw();
$result = $withdraw_model->transfer($withdraw_id);
return $result;
}
}
}

View File

@@ -0,0 +1,241 @@
<style>
.layui-card-body .content{width: 33.3%;}
.layui-layout-admin .screen{margin-bottom: 15px;}
.account-data-sum{padding-left:10px;}
</style>
<div class="layui-card panel-content card-common card-brief">
<div class="layui-card-header simple">
<span class="card-title">账户概况</span>
</div>
<div class="layui-card-body">
<div class="content">
<p class="title">待结算(元)</p>
<p class="money">{$stat.total_account}</p>
</div>
<div class="content">
<p class="title">已结算(元)</p>
<p class="money">{$stat.total_account_withdraw}</p>
</div>
<div class="content">
<p class="title">结算中(元)</p>
<p class="money">{$stat.total_account_apply}</p>
</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">
<select name="store_id" lay-filter="store_id">
<option value="">全部</option>
{foreach name="$store_list" item="store"}
<option value="{$store['store_id']}">{$store['store_name']}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">来源方式</label>
<div class="layui-input-inline">
<select name="from_type">
<option value="">全部</option>
{foreach $from_type_list as $from_type_k=> $from_type_v}
<option value="{$from_type_k}">{$from_type_v.type_name}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">发生时间</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="start_date" id="start_time" placeholder="请输入开始时间" autocomplete="off" readonly>
</div>
<div class="layui-input-inline split">-</div>
<div class="layui-input-inline end-time">
<input type="text" class="layui-input" name="end_date" id="end_time" placeholder="请输入结束时间" autocomplete="off" readonly>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">备注</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="remark" placeholder="请输入开始时间" autocomplete="off">
</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>
<button class="layui-btn layui-btn-primary" lay-submit lay-filter="export">导出</button>
<button class="layui-btn layui-btn-primary" onclick="exportList()">导出记录</button>
<span class="account-data-sum">账户汇总:<span id="account_data_sum">0.00</span></span>
</div>
</form>
</div>
</div>
<!-- 列表 -->
<table id="withdraw_list" lay-filter="withdraw_list"></table>
<script type="text/html" id="status">
{{# if(d.status == 0){ }}
<div class="layui-elip" style="color: red">
{{# }else if(d.status == 1){ }}
<div class="layui-elip" style="color: blue">
{{# }else if(d.status == 2){ }}
<div class="layui-elip" style="color: green">
{{# }else if(d.status == -1){ }}
<div class="layui-elip" style="color: gray">
{{# } }}
{{ d.status_name }}</div>
</script>
<!--操作-->
<script type="text/html" id="operation">
<div class="table-btn">
<a class="layui-btn" lay-event="detail">查看</a>
</div>
</script>
<script>
var table,upload;
layui.use(['form', 'laydate','laytpl'], function() {
var form = layui.form,
laydate = layui.laydate,
currentDate = new Date(),
laytpl = layui.laytpl,
minDate = "";
form.render();
currentDate.setDate(currentDate.getDate() - 7);
//开始时间
laydate.render({
elem: '#start_time',
type: 'datetime'
});
//结束时间
laydate.render({
elem: '#end_time',
type: 'datetime'
})
/**
* 表格加载
*/
table = new Table({
elem: '#withdraw_list',
url: ns.url("store://shop/account/lists"),
beforeParseData: function (res){
$("#account_data_sum").html(Number(res.data.account_data_sum).toFixed(2));
},
cols: [
[{
field: 'store_name',
title: '门店',
width: '12%',
unresize: 'false',
},{
field: 'type_name',
title: '来源方式',
width: '10%',
unresize: 'false',
}, {
field: 'account_data',
title: '记录金额',
width: '10%',
unresize: 'false',
}, {
title: '发生时间',
unresize: 'false',
width: '16%',
templet: function(data) {
return ns.time_to_date(data.create_time);
}
}, {
field: 'remark',
title: '备注',
width: '44%',
unresize: 'false',
templet: function(data) {
return '<div class="text">'+ data.remark +'</div>'
}
},{
title: '操作',
toolbar: '#operation',
unresize: 'false',
align:'right'
}]
]
});
/**
* 搜索功能
*/
form.on('submit(search)', function(data) {
table.reload({
page: {
curr: 1
},
where: data.field
});
return false;
});
/**
* 监听工具栏操作
*/
table.tool(function(obj) {
var data = obj.data;
switch(obj.event){
case 'detail':
detail(data);
break;
}
});
form.on('submit(export)', function(data){
$.ajax({
type: 'post',
dataType: 'json',
url: ns.url("store://shop/account/addexport"),
data: data.field,
success: function (res) {
console.log(res);
}
})
setTimeout(()=>{
window.open(ns.href("store://shop/account/exportlist"));
}, 500);
return false;
});
});
/**
* 查看详情
*/
function detail(data) {
switch(data.from_type){
case 'order':
window.open(ns.href("shop/order/detail",{order_id:data.related_id}));
break;
case 'refund':
window.open(ns.href("shop/orderrefund/detail",{order_goods_id:data.related_id}));
break;
case 'withdraw':
window.open(ns.href("store://shop/withdraw/detail",{withdraw_id:data.related_id}));
break;
}
}
function exportList(){
window.open(ns.href("store://shop/account/exportlist"));
}
</script>

View File

@@ -0,0 +1,316 @@
<style>
.layui-form-label{width: 160px;}
.layui-form-label + .layui-input-block{margin-left: 160px;}
.word-aux{margin-left: 160px;}
.form-row{margin-left: 160px;}
.confirm-popup.prompt-block span{height:18px;}
.confirm-popup.prompt-block .prompt {display: inline-block;width: auto;margin-left: 5px;}
.confirm-popup.prompt-block .prompt-box{width: 230px;left: 42px;}
.confirm-popup.prompt-block .prompt img{width: 200px;}
</style>
<div class="layui-form">
<div class="layui-card card-common card-brief">
<div class="layui-card-header">
<span class="card-title">运营设置</span>
</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">门店运营模式:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="radio" name="store_business" value="shop" title="平台运营模式" {if $business_config.store_business eq 'shop'}checked{/if} />
<input type="radio" name="store_business" value="store" title="连锁门店模式" {if $business_config.store_business eq 'store'}checked{/if} />
</div>
</div>
<div class="word-aux">
<p>平台运营模式:展示平台整体页面,商品全部展示,考虑门店库存</p>
<p>连锁门店模式:只会展示门店独立页面,商品查询只需查询对应门店</p>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">门店切换:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="radio" name="is_allow_change" value="1" title="允许用户切换门店" {if $business_config.is_allow_change eq 1}checked{/if} />
<input type="radio" name="is_allow_change" value="0" title="禁止用户切换门店" {if $business_config.is_allow_change eq 0}checked{/if} />
</div>
</div>
<div class="word-aux">禁止切换门店,会锁定距离用户最近的门店,定位失败进入默认总店</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">门店确认弹窗:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="radio" name="confirm_popup_control" value="1" title="开启" {if $business_config.confirm_popup_control eq 1}checked{/if} />
<input type="radio" name="confirm_popup_control" value="0" title="关闭" {if $business_config.confirm_popup_control eq 0}checked{/if} />
</div>
</div>
<div class="word-aux prompt-block confirm-popup">
<span>开启后,每次进入门店时弹窗提示当前门店信息</span>
<div class="prompt">
<span class="text-color">示例</span>
<div class="growth-box reason-box reason-growth prompt-box">
<div class="prompt-con">
<img src="STORE_IMG/store_confirm_popup_preview.png">
</div>
</div>
</div>
</div>
</div>
<div class="layui-form-item" style="display: none;">
<label class="layui-form-label">功能设置:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="checkbox" name="store_auth" lay-filter="store_auth" value="config" title="是否允许门店设置" lay-skin="primary" {if strpos($business_config['store_auth'], 'config') !== false}checked{/if} />
<input type="checkbox" name="store_auth" lay-filter="store_auth" value="balance" title="是否允许调整会员余额" lay-skin="primary" {if strpos($business_config['store_auth'], 'balance') !== false}checked{/if} />
<input type="checkbox" name="store_auth" lay-filter="store_auth" value="point" title="是否允许调整会员积分" lay-skin="primary" {if strpos($business_config['store_auth'], 'point') !== false}checked{/if} />
<input type="checkbox" name="store_auth" lay-filter="store_auth" value="coupon" title="是否允许发放优惠券" lay-skin="primary" {if strpos($business_config['store_auth'], 'coupon') !== false}checked{/if} />
<input type="checkbox" name="store_auth" lay-filter="store_auth" value="adjust" title="是否允许会员改价" lay-skin="primary" {if strpos($business_config['store_auth'], 'adjust') !== false}checked{/if} />
</div>
</div>
</div>
</div>
</div>
<div class="layui-card card-common card-brief">
<div class="layui-card-header">
<span class="card-title">结算设置</span>
</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">是否需要结算:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="radio" name="is_settlement" lay-filter="is_settlement" value="0" title="总部直营,无需结算" {if $withdraw_config.is_settlement eq 0}checked{/if} />
<input type="radio" name="is_settlement" lay-filter="is_settlement" value="1" title="总部收款,周期性自动结算" {if $withdraw_config.is_settlement eq 1}checked{/if} />
<input type="radio" name="is_settlement" lay-filter="is_settlement" value="2" title="总部收款,门店申请结算" {if $withdraw_config.period_type eq 4}checked{/if} />
</div>
</div>
</div>
<div class="layui-form-item period-type layui-hide">
<label class="layui-form-label">结算周期:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="radio" name="period_type" value="1" title="每日结算" {if $withdraw_config.period_type eq 1 || $withdraw_config.period_type eq 4}checked{/if} />
<input type="radio" name="period_type" value="2" title="每周结算" {if $withdraw_config.period_type eq 2}checked{/if} />
<input type="radio" name="period_type" value="3" title="每月结算" {if $withdraw_config.period_type eq 3}checked{/if} />
</div>
</div>
</div>
<div class="layui-form-item settlement-rate">
<label class="layui-form-label">门店抽成比率:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="number" name="settlement_rate" lay-verify="positivEinteger" placeholder="0" class="layui-input len-short" autocomplete="off" value="{$withdraw_config.settlement_rate}">
</div>
<div class="layui-form-mid layui-word-aux">%</div>
</div>
<div class="word-aux">门店抽成比率需是0-100,且保存两位小数</div>
</div>
<div class="layui-form-item is-withdraw">
<label class="layui-form-label">是否提现:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="checkbox" name="is_withdraw" value="1" lay-filter="third_party" lay-skin="switch" {if $withdraw_config.is_withdraw eq 1}checked{/if}>
</div>
</div>
</div>
{notempty name="$pay_type_list"}
<div class="layui-form-item settlement-pay-type">
<label class="layui-form-label">结算付款控制:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
{foreach name="$pay_type_list" item="vo" key="k"}
<input type="checkbox" name="settlement_pay_type" value="{$k}" title="{$vo}" lay-skin="primary" {if strpos($withdraw_config['settlement_pay_type'], $k) !== false}checked{/if} />
{/foreach}
</div>
</div>
</div>
{/notempty}
<div class="layui-form-item settlement-cost">
<label class="layui-form-label">结算成本控制:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="checkbox" name="settlement_cost" lay-filter="settlement_cost" value="coupon" title="结算优惠券" lay-skin="primary" {if strpos($withdraw_config['settlement_cost'], 'coupon') !== false}checked{/if} />
<input type="checkbox" name="settlement_cost" lay-filter="settlement_cost" value="point" title="结算积分抵扣" lay-skin="primary" {if strpos($withdraw_config['settlement_cost'], 'point') !== false}checked{/if} />
<input type="checkbox" name="settlement_cost" lay-filter="settlement_cost" value="fenxiao_commission" title="结算扣除佣金" lay-skin="primary" {if strpos($withdraw_config['settlement_cost'], 'fenxiao_commission') !== false}checked{/if} />
</div>
</div>
</div>
<div class="layui-form-item is-audit">
<label class="layui-form-label">是否提现审核:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="checkbox" name="is_audit" value="1" lay-skin="switch" {if $withdraw_config.is_audit eq 1}checked{/if}>
</div>
</div>
</div>
<div class="layui-form-item is-audit">
<label class="layui-form-label">是否自动转账:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="checkbox" name="is_auto_transfer" value="1" lay-skin="switch" {if $withdraw_config.is_auto_transfer eq 1}checked{/if}>
</div>
</div>
<div class="word-aux">只有微信和支付宝支付支持自动转账</div>
</div>
<div class="layui-form-item withdraw-least">
<label class="layui-form-label">最低提现金额:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="number" name="withdraw_least" lay-verify="withdrawLeast" placeholder="0" class="layui-input len-short" autocomplete="off" value="{$withdraw_config.withdraw_least}">
</div>
</div>
<div class="word-aux">最低提现金额必须大于0</div>
</div>
</div>
</div>
<div class="form-row">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</div>
<script>
var form,
repeat_flag = false, //防重复标识
submitIsSettlement;
layui.use(['form'], function() {
form = layui.form;
form.render();
initFn();
// 是否出现结算周期
form.on('radio(is_settlement)', function(data){
submitIsSettlement = data.value;
if(parseFloat(data.value) == 0){
$(".settlement-rate").addClass("layui-hide");
$(".period-type").addClass("layui-hide");
$('.settlement-pay-type').addClass("layui-hide");
$(".settlement-cost").addClass("layui-hide");
$(".is-withdraw").addClass("layui-hide");
$(".withdraw-least").addClass("layui-hide");
$(".is-audit").addClass("layui-hide");
}else if(parseFloat(data.value) == 1){
$(".is-withdraw").addClass("layui-hide");
$(".settlement-rate").removeClass("layui-hide");
$(".period-type").removeClass("layui-hide");
$('.settlement-pay-type').removeClass("layui-hide");
$(".settlement-cost").removeClass("layui-hide");
$(".withdraw-least").addClass("layui-hide");
$(".is-audit").removeClass("layui-hide");
}else if(parseFloat(data.value) == 2){
$('.settlement-pay-type').removeClass("layui-hide");
$(".settlement-cost").removeClass("layui-hide");
$(".is-withdraw").removeClass("layui-hide");
$(".settlement-rate").removeClass("layui-hide");
$(".period-type").addClass("layui-hide");
$(".withdraw-least").removeClass("layui-hide");
$(".is-audit").removeClass("layui-hide");
}
});
// 验证正整数
form.verify({
positivEinteger: function(value) {
if (parseFloat(value) < 0 || parseFloat(value) > 100) {
return '请输入0-100之间的数';
}
if (value.split(".").length > 1) {
let len = value.split(".")[1].length;
if (len > 2) {
return '门店抽成比率最多两位小数';
}
}
},
withdrawLeast: function(value){
if(value <= 0){
return '最低提现金额必须大于0';
}
if (value.split(".").length > 1) {
let len = value.split(".")[1].length;
if (len > 2) {
return '最低提现金额最多保留两位小数';
}
}
}
});
form.on('submit(save)', function(data) {
if (repeat_flag) return;
repeat_flag = true;
let field = data.field;
if($('input[name="settlement_pay_type"]').length) {
field.settlement_pay_type = [];
$('input[name="settlement_pay_type"]:checked').each(function () {
field.settlement_pay_type.push($(this).val());
});
field.settlement_pay_type = field.settlement_pay_type.toString();
}
field.settlement_cost = [];
$('input[name="settlement_cost"]:checked').each(function () {
field.settlement_cost.push($(this).val());
});
field.settlement_cost = field.settlement_cost.toString();
field.store_auth = [];
$('input[name="store_auth"]:checked').each(function () {
field.store_auth.push($(this).val());
});
field.store_auth = field.store_auth.toString();
if(submitIsSettlement == 2){
field.is_settlement = 1;
field.period_type = 4;
}
$.ajax({
type: 'POST',
dataType: 'JSON',
url: ns.url("store://shop/config/index"),
data: field,
success: function(res) {
layer.msg(res.message);
repeat_flag = false;
}
});
});
});
function initFn(){
// 是否展示结算周期
var isSettlement = '{$withdraw_config.is_settlement}';
var periodType = '{$withdraw_config.period_type}';
if(parseFloat(isSettlement) == 0){
$(".settlement-rate").addClass("layui-hide");
$(".period-type").addClass("layui-hide");
$('.settlement-pay-type').addClass("layui-hide");
$(".settlement-cost").addClass("layui-hide");
$(".is-withdraw").addClass("layui-hide");
}else if(parseFloat(isSettlement) == 1){
$(".is-withdraw").addClass("layui-hide");
$(".settlement-rate").removeClass("layui-hide");
$(".period-type").removeClass("layui-hide");
$('.settlement-pay-type').removeClass("layui-hide");
$(".settlement-cost").removeClass("layui-hide");
$(".is-audit").removeClass("layui-hide");
$(".withdraw-least").addClass("layui-hide");
}
if(parseFloat(periodType) == 4){
submitIsSettlement = 2;
$('.settlement-pay-type').removeClass("layui-hide");
$(".settlement-cost").removeClass("layui-hide");
$(".is-withdraw").removeClass("layui-hide");
$(".settlement-rate").removeClass("layui-hide");
$(".period-type").addClass("layui-hide");
$(".is-audit").removeClass("layui-hide");
$(".withdraw-least").removeClass("layui-hide");
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Some files were not shown because too many files have changed in this diff Show More