- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
<?php
namespace app\admin\controller\shopro;
use think\Db;
use addons\shopro\library\Tree;
use app\admin\model\shopro\Category as CategoryModel;
/**
* 商品分类
*/
class Category extends Common
{
protected $noNeedRight = ['select', 'goodsSelect'];
public function _initialize()
{
parent::_initialize();
$this->model = new CategoryModel;
}
/**
* 服务保障列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$categories = $this->model->sheepFilter()->where('parent_id', 0)->order('weigh', 'desc')->order('id', 'desc')->select();
$this->success('获取成功', null, $categories);
}
/**
* 添加服务保障
*
* @return \think\Response
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'name', 'style', 'description', 'weigh', 'categories'
]);
$this->svalidate($params, ".add");
$categories = json_decode($params['categories'], true);
Db::transaction(function () use ($params, $categories) {
$this->model->allowField(true)->save($params);
//递归处理分类数据
$this->createOrEditCategory($categories, $this->model->id);
});
$this->success('保存成功');
}
/**
* 服务保障详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$category = $this->model->where('parent_id', 0)->where('id', $id)->find();
if (!$category) {
$this->error(__('No Results were found'));
}
$categories = $this->model->with('children.children')->where('parent_id', $category->id)->order('weigh', 'desc')->order('id', 'desc')->select();
$this->success('获取成功', null, ['category' => $category, 'categories' => $categories]);
}
/**
* 修改商品分类
*
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isPost()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'name', 'style', 'description', 'weigh', 'categories'
]);
$this->svalidate($params, ".edit");
$categories = json_decode($params['categories'], true);
$category = $this->model->where('parent_id', 0)->where('id', $id)->find();
if (!$category) {
$this->error(__('No Results were found'));
}
Db::transaction(function () use ($category, $params, $categories) {
$category->allowField(true)->save($params);
//递归处理分类数据
$this->createOrEditCategory($categories, $category->id);
});
$this->success('更新成功');
}
/**
* 删除服务标签
*
* @param string $id 要删除的服务保障列表
* @return void
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->with('children')->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
if ($item->children) {
$this->error('请先删除子分类');
}
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
/**
* 获取所有服务列表
*
* @return \think\Response
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$categories = (new Tree(function () {
// 组装搜索条件,排序等
return $this->model->field("id, name, parent_id, status, weigh")->normal()
->order('weigh', 'desc')->order('id', 'asc');
}))->getTree(0);
$this->success('获取成功', null, $categories);
}
/**
* 商品列表左边分类
*
* @return void
*/
public function goodsSelect()
{
$categories = $this->model->with(['children'])
->where('parent_id', 0)->order('weigh', 'desc')->order('id', 'desc')->select();
$this->success('获取成功', null, $categories);
}
private function createOrEditCategory($categories, $parent_id)
{
foreach ($categories as $key => $data) {
$data['parent_id'] = $parent_id;
if (isset($data['id']) && $data['id']) {
$category = $this->model->find($data['id']);
if (!$category) {
$this->error(__('No Results were found'));
}
if (isset($data['deleted']) && $data['deleted'] == 1) {
$category->delete();
} else {
$category->name = $data['name'];
$category->parent_id = $data['parent_id'];
$category->image = $data['image'];
$category->description = $data['description'] ?? null;
$category->status = $data['status'];
$category->weigh = $data['weigh'];
$category->save();
}
} else {
if (!isset($data['deleted']) || !$data['deleted']) {
$category = new CategoryModel;
$category->name = $data['name'];
$category->parent_id = $data['parent_id'];
$category->image = $data['image'];
$category->description = $data['description'] ?? null;
$category->status = $data['status'];
$category->weigh = $data['weigh'];
$category->save();
$data['id'] = $category->id;
}
}
if (isset($data['children']) && !empty($data['children']) && isset($data['id'])) {
$this->createOrEditCategory($data['children'], $data['id']);
}
}
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace app\admin\controller\shopro;
use app\common\controller\Backend;
use addons\shopro\controller\traits\Util;
use addons\shopro\controller\traits\UnifiedToken;
/**
* shopro 基础控制器
*/
class Common extends Backend
{
use Util, UnifiedToken;
protected $model = null;
public function _initialize()
{
parent::_initialize();
if (check_env('yansongda', false)) {
set_addon_config('epay', ['version' => 'v3'], false);
}
$is_pro = check_env('commission', false);
\think\View::share('is_pro', $is_pro);
$this->assignconfig("is_pro", $is_pro);
}
}

View File

@@ -0,0 +1,320 @@
<?php
namespace app\admin\controller\shopro;
use app\admin\model\shopro\Config as ShoproConfig;
class Config extends Common
{
protected $noNeedRight = ['index', 'platformStatus', 'getPlatformUrl'];
public function index()
{
$configList = [
[
'label' => '基本信息',
'name' => 'shopro/config/basic',
'status' => $this->auth->check('shopro/config/basic')
],
[
'label' => '用户配置',
'name' => 'shopro/config/user',
'status' => $this->auth->check('shopro/config/user')
],
[
'label' => '平台配置',
'name' => 'shopro/config/platform',
'status' => $this->auth->check('shopro/config/platform')
],
[
'label' => '订单配置',
'name' => 'shopro/config/order',
'status' => $this->auth->check('shopro/config/order')
],
[
'label' => '商品配置',
'name' => 'shopro/config/goods',
'status' => $this->auth->check('shopro/config/goods')
],
[
'label' => '物流配置',
'name' => 'shopro/config/dispatch',
'status' => $this->auth->check('shopro/config/dispatch')
],
[
'label' => '充值提现',
'name' => 'shopro/config/rechargewithdraw',
'status' => $this->auth->check('shopro/config/rechargewithdraw')
],
[
'label' => '分销配置',
'name' => 'shopro/config/commission',
'status' => $this->auth->check('shopro/config/commission')
],
[
'label' => '支付配置',
'name' => 'shopro/pay_config',
'status' => $this->auth->check('shopro/pay_config')
],
[
'label' => '客服配置',
'name' => 'shopro/config/chat',
'status' => $this->auth->check('shopro/config/chat')
],
[
'label' => 'Redis配置',
'name' => 'shopro/config/redis',
'status' => $this->auth->check('shopro/config/redis')
]
];
$this->assignconfig("configList", $configList);
return $this->view->fetch();
}
/**
* 基本配置
*/
public function basic()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.basic', false);
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('shop.basic', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
/**
* 用户默认配置
*/
public function user()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.user', false);
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('shop.user', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
/**
* 物流配置
*/
public function dispatch()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.dispatch', false);
$configs['callback'] = $this->request->domain() . '/addons/shopro/order.express/push';
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('shop.dispatch', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
/**
* 平台状态
*/
public function platformStatus()
{
$status = [
'H5' => ShoproConfig::getConfigs('shop.platform.H5.status', false),
'App' => ShoproConfig::getConfigs('shop.platform.App.status', false),
'WechatMiniProgram' => ShoproConfig::getConfigs('shop.platform.WechatMiniProgram.status', false),
'WechatOfficialAccount' => ShoproConfig::getConfigs('shop.platform.WechatOfficialAccount.status', false),
];
$this->success('操作成功', null, $status);
}
/**
* 平台配置
*/
public function platform($platform)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
if (!in_array($platform, ['App', 'H5', 'WechatMiniProgram', 'WechatOfficialAccount'])) {
$this->error('平台不支持');
}
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.platform.' . $platform, false);
} elseif ('POST' === $this->request->method()) {
$params = $this->request->param();
if (!isset($params['share']['methods'])) {
$params['share']['methods'] = [];
}
if (!isset($params['payment']['methods'])) {
$params['payment']['methods'] = [];
}
$configs = ShoproConfig::setConfigs('shop.platform.' . $platform, $params);
}
$this->success('操作成功', null, $configs);
}
public function commission()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.commission', false);
} elseif ('POST' === $this->request->method()) {
check_env('commission');
$params = $this->request->param();
$configs = ShoproConfig::setConfigs('shop.commission', $params);
}
$this->success('操作成功', null, $configs);
}
/**
* 订单配置
*/
public function order()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.order', false);
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('shop.order', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
/**
* 商品配置
*/
public function goods()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.goods', false);
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('shop.goods', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
/**
* 充值提现配置
*/
public function rechargeWithdraw()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('shop.recharge_withdraw', false);
} elseif ('POST' === $this->request->method()) {
$params = $this->request->param();
if (!isset($params['recharge']['methods'])) {
$params['recharge']['methods'] = [];
}
if (!isset($params['recharge']['quick_amounts'])) {
$params['recharge']['quick_amounts'] = [];
}
if (!isset($params['withdraw']['methods'])) {
$params['withdraw']['methods'] = [];
}
$configs = ShoproConfig::setConfigs('shop.recharge_withdraw', $params);
}
$this->success('操作成功', null, $configs);
}
/**
* 客服配置
*/
public function chat()
{
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('chat', false);
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('chat', $this->request->param());
// 存文件
file_put_contents(
ROOT_PATH . 'application' . DS . 'extra' . DS . 'chat.php',
'<?php' . "\n\nreturn " . short_var_export($this->request->param(), true) . ";"
);
}
$this->success('操作成功', null, $configs);
}
/**
* redis 配置
*/
public function redis()
{
if ('GET' === $this->request->method()) {
$default = [
'host' => '127.0.0.1', // redis 主机地址
'password' => '', // redis 密码
'port' => 6379, // redis 端口
'select' => 1, // redis 数据库
'timeout' => 0, // redis 超时时间
'persistent' => false, // redis 持续性,连接复用
];
$redis = \think\Config::get('redis');
$redis['empty_password'] = 0;
$redis['password'] = ''; // 隐藏密码
$configs = $redis ? array_merge($default, $redis) : $default;
} elseif ('POST' === $this->request->method()) {
operate_filter();
$configs = $this->request->param();
$empty_password = (int)$configs['empty_password']; // 是否设置空密码
unset($configs['empty_password']);
if (isset($configs['password']) && empty($configs['password'])) {
$redis = \think\Config::get('redis');
// 不修改密码,保持为原始值
$configs['password'] = $redis['password'] ?? '';
} elseif ($empty_password) {
$configs['password'] = '';
}
$configs['persistent'] = (isset($configs['persistent']) && ($configs['persistent'] === true || $configs['persistent'] == 'true')) ? true : false;
// 存文件
file_put_contents(
ROOT_PATH . 'application' . DS . 'extra' . DS . 'redis.php',
'<?php' . "\n\nreturn " . short_var_export($configs, true) . ";"
);
}
$this->success('操作成功', null, $configs);
}
public function getPlatformUrl()
{
$h5Url = ShoproConfig::getConfigField('shop.basic.domain');
$wechatMpAppid = ShoproConfig::getConfigField('shop.platform.WechatMiniProgram.app_id');
$this->success('', null, [
'url' => $h5Url,
'appid' => $wechatMpAppid
]);
}
}

View File

@@ -0,0 +1,312 @@
<?php
namespace app\admin\controller\shopro;
use think\Db;
use app\admin\model\shopro\Coupon as CouponModel;
use app\admin\model\shopro\user\Coupon as UserCouponModel;
use addons\shopro\traits\CouponSend;
use app\admin\model\shopro\user\User;
/**
* 优惠券
*/
class Coupon extends Common
{
use CouponSend;
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->model = new CouponModel;
}
/**
* 优惠券列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$coupons = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10))->each(function ($coupon) {
// 优惠券领取和使用数量
$coupon->get_num = $coupon->get_num;
$coupon->use_num = $coupon->use_num;
});
$result = [
'coupons' => $coupons,
];
$result['total_num'] = UserCouponModel::count();
$result['expire_num'] = UserCouponModel::expired()->count();
$result['use_num'] = UserCouponModel::used()->count();
$result['use_percent'] = 0 . '%';
if ($result['total_num']) {
$result['use_percent'] = bcdiv(bcmul((string)$result['use_num'], '100'), (string)$result['total_num'], 1) . '%';
}
$this->success('获取成功', null, $result);
}
/**
* 添加优惠券
*
* @return \think\Response
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'name', 'type', 'use_scope', 'items', 'amount', 'max_amount', 'enough',
'stock', 'limit_num', 'get_time',
'use_time_type', 'use_time', 'start_days', 'days',
'is_double_discount', 'description', 'status'
]);
$this->svalidate($params, ".add");
// 时间转换
$getTime = explode(' - ', $params['get_time']);
$useTime = explode(' - ', $params['use_time']);
unset($params['get_time'], $params['use_time']);
$params['get_start_time'] = $getTime[0] ?? 0;
$params['get_end_time'] = $getTime[1] ?? 0;
$params['use_start_time'] = $useTime[0] ?? 0;
$params['use_end_time'] = $useTime[1] ?? 0;
$this->model->save($params);
$this->success('保存成功');
}
/**
* 优惠券详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$coupon = $this->model->where('id', $id)->find();
if (!$coupon) {
$this->error(__('No Results were found'));
}
$coupon->items_value = $coupon->items_value; // 可用范围值
$this->success('获取成功', null, $coupon);
}
/**
* 修改优惠券
*
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'name', 'use_scope', 'items', 'amount', 'max_amount', 'enough',
'stock', 'limit_num', 'get_time',
'use_time_type', 'use_time', 'start_days', 'days',
'is_double_discount', 'description', 'status'
]);
$this->svalidate($params);
// 时间转换
if (isset($params['get_time'])) {
$getTime = explode(' - ', $params['get_time']);
$params['get_start_time'] = $getTime[0] ?? 0;
$params['get_end_time'] = $getTime[1] ?? 0;
unset($params['get_time']);
}
if (isset($params['use_time'])) {
$useTime = explode(' - ', $params['use_time']);
$params['use_start_time'] = $useTime[0] ?? 0;
$params['use_end_time'] = $useTime[1] ?? 0;
unset($params['use_time']);
}
$coupon = $this->model->where('id', $id)->find();
if (!$coupon) {
$this->error(__('No Results were found'));
}
$coupon->save($params);
$this->success('更新成功');
}
/**
* 删除优惠券
*
* @param string $id 要删除的优惠券
* @return void
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
/**
* 优惠券列表
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type', 'page');
$coupons = $this->model->sheepFilter();
if ($type == 'select') {
// 普通结果
$coupons = $coupons->select();
} elseif ($type == 'find') {
$coupons = $coupons->find();
} else {
// 分页结果
$coupons = $coupons->paginate($this->request->param('list_rows', 10));
}
$this->success('获取成功', null, $coupons);
}
public function send($id)
{
$user_ids = $this->request->post('user_ids/a');
$users = User::whereIn('id', $user_ids)->select();
Db::transaction(function () use ($users, $id) {
$this->manualSend($users, $id);
});
$this->success('发放成功');
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$coupons = $this->model->onlyTrashed()->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $coupons);
}
/**
* 还原(支持批量)
*
* @param $id
* @return \think\Response
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$items = $this->model->onlyTrashed()->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
$count += $item->restore();
}
return $count;
});
if ($result) {
$this->success('还原成功', null, $result);
} else {
$this->error(__('No rows were updated'));
}
}
/**
* 销毁(支持批量)
*
* @param $id
* @return \think\Response
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
if ($id !== 'all') {
$items = $this->model->onlyTrashed()->whereIn('id', $id)->select();
} else {
$items = $this->model->onlyTrashed()->select();
}
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
// 删除商品
$count += $item->delete(true);
}
return $count;
});
if ($result) {
$this->success('销毁成功', null, $result);
}
$this->error('销毁失败');
}
}

View File

@@ -0,0 +1,241 @@
<?php
namespace app\admin\controller\shopro;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\order\OrderItem;
use app\admin\model\shopro\goods\Goods;
use app\admin\model\shopro\user\User;
use app\admin\model\shopro\Share;
use addons\shopro\service\SearchHistory;
class Dashboard extends Common
{
public function index()
{
$cardList = [
[
'name' => 'total',
'card' => 'shopro/dashboard/total',
'status' => $this->auth->check('shopro/dashboard/total')
],
[
'name' => 'chart',
'card' => 'shopro/dashboard/chart',
'status' => $this->auth->check('shopro/dashboard/chart')
],
[
'name' => 'ranking',
'card' => 'shopro/dashboard/ranking',
'status' => $this->auth->check('shopro/dashboard/ranking')
],
];
$this->assignconfig('cardList', $cardList);
return $this->view->fetch();
}
public function total()
{
// 用户数据
$userData = [
'total' => User::count(),
'today' => User::whereTime('createtime', 'today')->count(),
'week' => User::whereTime('createtime', 'week')->count(),
'array' => collection(User::field('id,createtime')->whereTime('createtime', 'today')->select())->each(function ($user) {
$user->counter = 1;
$user->createtime_unix = $user->getData('createtime') * 1000;
})
];
// -- commission code start --
$agentData = [
'total' => \app\admin\model\shopro\commission\Agent::count(),
'today' => \app\admin\model\shopro\commission\Agent::whereTime('createtime', 'today')->count(),
'week' => \app\admin\model\shopro\commission\Agent::whereTime('createtime', 'week')->count(),
'array' => collection(\app\admin\model\shopro\commission\Agent::field('user_id,createtime')->whereTime('createtime', 'today')->select())->each(function ($agent) {
$agent->counter = 1;
$agent->createtime_unix = $agent->getData('createtime') * 1000;
})
];
// -- commission code end --
// 分享数据
$shareData = [
'total' => Share::count(),
'today' => Share::whereTime('createtime', 'today')->count(),
'week' => Share::whereTime('createtime', 'week')->count(),
'array' => collection(Share::field('id,createtime')->whereTime('createtime', 'today')->select())->each(function ($share) {
$share->counter = 1;
$share->createtime_unix = $share->getData('createtime') * 1000;
})
];
$this->success('获取成功', null, [
'user_data' => $userData,
'agent_data' => $agentData ?? null,
'share_data' => $shareData
]);
}
public function chart()
{
$date = $this->request->param('date', '');
$date = array_values(array_filter(explode(' - ', $date)));
$orders = Order::with(['items'])->whereTime('createtime', 'between', $date)
->order('id', 'asc')->select();
// 订单数
$data['orderNum'] = count($orders);
$data['orderArr'] = [];
// 支付订单(包含退款的订单, 不包含货到付款还未收货(未支付)订单)
$data['payOrderNum'] = 0;
$data['payOrderArr'] = [];
//支付金额(包含退款的订单, 不包含货到付款还未收货(未支付)订单)
$data['payAmountNum'] = 0;
$data['payAmountArr'] = [];
// 支付用户(一个人不管下多少单,都算一个,包含退款的订单, 不包含货到付款还未收货(未支付)订单)
$userIds = [];
$data['payUserNum'] = 0;
$data['payUserArr'] = [];
// 代发货(包含货到付款)
$data['noSendNum'] = 0;
$data['noSendArr'] = [];
//售后维权
$data['aftersaleNum'] = 0;
$data['aftersaleArr'] = [];
//退款订单
$data['refundNum'] = 0;
$data['refundArr'] = [];
foreach ($orders as $key => $order) {
$data['orderArr'][] = [
'counter' => 1,
'createtime' => $order->getData('createtime') * 1000,
'user_id' => $order->user_id
];
// 已支付的,不包含,货到付款未支付的
if (in_array($order->status, [Order::STATUS_PAID, Order::STATUS_COMPLETED])) {
// 支付订单数
$data['payOrderNum']++;
$data['payOrderArr'][] = [
'counter' => 1,
'createtime' => $order->getData('createtime') * 1000,
'user_id' => $order->user_id
];
// 支付金额
$data['payAmountNum'] = bcadd((string)$data['payAmountNum'], $order->pay_fee, 2);
$data['payAmountArr'][] = [
'counter' => $order->pay_fee,
'createtime' => $order->getData('createtime') * 1000,
];
// 下单用户
if (!in_array($order->user_id, $userIds)) {
$data['payUserNum']++;
$data['payUserArr'][] = [
'counter' => 1,
'createtime' => $order->getData('createtime') * 1000,
'user_id' => $order->user_id
];
}
}
// 已支付的,和 货到付款未支付的
if (in_array($order->status, [Order::STATUS_PAID, Order::STATUS_COMPLETED]) || $order->isOffline($order)) {
$flagnoSend = false;
$flagaftersale = false;
$flagrefund = false;
$aftersaleIng = false;
foreach ($order->items as $k => $item) {
if (
!$flagnoSend
&& $item->dispatch_status == OrderItem::DISPATCH_STATUS_NOSEND
&& $item->refund_status == OrderItem::REFUND_STATUS_NOREFUND
&& in_array($order->apply_refund_status, [
Order::APPLY_REFUND_STATUS_NOAPPLY,
Order::APPLY_REFUND_STATUS_REFUSE
])
) {
$flagnoSend = true;
}
if (
$item->aftersale_status == OrderItem::AFTERSALE_STATUS_ING
&& $item->dispatch_status == OrderItem::DISPATCH_STATUS_NOSEND
&& $item->refund_status == OrderItem::REFUND_STATUS_NOREFUND
) {
$aftersaleIng = true;
}
if (!$flagaftersale && $item->aftersale_status != OrderItem::AFTERSALE_STATUS_NOAFTER) {
$data['aftersaleNum']++;
// $data['aftersaleArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// ];
$flagaftersale = true;
}
if (!$flagrefund && $item->refund_status > OrderItem::REFUND_STATUS_NOREFUND) {
$data['refundNum']++;
// $data['refundArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// ];
$flagrefund = true;
}
}
if (!$aftersaleIng && $flagnoSend) {
// 存在正在售后中的订单,不算待发货(和订单列表保持一直)
$data['noSendNum']++;
// $data['noSendArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// ];
}
}
}
$this->success('获取成功', null, $data);
}
public function ranking()
{
$goods = Goods::limit(5)->order('sales', 'desc')->select();
foreach ($goods as $key => $gd) {
$gd->append(['real_sales']);
$result = OrderItem::field('sum(goods_num * goods_price) as sale_total_money')->where('goods_id', $gd['id'])
->whereExists(function ($query) use ($gd) {
$order_table_name = (new Order())->getQuery()->getTable();
$table_name = (new OrderItem())->getQuery()->getTable();
$query->table($order_table_name)->where($table_name . '.order_id=' . $order_table_name . '.id')
->whereIn('status', [Order::STATUS_PAID, Order::STATUS_COMPLETED]); // 已支付的订单
})->find();
$gd['sale_total_money'] = $result['sale_total_money'] ?: 0;
}
$searchHistory = new SearchHistory();
$this->success('获取成功', null, [
'goods' => $goods,
'hot_search' => $searchHistory->hotSearch()
]);
}
}

View File

@@ -0,0 +1,112 @@
<?php
namespace app\admin\controller\shopro;
use think\Db;
use app\admin\model\shopro\Feedback as FeedbackModel;
class Feedback extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new FeedbackModel();
}
/**
* 查看
*
* @return Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$feedbacks = $this->model->sheepFilter()->with('user')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $feedbacks);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$detail = $this->model->with('user')->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
$params = $this->request->only(['status', 'remark']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除优惠券
*
* @param string $id 要删除的意见反馈
* @return void
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace app\admin\controller\shopro;
use think\Db;
use app\admin\model\shopro\PayConfig as PayConfigModel;
/**
* 支付配置
*/
class PayConfig extends Common
{
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->model = new PayConfigModel;
}
/**
* 支付配置列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$payConfigs = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $payConfigs);
}
/**
* 添加支付配置
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'name', 'type', 'params', 'status'
]);
$this->svalidate($params, ".add");
$this->svalidate($params['params'], '.' . $params['type']); // 验证对应的支付参数是否设置完整
operate_filter();
$this->model->save($params);
$this->success('保存成功');
}
/**
* 支付配置详情
*
* @param $id
*/
public function detail($id)
{
$payConfig = $this->model->where('id', $id)->find();
if (!$payConfig) {
$this->error(__('No Results were found'));
}
$payConfig->append(['params']);
$this->success('获取成功', null, pay_config_show($payConfig));
}
/**
* 修改支付配置
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'name', 'params', 'status'
]);
$this->svalidate($params);
$payConfig = $this->model->where('id', $id)->find();
if (!$payConfig) {
$this->error(__('No Results were found'));
}
if (isset($params['params'])) {
$this->svalidate($params['params'], '.' . $payConfig['type']); // 验证对应的支付参数是否设置完整
}
operate_filter();
$payConfig->save($params);
$this->success('更新成功');
}
/**
* 删除支付配置
*
* @param string $id 要删除的商品分类列表
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
operate_filter();
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
/**
* 获取所有支付配置
*/
public function select()
{
$payConfigs = $this->model->sheepFilter()->normal()
->field('id, name, type,status')
->select();
$this->success('获取成功', null, $payConfigs);
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$goods = $this->model->onlyTrashed()->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $goods);
}
/**
* 还原(支持批量)
*
* @param $id
* @return \think\Response
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$items = $this->model->onlyTrashed()->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
$count += $item->restore();
}
return $count;
});
if ($result) {
$this->success('还原成功', null, $result);
} else {
$this->error(__('No rows were updated'));
}
}
/**
* 销毁(支持批量)
*
* @param $id
* @return \think\Response
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
if ($id !== 'all') {
$items = $this->model->onlyTrashed()->whereIn('id', $id)->select();
} else {
$items = $this->model->onlyTrashed()->select();
}
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $config) {
// 删除商品
$count += $config->delete(true);
}
return $count;
});
if ($result) {
$this->success('销毁成功', null, $result);
}
$this->error('销毁失败');
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\admin\controller\shopro;
use app\admin\model\shopro\Share as ShareModel;
class Share extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new ShareModel();
}
/**
* 查看用户分享记录
*/
public function index()
{
$share_id = $this->request->param('id');
$data = ShareModel::with(['user' => function ($query) {
return $query->field(['id', 'nickname', 'avatar']);
}])->where('share_id', $share_id)->sheepFilter()->paginate($this->request->param('list_rows', 8));
$this->success('', null, $data);
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace app\admin\controller\shopro;
use think\Db;
use think\exception\HttpResponseException;
use addons\shopro\exception\ShoproException;
use app\admin\model\shopro\Withdraw as WithdrawModel;
use app\admin\model\shopro\WithdrawLog as WithdrawLogModel;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\Admin as AdminModel;
use addons\shopro\service\Withdraw as WithdrawLibrary;
use addons\shopro\library\Operator;
/**
* 提现
*/
class Withdraw extends Common
{
public $logModel;
public function _initialize()
{
parent::_initialize();
$this->model = new WithdrawModel;
$this->logModel = new WithdrawLogModel;
}
/**
* 提现列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$withdraws = $this->model->sheepFilter()->with(['user'])->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $withdraws);
}
/**
* 提现日志
*/
public function log($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$logs = $this->logModel->where('withdraw_id', $id)->order('id desc')->select();
$morphs = [
'user' => UserModel::class,
'admin' => AdminModel::class,
'system' => AdminModel::class
];
$logs = morph_to($logs, $morphs, ['oper_type', 'oper_id']);
$logs = $logs->toArray();
// 解析操作人信息
foreach ($logs as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('获取成功', null, $logs);
}
public function handle($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->param();
$action = $params['action'] ?? null;
$refuse_msg = $params['refuse_msg'] ?? '';
if ($action == 'refuse' && !$refuse_msg) {
$this->error('请输入拒绝原因');
}
$ids = is_array($id) ? $id : explode(',', $id);
foreach ($ids as $key => $id) {
Db::startTrans();
try {
$withdraw = $this->model->lock(true)->where('id', $id)->find();
if (!$withdraw) {
$this->error(__('No Results were found'));
}
$withdrawLib = new WithdrawLibrary($withdraw->user_id);
switch ($action) {
case 'agree':
$withdraw = $withdrawLib->handleAgree($withdraw);
break;
case 'agree&withdraw':
$withdraw = $withdrawLib->handleAgree($withdraw);
$withdraw = $withdrawLib->handleWithdraw($withdraw);
break;
case 'withdraw':
$withdraw = $withdrawLib->handleWithdraw($withdraw);
break;
case 'refuse':
$withdraw = $withdrawLib->handleRefuse($withdraw, $refuse_msg);
break;
}
Db::commit();
} catch (ShoproException $e) {
Db::commit(); // 不回滚,记录错误日志
$this->error($e->getMessage());
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
}
$this->success('处理成功');
}
}

View File

@@ -0,0 +1,321 @@
<?php
namespace app\admin\controller\shopro\activity;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\activity\Activity as ActivityModel;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\goods\Sku as SkuModel;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use addons\shopro\library\activity\Activity as ActivityManager;
use addons\shopro\library\activity\traits\CheckActivity;
use addons\shopro\facade\Activity as ActivityFacade;
/**
* 活动管理
*/
class Activity extends Common
{
use CheckActivity;
protected $noNeedRight = ['getType', 'select', 'skus'];
protected $manager = null;
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new ActivityModel;
$this->manager = ActivityFacade::instance();
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
$type = $this->request->param('type', null);
if (!$this->request->isAjax()) {
if ($type) {
return $this->view->fetch('shopro/activity/activity/index');
}
return $this->view->fetch('shopro/activity/activity/activity');
}
$activities = $this->model->sheepFilter()->where('type', $type)->paginate(request()->param('list_rows', 10))->toArray();
$items = $activities['data'];
// 关联活动的商品
$goodsIds = array_values(array_filter(array_column($items, 'goods_ids')));
$goodsIdsArr = [];
foreach ($goodsIds as $ids) {
$idsArr = explode(',', $ids);
$goodsIdsArr = array_merge($goodsIdsArr, $idsArr);
}
$goodsIdsArr = array_values(array_filter(array_unique($goodsIdsArr)));
if ($goodsIdsArr) {
// 查询商品
$goods = GoodsModel::where('id', 'in', $goodsIdsArr)->select();
$goods = array_column($goods, null, 'id');
}
foreach ($items as $key => $activity) {
$items[$key]['goods'] = [];
if ($activity['goods_ids']) {
$idsArr = explode(',', $activity['goods_ids']);
foreach ($idsArr as $id) {
if (isset($goods[$id])) {
$items[$key]['goods'][] = $goods[$id];
}
}
}
}
$activities['data'] = $items;
$this->success('获取成功', null, $activities);
}
// 获取数据类型
public function getType()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$typeList = $this->model->typeList();
$result = [
'type_list' => $typeList,
];
$data = [];
foreach ($result as $key => $list) {
$data[$key][] = ['name' => '全部', 'type' => 'all'];
foreach ($list as $k => $v) {
$data[$key][] = [
'name' => $v,
'type' => $k
];
}
}
$this->success('获取成功', null, $data);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'title', 'goods_ids', 'type', 'prehead_time', 'start_time', 'end_time',
'rules', 'richtext_id', 'richtext_title', 'goods_list'
]);
if (isset($params['goods_list'])) {
$params['goods_list'] = json_decode($params['goods_list'], true);
}
$this->svalidate($params, ".add");
Db::transaction(function () use ($params) {
$this->manager->save($params);
});
$this->success('保存成功');
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$activity = $this->model->where('id', $id)->find();
if (!$activity) {
$this->error(__('No Results were found'));
}
$activity->goods_list = $activity->goods_list;
$activity->rules = $activity->rules;
$this->success('获取成功', null, $activity);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'title', 'goods_ids', 'prehead_time', 'start_time', 'end_time',
'rules', 'richtext_id', 'richtext_title', 'goods_list'
]);
if (isset($params['goods_list'])) {
$params['goods_list'] = json_decode($params['goods_list'], true);
}
$this->svalidate($params);
$id = explode(',', $id);
$items = $this->model->whereIn('id', $id)->select();
Db::transaction(function () use ($items, $params) {
foreach ($items as $activity) {
$this->manager->update($activity, $params);
}
});
$this->success('更新成功');
}
/**
* 获取活动商品规格并且初始化
*/
public function skus()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->param();
$id = $params['id'] ?? 0;
$goods_id = $params['goods_id'] ?? 0;
$activity_type = $params['activity_type'] ?? '';
$start_time = $params['start_time'] ?? '';
$end_time = $params['end_time'] ?? '';
$prehead_time = $params['prehead_time'] ?? '';
if ($start_time && $end_time && $activity_type) {
// 如果存在开始结束时间,并且是要修改
$goodsList = [$goods_id => ['id' => $goods_id]];
$this->checkActivityConflict([
'type' => $activity_type,
'classify' => $this->model->getClassify($activity_type),
'start_time' => $start_time,
'end_time' => $end_time,
'prehead_time' => $prehead_time
], $goodsList, $id);
}
// 商品规格
$skus = SkuModel::with('children')->where('goods_id', $goods_id)->where('parent_id', 0)->select();
// 获取规格
$skuPrices = SkuPriceModel::with(['activity_sku_price' => function ($query) use ($id) {
$query->where('activity_id', $id);
}])->where('goods_id', $goods_id)->select();
//编辑
$activitySkuPrices = [];
foreach ($skuPrices as $k => $skuPrice) {
$activitySkuPrices[$k] = $skuPrice->activity_sku_price ? $skuPrice->activity_sku_price->toArray() : [];
// 活动规格数据初始化
if (!$activitySkuPrices[$k]) {
$activitySkuPrices[$k]['id'] = 0;
$activitySkuPrices[$k]['status'] = 'down';
$activitySkuPrices[$k]['price'] = '';
$activitySkuPrices[$k]['stock'] = '';
$activitySkuPrices[$k]['sales'] = '0';
$activitySkuPrices[$k]['goods_sku_price_id'] = $skuPrice->id;
}
// 个性化初始化每个活动的 规格 字段
$activitySkuPrices[$k] = $this->manager->showSkuPrice($activity_type, $activitySkuPrices[$k]);
}
$this->success('获取成功', null, [
'skus' => $skus,
'sku_prices' => $skuPrices,
'activity_sku_prices' => $activitySkuPrices,
]);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type');
$activities = $this->model->sheepFilter()->whereIn('type', $type)->paginate(request()->param('list_rows', 10))->toArray();
$this->success('获取成功', null, $activities);
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $this->manager->delete($item);
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type');
$activities = $this->model->onlyTrashed()->sheepFilter()->where('type', $type)->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $activities);
}
}

View File

@@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
namespace app\admin\controller\shopro\activity;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\activity\Activity as ActivityModel;
use app\admin\model\shopro\activity\Groupon as GrouponModel;
use app\admin\model\shopro\Admin;
use addons\shopro\library\activity\traits\Groupon as GrouponTrait;
/**
* 团管理
*/
class Groupon extends Common
{
use GrouponTrait;
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new GrouponModel;
}
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$groupons = $this->model->sheepFilter()->with(['goods', 'user', 'grouponLogs'])
->paginate(request()->param('list_rows', 10));
$this->success('获取成功', null, $groupons);
}
/**
* 团详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$groupon = $this->model->with(['goods', 'user', 'grouponLogs'])->where('id', $id)->find();
if (!$groupon) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $groupon);
}
/**
* 添加虚拟用户(人满自动成团)
*
* @param Request $request
* @param integer $id
*/
public function addUser($id)
{
$groupon = $this->model->where('id', $id)->find();
if (!$groupon) {
$this->error(__('No Results were found'));
}
$activity = ActivityModel::where('id', $groupon['activity_id'])->find();
if (!$activity) {
$this->error('活动不存在');
}
if ($groupon['status'] != 'ing' || $groupon['current_num'] > $groupon['num']) {
$this->error('团已完成或已失效');
}
$avatar = $this->request->param('avatar', '');
$nickname = $this->request->param('nickname', '');
$user = ['avatar' => $avatar, 'nickname' => $nickname];
Db::transaction(function () use ($activity, $groupon, $user) {
// 增加人数
$this->finishFictitiousGroupon($activity, $groupon, false, 1, [$user]);
});
$this->success('操作成功');
}
/**
* 解散团,自动退款
*
* @param Request $request
* @param integer $id
*/
public function invalid($id)
{
$admin = $this->auth->getUserInfo();
$admin = Admin::find($admin['id']);
$groupon = $this->model->where('id', $id)->find();
if ($groupon['status'] != 'ing') {
$this->error('团已完成或已失效');
}
Db::transaction(function () use ($groupon, $admin) {
// 解散团,并退款
$this->invalidRefundGroupon($groupon, $admin);
});
$this->success('操作成功');
}
}

View File

@@ -0,0 +1,323 @@
<?php
namespace app\admin\controller\shopro\app;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\app\ScoreSkuPrice;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\goods\Sku as SkuModel;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
/**
* 积分商城
*/
class ScoreShop extends Common
{
protected $noNeedRight = ['skuPrices', 'select', 'skus'];
public function _initialize()
{
parent::_initialize();
$this->model = new ScoreSkuPrice;
$this->goodsModel = new GoodsModel();
}
/**
* 积分商城商品列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$scoreGoodsIds = $this->model->group('goods_id')->column('goods_id');
$scoreGoods = $this->goodsModel->sheepFilter()->with(['score_sku_prices'])
->whereIn('id', $scoreGoodsIds)
->paginate($this->request->param('list_rows', 10))->each(function($goods) {
$goods->score_price = $goods->score_price;
$goods->score_sales = $goods->score_sales;
$goods->score_stock = $goods->score_stock;
});
$this->success('获取成功', null, $scoreGoods);
}
/**
* skuPrices列表
*/
public function skuPrices($goods_id)
{
$skuPrices = $this->model->up()->with(['sku_price'])->where('goods_id', $goods_id)->select();
$skuPrices = collection($skuPrices)->each(function ($skuPrice) {
$skuPrice->goods_sku_ids = $skuPrice->goods_sku_ids;
$skuPrice->goods_sku_text = $skuPrice->goods_sku_text;
$skuPrice->image = $skuPrice->image;
$skuPrice->score_price = $skuPrice->score_price;
});
$this->success('获取成功', null, $skuPrices);
}
/**
* 添加积分商城商品
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'goods_id', 'sku_prices'
]);
$this->svalidate($params, ".add");
// 检查是否已经是积分商品了
$count = $this->model->where('goods_id', $params['goods_id'])->count();
if ($count) {
error_stop('该商品已经是积分商城商品了');
}
$statuses = array_column($params['sku_prices'], 'status');
if (!in_array('up', $statuses)) {
error_stop('请至少选择一个规格');
}
Db::transaction(function () use ($params) {
$this->editSkuPrices($params['goods_id'], $params);
});
$this->success('保存成功');
}
public function skus($goods_id)
{
$skus = SkuModel::with('children')->where('goods_id', $goods_id)->where('parent_id', 0)->select();
$skuPrices = SkuPriceModel::with(['score_sku_price'])->where('goods_id', $goods_id)->select();
//编辑
$scoreSkuPrices = [];
foreach ($skuPrices as $k => $skuPrice) {
$scoreSkuPrices[$k] = $skuPrice->score_sku_price ? : [];
// 活动规格数据初始化
if (!$scoreSkuPrices[$k]) {
$scoreSkuPrices[$k]['id'] = 0;
$scoreSkuPrices[$k]['status'] = 'down';
$scoreSkuPrices[$k]['price'] = '';
$scoreSkuPrices[$k]['score'] = '';
$scoreSkuPrices[$k]['stock'] = '';
$scoreSkuPrices[$k]['goods_sku_price_id'] = $skuPrice->id;
}
}
$this->success('获取成功', null, [
'skus' => $skus,
'sku_prices' => $skuPrices,
'score_sku_prices' => $scoreSkuPrices
]);
}
/**
* 编辑积分商城商品
*/
public function edit($goods_id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'sku_prices'
]);
$this->svalidate($params, ".edit");
$statuses = array_column($params['sku_prices'], 'status');
if (!in_array('up', $statuses)) {
error_stop('请至少选择一个规格');
}
Db::transaction(function () use ($goods_id, $params) {
$this->editSkuPrices($goods_id, $params);
});
$this->success('更新成功');
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type', 'page');
$scoreGoodsIds = $this->model->group('goods_id')->column('goods_id');
$scoreGoods = $this->goodsModel->sheepFilter()->with(['score_sku_prices'])
->whereIn('id', $scoreGoodsIds);
if ($type == 'select') {
// 普通结果
$scoreGoods = $scoreGoods->select();
$scoreGoods = collection($scoreGoods);
} else {
// 分页结果
$scoreGoods = $scoreGoods->paginate($this->request->param('list_rows', 10));
}
$scoreGoods = $scoreGoods->each(function ($goods) {
$goods->score_price = $goods->score_price;
$goods->score_sales = $goods->score_sales;
$goods->score_stock = $goods->score_stock;
});
$this->success('获取成功', null, $scoreGoods);
}
/**
* 删除积分商城商品
*
* @param string $id 要删除的积分商城商品 id
* @return void
*/
public function delete($goods_id)
{
if (empty($goods_id)) {
$this->error(__('Parameter %s can not be empty', 'goods_id'));
}
$goodsIds = explode(',', $goods_id);
$list = $this->model->whereIn('goods_id', $goodsIds)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$scoreGoodsIds = $this->model->onlyTrashed()->group('goods_id')->column('goods_id');
$scoreGoods = $this->goodsModel->sheepFilter()->with(['del_score_sku_prices'])
->whereIn('id', $scoreGoodsIds)
->paginate($this->request->param('list_rows', 10))->each(function ($skuPrice) {
$deleteTimes = collection($skuPrice->del_score_sku_prices)->column('deletetime');
$skuPrice->deletetime = $deleteTimes ? max($deleteTimes) : null; // 取用积分规格的删除时间
});
$this->success('获取成功', null, $scoreGoods);
}
/**
* 还原(支持批量)
*
* @param $id
* @return \think\Response
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'goods_id'));
}
$goodsIds = explode(',', $id);
Db::transaction(function () use ($goodsIds) {
foreach ($goodsIds as $goods_id) {
$count = $this->model->where('goods_id', $goods_id)->count();
if ($count) {
error_stop('商品 ID 为 ' . $goods_id . ' 的商品已经是积分商品了,不可还原');
}
$list = $this->model->onlyTrashed()->whereIn('goods_id', $goods_id)->select();
foreach ($list as $goods) {
$goods->restore();
}
}
});
$this->success('还原成功');
}
/**
* 销毁(支持批量)
*
* @param $id
* @return \think\Response
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'goods_id'));
}
$goodsIds = explode(',', $id);
Db::transaction(function () use ($goodsIds) {
if (!in_array('all', $goodsIds)) {
foreach ($goodsIds as $goods_id) {
$list = $this->model->onlyTrashed()->whereIn('goods_id', $goods_id)->select();
foreach ($list as $goods) {
$goods->delete(true);
}
}
} else {
$list = $this->model->onlyTrashed()->select();
foreach ($list as $goods) {
$goods->delete(true);
}
}
});
$this->success('销毁成功');
}
private function editSkuPrices($goods_id, $params)
{
//下架全部规格
$this->model->where('goods_id', $goods_id)->update(['status' => 'down']);
foreach ($params['sku_prices'] as $key => $skuPrice) {
if ($skuPrice['id'] == 0) {
unset($skuPrice['id']);
}
unset($skuPrice['sales']); //不更新销量
unset($skuPrice['createtime'], $skuPrice['updatetime'], $skuPrice['deletetime']); // 不手动更新时间
$skuPrice['goods_id'] = $goods_id;
$model = new ScoreSkuPrice;
if (isset($skuPrice['id'])) {
$model = $this->model->find($skuPrice['id']);
$model = $model ? : new ScoreSkuPrice;
}
$model->save($skuPrice);
}
}
}

View File

@@ -0,0 +1,163 @@
<?php
namespace app\admin\controller\shopro\app\mplive;
use app\admin\model\shopro\app\mplive\Goods as MpliveGoodsModel;
/**
* 小程序直播商品管理
*/
class Goods extends Index
{
// 直播间商品
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$model = new MpliveGoodsModel();
$list = $model->sheepFilter()->paginate($this->request->param('list_rows', 10));
// 批量更新直播商品状态
// $this->updateAuditStatusByGoods($list);
$this->success('获取成功', null, $list);
}
// 直播间商品详情
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$goods = (new MpliveGoodsModel)->findOrFail($id);
$this->success('', null, $goods);
}
// 创建直播间商品并提交审核
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->param();
$data = [
"coverImgUrl" => $this->uploadMedia($params['cover_img_url']),
"name" => $params['name'],
"priceType" => $params['price_type'],
"price" => $params['price'],
"price2" => $params['price_type'] === 1 ? "" : $params['price2'], // priceType为2或3时必填
"url" => $params['url'],
];
$res = $this->wechat->broadcast->create($data);
$this->catchLiveError($res);
$params['id'] = $res['goodsId'];
$params['audit_id'] = $res['auditId'];
$params['audit_status'] = 1;
(new MpliveGoodsModel)->save($params);
$this->success("操作成功");
}
// 直播商品审核
public function audit($id)
{
$id = intval($id);
$act = $this->request->param('act');
$goods = MpliveGoodsModel::where('id', $id)->find();
if (!$goods) {
error_stop('未找到该商品');
}
// 撤回审核
if ($act === 'reset') {
$auditId = $goods->audit_id;
if ($auditId) {
$res = $this->wechat->broadcast->resetAudit($auditId, $id);
$this->catchLiveError($res);
}
}
// 重新审核
if ($act === 'resubmit') {
$res = $this->wechat->broadcast->resubmitAudit($id);
$this->catchLiveError($res);
$goods->audit_id = $res['auditId'];
$goods->save();
}
return $this->status($id);
}
// 删除直播商品
public function delete($id)
{
$id = intval($id);
$res = $this->wechat->broadcast->delete($id);
$this->catchLiveError($res);
MpliveGoodsModel::where('id', $id)->delete();
$this->success('操作成功');
}
// 更新直播商品
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->param();
$data = [
'goodsId' => $id,
"coverImgUrl" => $this->uploadMedia($params['cover_img_url']),
"name" => $params['name'],
"priceType" => $params['price_type'],
"price" => $params['price'],
"price2" => $params['price_type'] === 1 ? "" : $params['price2'], // priceType为2或3时必填
"url" => $params['url'],
];
$res = $this->wechat->broadcast->update($data);
$this->catchLiveError($res);
$goods = MpliveGoodsModel::where('id', $id)->find();
$goods->save($data);
$this->success('操作成功');
}
// 更新直播商品状态
public function status($id)
{
$res = $this->wechat->broadcast->getGoodsWarehouse([$id]);
$this->catchLiveError($res);
$list = $res['goods'];
foreach ($list as $key => $goods) {
$mpliveGoods = MpliveGoodsModel::where('id', $goods['goods_id'])->find();
if ($mpliveGoods) {
$mpliveGoods->audit_status = $goods['audit_status'];
$mpliveGoods->third_party_tag = $goods['third_party_tag'];
$mpliveGoods->save();
}
}
$this->success('操作成功');
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace app\admin\controller\shopro\app\mplive;
use fast\Http;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\app\mplive\Room as MpliveRoomModel;
use addons\shopro\library\mplive\ServiceProvider;
use addons\shopro\facade\Wechat;
/**
* 小程序直播
*/
class Index extends Common
{
protected $wechat;
public function _initialize()
{
parent::_initialize();
$this->wechat = Wechat::miniProgram();
(new ServiceProvider())->register($this->wechat);
}
// 上传临时素材
protected function uploadMedia($path)
{
$filesystem = config('filesystem.default');
if ($filesystem !== 'local' || is_url($path)) {
$body = Http::get(cdnurl($path, true));
$dir = RUNTIME_PATH . 'storage' . DS . 'temp';
if (!is_dir($dir)) {
@mkdir($dir, 0755, true);
}
$temp_path = $dir . $this->getBaseName($path);
file_put_contents($temp_path, $body);
} else {
$temp_path = ROOT_PATH . 'public' . $path;
}
if (!isset($temp_path) || empty($temp_path)) {
error_stop("上传失败,不是一个有效的文件: " . $path);
}
$media = $this->wechat->media;
$res = $media->uploadImage($temp_path);
@unlink($temp_path); // 删除临时文件
if (isset($res['media_id'])) {
return $res['media_id'];
}
return '';
}
// 解析图片文件名
private function getBaseName($path)
{
if (strpos($path, 'mmbiz.qpic.cn') !== false) {
return DS . gen_random_str(8) . '.jpg';
}
return basename($path);
}
// 转义直播错误信息
protected function catchLiveError($response)
{
if (!isset($response['errcode'])) {
error_stop("未知错误");
}
$errorMap = MpliveRoomModel::ERR_CODE;
if (isset($response['errcode']) && ($response['errcode'] !== 0 && $response['errcode'] !== 1001)) {
if (isset($errorMap[$response['errcode']])) {
error_stop("{$errorMap[$response['errcode']]} [错误码: {$response['errcode']}]");
} else {
error_stop("{$response['errmsg']} [错误码: {$response['errcode']}]");
}
}
}
}

View File

@@ -0,0 +1,201 @@
<?php
namespace app\admin\controller\shopro\app\mplive;
use app\admin\model\shopro\app\mplive\Room as MpliveRoomModel;
/**
* 小程序直播
*/
class Room extends Index
{
protected $noNeedRight = ['select'];
// 直播间列表
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = (new MpliveRoomModel)->sheepFilter()->select();
$this->success('', null, $list);
}
// 直播间详情
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$room = (new MpliveRoomModel)->where('roomid', $id)->findOrFail();
$this->success('', null, $room);
}
// 同步直播间列表
public function sync()
{
$res = $this->wechat->broadcast->getRooms();
$data = [];
$this->catchLiveError($res);
MpliveRoomModel::where('roomid', '>', 0)->delete();
foreach ($res['room_info'] as $room) {
$room['status'] = $room['live_status'];
$room['type'] = $room['live_type'];
$data[] = $room;
}
MpliveRoomModel::strict(false)->insertAll($data);
$list = MpliveRoomModel::select();
$this->success('', null, $list);
}
// 创建直播间
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->param();
$data = [
'name' => $params['name'], // 房间名字
'coverImg' => $this->uploadMedia($params['cover_img']), // 通过 uploadfile 上传,填写 mediaID
'shareImg' => $this->uploadMedia($params['share_img']), //通过 uploadfile 上传,填写 mediaID
'feedsImg' => $this->uploadMedia($params['feeds_img']), //通过 uploadfile 上传,填写 mediaID
'startTime' => $params['start_time'], // 开始时间
'endTime' => $params['end_time'], // 结束时间
'anchorName' => $params['anchor_name'], // 主播昵称
'anchorWechat' => $params['anchor_wechat'], // 主播微信号
'subAnchorWechat' => $params['sub_anchor_wechat'], // 主播副号微信号
'isFeedsPublic' => $params['is_feeds_public'], // 是否开启官方收录1 开启0 关闭
'type' => $params['type'], // 直播类型1 推流 0 手机直播
'closeLike' => $params['close_like'], // 是否关闭点赞 1关闭
'closeGoods' => $params['close_goods'], // 是否关闭商品货架1关闭
'closeComment' => $params['close_comment'], // 是否开启评论1关闭
'closeReplay' => $params['close_replay'], // 是否关闭回放 1 关闭
'closeKf' => $params['close_kf'], // 是否关闭客服1 关闭
];
$res = $this->wechat->broadcast->createLiveRoom($data);
$this->catchLiveError($res);
return $this->sync();
}
// 更新直播间
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->param();
$data = [
'id' => $id,
'name' => $params['name'], // 房间名字
'coverImg' => $this->uploadMedia($params['cover_img']), // 通过 uploadfile 上传,填写 mediaID
'shareImg' => $this->uploadMedia($params['share_img']), //通过 uploadfile 上传,填写 mediaID
'feedsImg' => $this->uploadMedia($params['feeds_img']), //通过 uploadfile 上传,填写 mediaID
'startTime' => $params['start_time'], // 开始时间
'endTime' => $params['end_time'], // 结束时间
'anchorName' => $params['anchor_name'], // 主播昵称
'anchorWechat' => $params['anchor_wechat'], // 主播昵称
'isFeedsPublic' => $params['is_feeds_public'], // 是否开启官方收录1 开启0 关闭
'type' => $params['type'], // 直播类型1 推流 0 手机直播
'closeLike' => $params['close_like'], // 是否关闭点赞 1关闭
'closeGoods' => $params['close_goods'], // 是否关闭商品货架1关闭
'closeComment' => $params['close_comment'], // 是否开启评论1关闭
'closeReplay' => $params['close_replay'], // 是否关闭回放 1 关闭
'closeKf' => $params['close_kf'], // 是否关闭客服1 关闭
];
$res = $this->wechat->broadcast->updateLiveRoom($data);
$this->catchLiveError($res);
return $this->sync();
}
// 删除直播间
public function delete($id)
{
$res = $this->wechat->broadcast->deleteLiveRoom([
'id' => $id,
]);
$this->catchLiveError($res);
MpliveRoomModel::where('roomid', $id)->delete();
$this->success('操作成功');
}
// 推流地址
public function pushUrl($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$res = $this->wechat->broadcast->getPushUrl([
'roomId' => $id
]);
$this->catchLiveError($res);
$this->success('', null, ['pushAddr' => $res['pushAddr']]);
}
// 分享二维码
public function qrcode($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$res = $this->wechat->broadcast->getShareQrcode([
'roomId' => $id
]);
$this->catchLiveError($res);
$this->success('', null, ['pagePath' => $res['pagePath'], 'cdnUrl' => $res['cdnUrl']]);
}
// 查看回放
public function playback($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$res = $this->wechat->broadcast->getPlaybacks((int)$id, (int)$start = 0, (int)$limit = 10);
$this->catchLiveError($res);
$data = $res['live_replay'];
$this->success('', null, $data);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = (new MpliveRoomModel)->sheepFilter()->select();
$this->success('', null, $list);
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace app\admin\controller\shopro\chat;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\CommonWord as ChatCommonWord;
class CommonWord extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new ChatCommonWord;
}
/**
* 常用语列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$commonWords = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $commonWords);
}
/**
* 常用语添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['room_id', 'name', 'status', 'weigh']);
$params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params, ".add");
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 常用语详情
*
* @param $id
*/
public function detail($id)
{
$commonWord = $this->model->where('id', $id)->find();
if (!$commonWord) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $commonWord);
}
/**
* 常用语编辑
*
* @param $id
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['room_id', 'name', 'status', 'weigh']);
$this->request->has('content') && $params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params);
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除(支持批量)
*
* @param $id
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,207 @@
<?php
namespace app\admin\controller\shopro\chat;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\CustomerService as ChatCustomerService;
use app\admin\model\shopro\chat\CustomerServiceUser;
use app\admin\model\Admin;
class CustomerService extends Common
{
protected $noNeedRight = ['select'];
protected $adminModel;
public function _initialize()
{
parent::_initialize();
$this->model = new ChatCustomerService;
$this->adminModel = new Admin;
}
/**
* 客服列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$customerService = $this->model->sheepFilter()->with('customer_service_user')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $customerService);
}
/**
* 客服添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['name', 'avatar', 'room_id', 'max_num', 'auth', 'auth_id']);
$this->svalidate($params, ".add");
if ($this->checkHasAuthId($params['auth'], $params['auth_id'], $params['room_id'])) {
error_stop('该身份已绑定其他客服');
}
$data = Db::transaction(function () use ($params) {
$this->model->allowField(true)->save($params);
$customerServiceUser = CustomerServiceUser::create([
'customer_service_id' => $this->model->id,
'auth' => $params['auth'],
'auth_id' => $params['auth_id'],
]);
return $customerServiceUser;
});
$this->success('保存成功', null, $data);
}
/**
* 客服详情
*
* @param $id
*/
public function detail($id)
{
$customerService = $this->model->with(['customer_service_user'])->where('id', $id)->find();
if (!$customerService) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $customerService);
}
/**
* 客服编辑
*
* @param $id
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['name', 'avatar', 'room_id', 'max_num', 'auth', 'auth_id']);
$this->svalidate($params);
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->with('customer_service_user')->select();
Db::transaction(function () use ($list, $params) {
foreach ($list as $customerService) {
$customerService->allowField(true)->save($params);
$customerServiceUser = $customerService['customer_service_user'];
// 编辑了客服身份所有者
if ($params['auth'] != $customerServiceUser['auth'] || $params['auth_id'] != $customerServiceUser['auth_id']) {
// 验证新的身份是否已经被绑定别的客服
if ($this->checkHasAuthId($params['auth'], $params['auth_id'], $params['room_id'])) {
error_stop('该身份已绑定其他客服');
}
// 删除老的身份
CustomerServiceUser::{'auth' . ucfirst($customerServiceUser['auth'])}($customerServiceUser['auth_id'])
->where('customer_service_id', $customerService['id'])->delete();
// 添加新的身份
$customerServiceUser = CustomerServiceUser::create([
'customer_service_id' => $customerService->id,
'auth' => $params['auth'],
'auth_id' => $params['auth_id'],
]);
}
}
});
$this->success('更新成功');
}
/**
* 客服用语
*
* @param $id
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
Db::transaction(function () use ($list) {
foreach ($list as $customerService) {
// 删除客服的身份
CustomerServiceUser::where('customer_service_id', $customerService['id'])->delete();
$customerService->delete();
}
});
$this->success('删除成功');
}
/**
* 检验是否已经被绑定了客服(一个管理员或者用户只能是一种客服)
*
* @param string $auth
* @param integer $auth_id
* @return void
*/
private function checkHasAuthId($auth, $auth_id, $room_id)
{
$customerServiceUser = CustomerServiceUser::{'auth' . ucfirst($auth)}($auth_id)->with('customer_service')->find();
if ($customerServiceUser) {
$customerService = $customerServiceUser['customer_service'];
if ($customerService && $customerService['room_id'] == $room_id) {
return true;
}
}
return false;
}
/**
* 获取管理员列表
*
* @return void
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$id = $this->request->param('id', 0);
$room_id = $this->request->param('room_id', 'admin');
// 已经被设置为客服的管理员
$adminIds = CustomerServiceUser::whereExists(function ($query) use ($room_id) {
$table_name = $this->model->getQuery()->getTable();
$query->table($table_name)->where('room_id', $room_id)->where('customer_service_id=id');
})->where('auth', 'admin')->where('customer_service_id', '<>', $id)->column('auth_id');
// 正常的,并且排除了已经设置为客服的管理员
$admins = $this->adminModel->where('status', 'normal')->whereNotIn('id', $adminIds)->select();
$this->success('获取成功', null, $admins);
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace app\admin\controller\shopro\chat;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\CustomerService;
class Index extends Common
{
protected $noNeedRight = ['init'];
/**
* socket 初始化
*
* @return void
*/
public function init()
{
// 当前管理员
$admin = auth_admin();
$token = $this->getUnifiedToken('admin:' . $admin['id']); // 统一验证 token
// 客服配置
$chatSystem = sheep_config('chat.system');
// 初始化 socket ssl 类型, 默认 cert
$ssl = $chatSystem['ssl'] ?? 'none';
$chat_domain = ($ssl == 'none' ? 'http://' : 'https://') . request()->host(true) . ($ssl == 'reverse_proxy' ? '' : (':' . $chatSystem['port'])) . '/chat';
$data = [
'token' => $token,
'chat_domain' => $chat_domain,
'default_rooms' => CustomerService::defaultRooms()
];
$this->success('获取成功', null, $data);
}
}

View File

@@ -0,0 +1,133 @@
<?php
namespace app\admin\controller\shopro\chat;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\Question as ChatQuestion;
class Question extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new ChatQuestion;
}
/**
* 猜你想问列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$questions = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $questions);
}
/**
* 猜你想问添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['room_id', 'title', 'status', 'weigh']);
$params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params, ".add");
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 猜你想问详情
*
* @param $id
*/
public function detail($id)
{
$question = $this->model->where('id', $id)->find();
if (!$question) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $question);
}
/**
* 猜你想问编辑
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['room_id', 'title', 'status', 'weigh']);
$this->request->has('content') && $params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params);
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除猜你想问
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace app\admin\controller\shopro\chat;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\Record as ChatRecord;
class Record extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new ChatRecord;
}
/**
* 聊天列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$records = $this->model->sheepFilter()->order('id desc')->paginate($this->request->param('list_rows', 10));
$morphs = [
'customer' => \app\admin\model\shopro\chat\User::class,
'customer_service' => \app\admin\model\shopro\chat\CustomerService::class,
];
$records = morph_to($records, $morphs, ['sender_identify', 'sender_id']);
$this->success('获取成功', null, $records);
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace app\admin\controller\shopro\chat;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\chat\User as ChatUser;
use app\admin\model\shopro\chat\ServiceLog;
use app\admin\model\shopro\chat\Record;
class User extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new ChatUser;
}
/**
* 会话列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$user = $this->model->sheepFilter()->with(['user', 'customer_service'])->where('auth', 'user')->order('id desc')->paginate(request()->param('list_rows', 10));
$this->success('获取成功', null, $user);
}
/**·
* 删除会话
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
Db::transaction(function () use ($list) {
foreach ($list as $user) {
// 删除这个会话的所有服务记录
ServiceLog::where('chat_user_id', $user->id)->delete();
// 删除这个会话的所有聊天记录
Record::where('chat_user_id', $user->id)->delete();
// 删除这个会话
$user->delete();
}
});
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,250 @@
<?php
namespace app\admin\controller\shopro\commission;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\Agent as AgentModel;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\shopro\commission\Log as LogModel;
use app\admin\model\shopro\commission\Level as LevelModel;
use addons\shopro\service\commission\Agent as AgentService;
use think\Db;
class Agent extends Common
{
protected $noNeedRight = ['select'];
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new AgentModel();
}
/**
* 查看
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->with(['user.parent_user', 'level_info', 'level_status_info', 'upgrade_level'])->paginate($this->request->param('list_rows', 10));
$this->success('分销商列表', null, $list);
}
/**
* 详情
*
* @param $id
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$detail = $this->model->with(['user.parent_user', 'level_info', 'level_status_info', 'upgrade_level'])->where('user_id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('分销商详情', null, $detail);
}
/**
* 团队
*
* @param $id
*/
public function team($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$detail = $this->model->with(['user.parent_user', 'level_info'])->where('user_id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$detail->agent_team = AgentModel::hasWhere('user', function ($query) use ($detail) {
return $query->where('parent_user_id', $detail->user_id);
})->with(['user', 'level_info'])->select();
$this->success('分销商详情', null, $detail);
}
// 选择分销商
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$data = $this->model->sheepFilter()->with(['user', 'level_info', 'level_status_info', 'upgrade_level'])
->paginate($this->request->param('list_rows', 10));
$this->success('选择分销商', null, $data);
}
/**
* 编辑
*
* @param $id
*/
public function edit($id = null)
{
$params = $this->request->only(['status', 'upgrade_lock', 'level_status', 'level', 'apply_info']);
$result = Db::transaction(function () use ($id, $params) {
$row = $this->model->with(['user', 'level_info', 'level_status_info', 'upgrade_level'])->where('user_id', $id)->find();
if (!$row) {
$this->error('未找到该分销商');
}
foreach ($params as $field => $value) {
switch ($field) {
case 'status': // 修改状态
return $this->changeStatus($row, $value);
break;
case 'level_status': // 审核等级
return $this->changeLevelStatus($row, $value);
break;
case 'level': // 修改等级
return $this->changeLevel($row, $value);
break;
default:
return $row->save([$field => $value]);
}
}
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
// 修改状态
private function changeStatus($row, $value)
{
$result = $row->save(['status' => $value]);
if ($result) {
LogModel::add($row->user_id, 'agent', ['type' => 'status', 'value' => $value]);
(new AgentService($row->user_id))->createAsyncAgentUpgrade();
}
return $result;
}
// 审核等级
private function changeLevelStatus($row, $value)
{
if ($row->level_status == 0 && $value > 0) {
$this->error('非法操作');
}
if ($value == 0) { // 拒绝操作
return $row->save(['level_status' => 0]);
} else { // 同意操作
if ($row->upgrade_level) {
$result = $row->save(['level_status' => 0, 'level' => $row->upgrade_level->level]);
if ($result) {
LogModel::add($row->user_id, 'agent', ['type' => 'level', 'level' => $row->upgrade_level]);
(new AgentService($row->user_id))->createAsyncAgentUpgrade();
}
return $result;
}
}
return false;
}
// 修改等级
private function changeLevel($row, $value)
{
$level = LevelModel::find($value);
if ($level) {
$result = $row->save(['level' => $level->level]);
if ($result) {
LogModel::add($row->user_id, 'agent', ['type' => 'level', 'level' => $level]);
(new AgentService($row->user_id))->createAsyncAgentUpgrade();
}
return $result;
} else {
$this->error('未找到该等级');
}
}
// 更换推荐人
public function changeParentUser($id)
{
$userAgent = new AgentService($id);
if (!$userAgent->user) {
$this->error('未找到该用户');
}
$parentUserId = $this->request->param('parent_user_id', 0);
// 更换推荐人检查
if ($parentUserId != 0) {
$parentAgent = new AgentService($parentUserId);
if (!$parentAgent->isAgentAvaliable()) {
$this->error('选中用户暂未成为分销商,不能成为推荐人');
}
if (!$this->checkChangeParentAgent($id, $parentUserId)) {
$this->error('不能绑定该上级');
}
LogModel::add($parentUserId, 'share', ['user' => $userAgent->user]);
if ($userAgent->isAgentAvaliable()) {
LogModel::add($id, 'bind', ['user' => $parentAgent->user ?? NULL]);
}
}
$lastParentUserId = $userAgent->user->parent_user_id;
$userAgent->user->parent_user_id = $parentUserId;
$userAgent->user->save();
if ($lastParentUserId > 0) {
$userAgent->createAsyncAgentUpgrade($lastParentUserId);
}
if ($parentUserId > 0) {
$userAgent->createAsyncAgentUpgrade($parentUserId);
}
$this->success('绑定成功');
}
// 递归往上找推荐人,防止出现推荐循环
private function checkChangeParentAgent($userId, $parentUserId)
{
if ($userId == $parentUserId) {
$this->error('推荐人不能是本人');
}
if ($parentUserId == 0) {
return true;
}
$parentAgent = UserModel::find($parentUserId);
if ($parentAgent) {
if ($parentAgent->parent_user_id == $userId) {
$this->error("已选中分销商的上级团队中已存在该用户");
}
if ($parentAgent->parent_user_id == 0) {
return true;
} else {
return $this->checkChangeParentAgent($userId, $parentAgent->parent_user_id);
}
}
return false;
}
}

View File

@@ -0,0 +1,89 @@
<?php
namespace app\admin\controller\shopro\commission;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\CommissionGoods as CommissionGoodsModel;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use think\Db;
class Goods extends Common
{
protected $model = null;
protected $goodsModel;
public function _initialize()
{
parent::_initialize();
$this->model = new CommissionGoodsModel();
$this->goodsModel = new GoodsModel();
}
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$data = $this->goodsModel->sheepFilter()->with('commission_goods')->paginate($this->request->param('list_rows', 10));
$this->success('分销商品列表', null, $data);
}
/**
* 详情
*
* @param $id
*/
public function detail($id)
{
$goodsList = collection(GoodsModel::with(['commission_goods'])->whereIn('id', $id)->select())->each(function ($goods) {
$goods->skus = $goods->skus;
$goods->sku_prices = $goods->sku_prices;
});
$config = sheep_config('shop.commission');
$this->success('分销商品详情', null, [
'goods' => $goodsList,
'config' => $config
]);
}
/**
* 设置佣金(支持批量)
*
* @param $id
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
// 接受全部参数
$params = $this->request->only(['status', 'self_rules', 'commission_order_status', 'commission_config', 'commission_rules']);
$result = Db::transaction(function () use ($id, $params) {
$count = 0;
$ids = explode(',', $id);
foreach ($ids as $goods_id) {
if ($row = $this->model->get($goods_id)) {
$row->save($params);
} else {
$model = new CommissionGoodsModel();
$params['goods_id'] = $goods_id;
$model->save($params);
}
$count++;
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace app\admin\controller\shopro\commission;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\Level as LevelModel;
use think\Db;
class Level extends Common
{
protected $noNeedRight = ['select'];
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new LevelModel();
}
/**
* 查看
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$defaultLevel = $this->model->find(1);
if (!$defaultLevel) {
$this->model->save([
'name' => '默认等级',
'level' => 1,
'commission_rules' => [
'commission_1' => '0.00',
'commission_2' => '0.00',
'commission_3' => '0.00'
]
]);
}
$list = $this->model->sheepFilter()->select();
$this->success('全部等级', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['name', 'level', 'image', 'commission_rules', 'upgrade_type', 'upgrade_rules']);
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 编辑
*
* @param $id
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['level', 'name', 'image', 'commission_rules', 'upgrade_type', 'upgrade_rules']);
$result = Db::transaction(function () use ($id, $params) {
$this->svalidate($params);
$data = $this->model->where('level', $id)->find();
if (!$data) {
$this->error(__('No Results were found'));
}
return $data->save($params);
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->get($id);
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('等级详情', null, $detail);
}
/**
* 删除
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$result = Db::transaction(function () use ($id) {
return $this->model->where('level', $id)->delete();
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
// 选择分销商等级
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$data = $this->model->sheepFilter()->field('level, name, image, commission_rules')->select();
$this->success('选择等级', null, $data);
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace app\admin\controller\shopro\commission;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\Log as LogModel;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\Admin as AdminModel;
use addons\shopro\library\Operator;
class Log extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new LogModel();
}
/**
* 查看
*
* @return Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$logs = $this->model->sheepFilter()->with(['agent'])->paginate($this->request->param('list_rows', 10));
$morphs = [
'user' => UserModel::class,
'admin' => AdminModel::class,
'system' => AdminModel::class
];
$logs = morph_to($logs, $morphs, ['oper_type', 'oper_id']);
$logs = $logs->toArray();
// 格式化操作人信息
foreach ($logs['data'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('获取成功', null, $logs);
}
}

View File

@@ -0,0 +1,323 @@
<?php
namespace app\admin\controller\shopro\commission;
use think\Db;
use think\exception\HttpResponseException;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\Order as OrderModel;
use app\admin\model\shopro\commission\Reward as RewardModel;
use addons\shopro\service\commission\Reward as RewardService;
class Order extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new OrderModel();
}
/**
* 查看
*/
public function index()
{
if (!$this->request->isAjax()) {
$exportConfig = (new \addons\shopro\library\Export())->getConfig();
$this->assignconfig("save_type", $exportConfig['save_type'] ?? 'download');
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->with(['buyer', 'agent', 'order', 'rewards.agent', 'order_item'])->paginate($this->request->param('list_rows', 10));
$list = $list->toArray();
// 统计数据
$count = [
'total' => $list['total'],
'total_amount' => 0,
'total_commission' => 0,
'total_commission_cancel' => 0,
'total_commission_accounted' => 0,
'total_commission_back' => 0,
'total_commission_pending' => 0
];
$orders = $this->model->sheepFilter()->with(['rewards'])->select();
collection($orders)->each(function ($order) use (&$count) {
$count['total_amount'] += $order['amount'];
foreach ($order['rewards'] as $reward) {
$count['total_commission'] += $reward['commission'];
switch ($reward['status']) {
case RewardModel::COMMISSION_REWARD_STATUS_ACCOUNTED:
$count['total_commission_accounted'] += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_BACK:
$count['total_commission_back'] += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_PENDING:
$count['total_commission_pending'] += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_CANCEL:
$count['total_commission_cancel'] += $reward['commission'];
break;
}
}
});
$this->success('', null, [
'list' => $list,
'count' => $count
]);
}
/**
* 结算佣金
*
* @return Response
*/
public function confirm()
{
$params = $this->request->only(['commission_reward_id', 'commission_order_id']);
try {
Db::transaction(function () use ($params) {
$rewardService = new RewardService('admin');
if (isset($params['commission_reward_id'])) {
return $rewardService->runCommissionReward($params['commission_reward_id']);
} elseif (isset($params['commission_order_id'])) {
return $rewardService->runCommissionRewardByOrder($params['commission_order_id']);
}
});
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success('操作成功');
}
/**
* 取消结算
*
* @return Response
*/
public function cancel()
{
$params = $this->request->only(['commission_reward_id', 'commission_order_id']);
try {
Db::transaction(function () use ($params) {
$rewardService = new RewardService('admin');
if (isset($params['commission_reward_id'])) {
return $rewardService->cancelCommissionReward($params['commission_reward_id']);
} elseif (isset($params['commission_order_id'])) {
return $rewardService->backCommissionRewardByOrder($params['commission_order_id']);
}
});
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success('操作成功');
}
/**
* 退回已结算佣金
*/
public function back()
{
$params = $this->request->only(['commission_reward_id', 'commission_order_id', 'deduct_order_money']);
try {
Db::transaction(function () use ($params) {
$rewardService = new RewardService('admin');
if (isset($params['commission_reward_id'])) {
return $rewardService->backCommissionReward($params['commission_reward_id']);
} elseif (isset($params['commission_order_id'])) {
return $rewardService->backCommissionRewardByOrder($params['commission_order_id'], $params['deduct_order_money']);
}
});
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success('操作成功');
}
/**
* 修改待结算佣金
*/
public function edit($id = null)
{
$params = $this->request->only(['commission_reward_id', 'commission']);
$reward = RewardModel::get($params['commission_reward_id']);
if (!$reward) {
$this->error(__('No Results were found'));
}
$reward->commission = $params['commission'];
$result = $reward->save();
if ($result) {
$this->success('操作成功');
}
$this->error('操作失败');
}
public function export()
{
$cellTitles = [
// 主要字段
'commission_order_id' => 'Id',
'order_sn' => '订单号',
'goods_title' => '商品名称',
'goods_sku_text' => '商品规格',
'goods_price' => '商品价格',
'goods_num' => '购买数量',
'refund_status_text' => '退款状态',
'buyer_nickname' => '下单用户',
'buyer_mobile' => '手机号',
'share_nickname' => '推广分销商',
'share_mobile' => '手机号',
'commission_reward_status_text' => '佣金状态',
'reward_event_text' => '结算方式',
'commission_time' => '结算时间',
'reward_type_text' => '商品结算方式',
'amount' => '商品结算金额',
'commission_order_status_text' => '分销商业绩',
'total_commission' => '分销总金额',
'total_commissioned' => '到账金额',
// 佣金明细
'reward_agent_nickname' => '分佣用户',
'reward_agent_mobile' => '分佣手机号',
'reward_commission' => '分佣金额',
'reward_status_text' => '分佣状态',
'reward_type_text' => '入账方式',
'reward_commission_time' => '结算时间',
];
// 数据总条数
$total = $this->model->sheepFilter()->count();
if ($total <= 0) {
$this->error('导出数据为空');
}
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '分销订单列表',
'cell_titles' => $cellTitles,
'total' => $total,
'is_sub_cell' => true,
'sub_start_cell' => 'reward_agent_nickname',
'sub_field' => 'rewards'
];
$total_amount = 0;
$total_commission = 0;
$total_commission_cancel = 0;
$total_commission_accounted = 0;
$total_commission_back = 0;
$total_commission_pending = 0;
$result = $export->export($params, function ($pages) use (&$total_amount, &$total_commission, &$total_commission_cancel, &$total_commission_accounted, &$total_commission_back, &$total_commission_pending, $total) {
$datas = $this->model->sheepFilter()->with(['buyer', 'agent', 'order', 'rewards.agent', 'order_item'])
->limit((($pages['page'] - 1) * $pages['list_rows']), $pages['list_rows'])
->select();
$datas = collection($datas);
$datas->each(function ($commissionOrder) use (&$total_amount, &$total_commission, &$total_commission_cancel, &$total_commission_accounted, &$total_commission_back, &$total_commission_pending, $total) {
$total_amount += $commissionOrder['amount'];
foreach ($commissionOrder['rewards'] as $reward) {
$total_commission += $reward['commission'];
switch ($reward['status']) {
case RewardModel::COMMISSION_REWARD_STATUS_ACCOUNTED:
$total_commission_accounted += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_BACK:
$total_commission_back += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_PENDING:
$total_commission_pending += $reward['commission'];
break;
case RewardModel::COMMISSION_REWARD_STATUS_CANCEL:
$total_commission_cancel += $reward['commission'];
break;
}
}
})->toArray();
$newDatas = [];
foreach ($datas as $commissionOrder) {
$commission = 0;
$commissioned = 0;
foreach ($commissionOrder['rewards'] as $reward) {
if ($reward['status'] == 1) {
$commissioned += $reward['commission'];
}
$commission += $reward['commission'];
}
$data = [
'commission_order_id' => $commissionOrder['id'],
'order_sn' => $commissionOrder['order'] ? $commissionOrder['order']['order_sn'] : '',
'goods_title' => $commissionOrder['order_item'] ? '#' . $commissionOrder['order_item']['goods_id'] . ' ' . $commissionOrder['order_item']['goods_title'] : '',
'goods_sku_text' => $commissionOrder['order_item'] ? $commissionOrder['order_item']['goods_sku_text'] : '',
'goods_price' => $commissionOrder['order_item'] ? $commissionOrder['order_item']['goods_price'] : '',
'goods_num' => $commissionOrder['order_item'] ? $commissionOrder['order_item']['goods_num'] : '',
'refund_status_text' => $commissionOrder['order_item'] ? $commissionOrder['order_item']['refund_status_text'] : '',
'buyer_nickname' => $commissionOrder['buyer'] ? $commissionOrder['buyer']['nickname'] : '-',
'buyer_mobile' => $commissionOrder['buyer'] ? $commissionOrder['buyer']['mobile'] . ' ' : '-',
'share_nickname' => $commissionOrder['agent'] ? $commissionOrder['agent']['nickname'] : '-',
'share_mobile' => $commissionOrder['agent'] ? $commissionOrder['agent']['mobile'] . ' ' : '-',
// 这里循环 rewards 佣金详情
'commission_reward_status_text' => $commissionOrder['commission_reward_status_text'],
'reward_event_text' => $commissionOrder['reward_event_text'],
'commission_time' => $commissionOrder['commission_time'],
'reward_type_text' => $commissionOrder['reward_type_text'],
'amount' => $commissionOrder['amount'],
'commission_order_status_text' => $commissionOrder['commission_order_status_text'],
'total_commission' => $commission,
'total_commissioned' => $commissioned,
];
$rewardsItems = [];
foreach ($commissionOrder['rewards'] as $reward) {
$rewardsItems[] = [
'reward_agent_nickname' => $reward['agent'] ? $reward['agent']['nickname'] : '',
'reward_agent_mobile' => $reward['agent'] ? $reward['agent']['mobile'] : '',
'reward_commission' => $reward['commission'],
'reward_status_text' => $reward['status_text'],
'reward_type_text' => $reward['type_text'],
'reward_commission_time' => $reward['commission_time']
];
}
$data['rewards'] = $rewardsItems;
$newDatas[] = $data;
}
if ($pages['is_last_page']) {
$newDatas[] = ['order_id' => "商品总订单数:" . $total . ";商品结算总金额:¥" . $total_amount . ";分佣总金额:¥" . $total_commission . ";已取消佣金:¥" . $total_commission_cancel . ";已退回佣金:¥" . $total_commission_back . ";未结算佣金:" . $total_commission_pending . ";已结算佣金:" . $total_commission_accounted];
}
return $newDatas;
});
$this->success('导出成功' . (isset($result['file_path']) && $result['file_path'] ? ',请在服务器: “' . $result['file_path'] . '” 查看' : ''), null, $result);
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace app\admin\controller\shopro\commission;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\commission\Reward as RewardModel;
class Reward extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new RewardModel();
}
/**
* 查看
*/
public function index()
{
if (!$this->request->isAjax()) {
$exportConfig = (new \addons\shopro\library\Export())->getConfig();
$this->assignconfig("save_type", $exportConfig['save_type'] ?? 'download');
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->with(['buyer', 'agent', 'order', 'order_item'])->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $list);
}
public function export()
{
$cellTitles = [
'reward_id' => 'Id',
'order_sn' => '订单号',
'buyer_nickname' => '下单用户',
'buyer_mobile' => '手机号',
'agent_nickname' => '分销用户',
'agent_mobile' => '分销手机号',
'original_commission' => '原始佣金',
'commission' => '分销佣金',
'commission_level' => '执行层级',
'agent_level' => '执行等级',
'status_text' => '状态',
'type_text' => '入账方式',
'commission_time' => '结算时间'
];
// 数据总条数
$total = $this->model->sheepFilter()->count();
if ($total <= 0) {
$this->error('导出数据为空');
}
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '佣金明细列表',
'cell_titles' => $cellTitles,
'total' => $total,
'is_sub_cell' => false,
];
$total_commission = 0;
$result = $export->export($params, function ($pages) use (&$total_commission, $total) {
$datas = $this->model->sheepFilter()->with(['buyer', 'agent', 'order', 'order_item'])
->limit((($pages['page'] - 1) * $pages['list_rows']), $pages['list_rows'])
->select();
$datas = collection($datas);
$datas->each(function ($order) {
})->toArray();
$newDatas = [];
foreach ($datas as &$reward) {
$data = [
'reward_id' => $reward['id'],
'order_sn' => $reward['order'] ? $reward['order']['order_sn'] : '',
'buyer_nickname' => $reward['buyer'] ? $reward['buyer']['nickname'] : '-',
'buyer_mobile' => $reward['buyer'] ? $reward['buyer']['mobile'] . ' ' : '-',
'agent_nickname' => $reward['agent'] ? $reward['agent']['nickname'] : '-',
'agent_mobile' => $reward['agent'] ? $reward['agent']['mobile'] . ' ' : '-',
'original_commission' => $reward['original_commission'],
'commission' => $reward['commission'],
'commission_level' => $reward['commission_level'],
'agent_level' => $reward['agent_level'],
'status_text' => $reward['status_text'],
'type_text' => $reward['type_text'],
'commission_time' => $reward['commission_time'],
];
$newDatas[] = $data;
}
$total_commission += array_sum(array_column($newDatas, 'commission'));
if ($pages['is_last_page']) {
$newDatas[] = ['reward_id' => "总数:" . $total . ";总佣金金额:¥" . $total_commission . ""];
}
return $newDatas;
});
$this->success('导出成功' . (isset($result['file_path']) && $result['file_path'] ? ',请在服务器: “' . $result['file_path'] . '” 查看' : ''), null, $result);
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 地区管理
*/
class Area extends Common
{
protected $noNeedRight = ['select'];
/**
* Faq模型对象
* @var \app\admin\model\shopro\data\Express
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\Area;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->with('children.children')->where('pid', 0)->select(); // 查询全部
$this->success('', null, $list);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$level = $this->request->param('level', 'all');
$with = ['children.children'];
if ($level == 'city') {
$with = ['children'];
} else if ($level == 'province') {
$with = [];
}
$list = $this->model->with($with)->where('pid', 0)->field('id, name, pid, level')->select(); // 查询全部
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['id', 'pid', 'name']);
$params['level'] = 'province';
if (isset($params['pid']) && $params['pid']) {
$parent = $this->model->find($params['pid']);
if (!$parent) {
$this->error(__('No Results were found'));
}
if ($parent['level'] == 'province') {
$params['level'] = 'city';
} else if ($parent['level'] == 'city') {
$params['level'] = 'district';
}
}
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($old_id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['id', 'pid', 'name']);
$params['level'] = 'province';
if (isset($params['pid']) && $params['pid']) {
$parent = $this->model->find($params['pid']);
if (!$parent) {
$this->error(__('No Results were found'));
}
if ($parent['level'] == 'province') {
$params['level'] = 'city';
} else if ($parent['level'] == 'city') {
$params['level'] = 'district';
}
}
$area = $this->model->where('id', 'in', $old_id)->find();
if (!$area) {
$this->error(__('No Results were found'));
}
$area->save($params);
$this->success('更新成功', null, $area);
}
/**
* 删除
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$area = $this->model->where('id', 'in', $id)->find();
if (!$area) {
$this->error(__('No Results were found'));
}
$children = $this->model->where('pid', $id)->count();
if ($children) {
$this->error('请先删除下级地市');
}
$area->delete();
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 快递公司
*/
class Express extends Common
{
protected $noNeedRight = ['select'];
/**
* Faq模型对象
* @var \app\admin\model\shopro\data\Express
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\Express;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->request('list_rows', 10));
$this->success('', null, $list);
}
/**
* 选择快递公司
*
* @return void
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['name', 'code', 'weigh']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['name', 'code', 'weigh']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,222 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 虚拟用户
*/
class FakeUser extends Common
{
protected $noNeedRight = ['select', 'getRandom'];
/**
* Faq模型对象
* @var \app\admin\model\shopro\data\Express
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\FakeUser;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('', null, $list);
}
/**
* 随机获取一个虚拟用户
*
* @return void
*/
public function getRandom()
{
$userFake = $this->model->orderRaw('rand()')->find();
$userFake ? $this->success('获取成功', null, $userFake) : $this->error('请在数据维护中添加虚拟用户');
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['username', 'nickname', 'mobile', 'password', 'avatar', 'gender', 'email']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 随机生成用户
*/
public function random()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
set_time_limit(0);
$num = $this->request->param('num', 1);
for ($i = 0; $i < $num; $i++) {
$style = [
'adventurer',
'adventurer-neutral',
'big-smile',
'big-ears-neutral',
'bottts',
'croodles',
'croodles-neutral',
'fun-emoji',
'icons',
'identicon',
'lorelei',
'lorelei-neutral',
'micah',
'notionists'
];
$username = gen_random_str(mt_rand(6, 15), mt_rand(0, 1));
$avatarSources = [
// "https://joeschmoe.io/api/v1/random", // 生成的是 svg ,无法使用
"https://api.dicebear.com/7.x/%s/png" . "?seed=" . $username . '&size=256',
"https://api.multiavatar.com/" . $username . ".png"
];
$avatar_url = $avatarSources[array_rand($avatarSources)];
$avatar_url = sprintf($avatar_url, $style[array_rand($style)]);
$store_path = '/uploads/' . date('Ymd') . '/' . md5(time() . mt_rand(1000, 9999)) . '.png'; // 存数据库路径
$save_path = ROOT_PATH . 'public' . $store_path; // 服务器绝对路径
image_resize_save($avatar_url, $save_path);
$fakeUser = new \app\admin\model\shopro\data\FakeUser();
$fakeUser->username = $username;
$fakeUser->nickname = $username;
$fakeUser->mobile = random_mobile();
$fakeUser->password = gen_random_str();
$fakeUser->avatar = cdnurl($store_path, true); // 这里存了完整路径
$fakeUser->gender = mt_rand(0, 1);
$fakeUser->email = random_email($fakeUser->mobile);
$fakeUser->save();
}
$this->success('生成成功');
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['username', 'nickname', 'mobile', 'password', 'avatar', 'gender', 'email']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 常见问题
*/
class Faq extends Common
{
/**
* Faq模型对象
* @var \app\admin\model\shopro\data\Faq
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\Faq;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->request('list_rows', 10));
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['title', 'content', 'status']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['title', 'content', 'status']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 前端路由
*/
class Page extends Common
{
protected $noNeedRight = ['select'];
/**
* Page模型对象
* @var \app\admin\model\shopro\data\Page
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\Page;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->request('list_rows', 10));
$this->success('', null, $list);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->group('group')->with(['children'])->field('group')->select();
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['name', 'path', 'group']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['name', 'path', 'group']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace app\admin\controller\shopro\data;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 富文本
*/
class Richtext extends Common
{
protected $noNeedRight = ['select'];
/**
* Richtext模型对象
* @var \app\admin\model\shopro\data\Richtext
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\data\Richtext;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->paginate($this->request->request('list_rows', 10));
$this->success('', null, $list);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type', 'page');
$list = $this->model->sheepFilter();
if ($type == 'select') {
// 普通结果
$list = $list->select();
} elseif ($type == 'find') {
$list = $list->find();
} else {
// 分页结果
$list = $list->paginate($this->request->request('list_rows', 10));
}
$this->success('', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['title', 'content']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only(['title', 'content']);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace app\admin\controller\shopro\decorate;
use app\admin\controller\shopro\Common;
use think\Db;
use app\admin\model\shopro\decorate\Decorate as DecorateModel;
use app\admin\model\shopro\decorate\Page as PageModel;
class Designer extends Common
{
/**
* 使用设计师模板
*/
public function use()
{
$params = $this->request->param();
Db::transaction(function () use ($params) {
$decorate = DecorateModel::create([
'name' => $params['name'],
'type' => $params['type'],
'memo' => $params['memo'],
'platform' => $params['platform'],
'status' => 'disabled'
]);
$pageList = [];
$params['page'] = json_decode($params['page'], true);
foreach ($params['page'] as $page) {
array_push($pageList, [
'decorate_id' => $decorate->id,
'image' => $page['image'] ?? '',
'type' => $page['type'],
'page' => json_encode($page['page'], JSON_UNESCAPED_UNICODE)
]);
}
PageModel::insertAll($pageList);
$this->downLoadDecorateImages($params['imageList']);
});
$this->success();
}
private function downLoadDecorateImages($imageList)
{
\think\Queue::push('\addons\shopro\job\Designer@redeposit', ['imageList' => $imageList], 'shopro');
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace app\admin\controller\shopro\decorate;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\decorate\Page as PageModel;
class Page extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new PageModel();
}
/**
* 页面列表
*/
public function index()
{
return $this->view->fetch();
}
/**
* 页面详情
*
* @param int $id
*/
public function detail($id)
{
$type = $this->request->param('type');
$page = $this->model->where(['decorate_id' => $id, 'type' => $type])->find();
$this->success('获取成功', null, $page);
}
/**
* 编辑
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
$type = $this->request->param('type');
$page = $this->request->param('page');
$image = $this->request->param('image');
$pageRow = PageModel::where(['decorate_id' => $id, 'type' => $type])->find();
operate_filter();
if ($pageRow) {
$pageRow->page = $page;
$pageRow->image = $image;
$pageRow->save();
} else {
PageModel::create([
'decorate_id' => $id,
'type' => $type,
'page' => $page,
'image' => $image
]);
}
$this->success('保存成功');
}
/**
* 预览
*/
public function preview()
{
return $this->view->fetch();
}
}

View File

@@ -0,0 +1,286 @@
<?php
namespace app\admin\controller\shopro\decorate;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\decorate\Decorate as DecorateModel;
use app\admin\model\shopro\decorate\Page as PageModel;
class Template extends Common
{
protected $model = null;
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->model = new DecorateModel();
}
/**
* 查看
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->sheepFilter()->with(['page' => function ($query) {
return $query->where('type', 'in', ['home', 'user', 'diypage'])->field('decorate_id, type, image');
}])->select();
$this->success('获取成功', null, $list);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['type', 'name', 'memo', 'platform']);
$this->svalidate($params, '.add');
$this->model->save($params);
$this->success('保存成功', null, $this->model);
}
/**
* 详情
*
* @param $id
*/
public function detail($id)
{
$detail = $this->model->where('id', $id)->find();
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
operate_filter();
$params = $this->request->only([
'type', 'name', 'memo', 'platform'
]);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$this->svalidate($params);
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 复制
*
* @param $id
*/
public function copy($id)
{
$template = $this->model->where('id', $id)->find();
if (!$template) {
$this->error(__('No Results were found'));
}
Db::transaction(function () use ($template) {
$params = [
'name' => '复制 ' . $template->name,
'type' => $template->type,
'memo' => $template->memo,
'platform' => $template->platform,
'status' => 'disabled'
];
$newTemplate = $this->model->create($params);
$pageList = PageModel::where('decorate_id', $template->id)->select();
$newPageList = [];
foreach ($pageList as $page) {
$newPageList[] = [
'decorate_id' => $newTemplate->id,
'type' => $page['type'],
'page' => json_encode($page['page']),
'image' => $page['image']
];
}
if (count($newPageList) > 0) {
PageModel::insertAll($newPageList);
}
});
$this->success('复制成功');
}
/**
* 启用/禁用
*
* @param $id
*/
public function status($id)
{
$status = $this->request->param('status');
$template = $this->model->where('id', $id)->find();
if (!$template) {
$this->error(__('No Results were found'));
}
operate_filter();
$template->status = $status;
$template->save();
$this->success('操作成功', null, $template);
}
/**
* 删除(支持批量)
*
* @param $id
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
operate_filter();
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$templates = $this->model->onlyTrashed()->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $templates);
}
/**
* 还原(支持批量)
*
* @param $id
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$items = $this->model->onlyTrashed()->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
$count += $item->restore();
}
return $count;
});
if ($result) {
$this->success('还原成功', null, $result);
} else {
$this->error(__('No rows were updated'));
}
}
/**
* 销毁(支持批量)
*
* @param $id
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
if ($id !== 'all') {
$items = $this->model->onlyTrashed()->whereIn('id', $id)->select();
} else {
$items = $this->model->onlyTrashed()->select();
}
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
PageModel::where('decorate_id', $item->id)->delete();
// 删除商品
$count += $item->delete(true);
}
return $count;
});
if ($result) {
$this->success('销毁成功', null, $result);
}
$this->error('销毁失败');
}
/**
* 选择自定义页面
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list = $this->model->where('type', 'diypage')->with(['page' => function ($query) {
return $query->field('decorate_id, type, image');
}])->select();
$this->success('获取成功', null, $list);
}
}

View File

@@ -0,0 +1,232 @@
<?php
namespace app\admin\controller\shopro\dispatch;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\dispatch\Dispatch as DispatchModel;
use app\admin\model\shopro\dispatch\DispatchExpress as DispatchExpressModel;
use app\admin\model\shopro\dispatch\DispatchAutosend as DispatchAutosendModel;
/**
* 配送管理
*/
class Dispatch extends Common
{
protected $noNeedRight = ['select'];
protected $expressModel;
protected $autosendModel;
protected $dispatch_type;
public function _initialize()
{
parent::_initialize();
$this->model = new DispatchModel;
$this->expressModel = new DispatchExpressModel;
$this->autosendModel = new DispatchAutosendModel;
$this->dispatch_type = $this->request->param('type', 'express');
}
/**
* 配送方式列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$dispatchs = $this->model->sheepFilter()->with([$this->dispatch_type])->where('type', $this->dispatch_type)->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $dispatchs);
}
/**
* 添加配送方式
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'name', 'type', 'status', 'express', 'autosend'
]);
$this->svalidate($params, ".add");
$data = $params[$this->dispatch_type] ?? [];
unset($params['express'], $params['autosend']);
if ($this->dispatch_type == 'express') {
// 验证 express
foreach ($data as $key => $express) {
$this->svalidate($express, '.express');
}
} else if ($this->dispatch_type == 'autosend') {
// 验证 autosend
$this->svalidate($data, '.autosend');
}
Db::transaction(function () use ($params, $data) {
unset($params['createtime'], $params['updatetime'], $params['id']); // 删除时间
$this->model->allowField(true)->save($params);
if ($this->dispatch_type == 'express') {
foreach ($data as $key => $express) {
$express['dispatch_id'] = $this->model->id;
$expressModel = new DispatchExpressModel();
unset($express['createtime'], $express['updatetime'], $express['id']); // 删除时间
$expressModel->allowField(true)->save($express);
}
} else if ($this->dispatch_type == 'autosend') {
$data['dispatch_id'] = $this->model->id;
$autosendModel = new DispatchAutosendModel();
unset($data['createtime'], $data['updatetime'], $data['id']); // 删除时间
$autosendModel->allowField(true)->save($data);
}
});
$this->success('保存成功');
}
/**
* 配送方式详情
*
* @param $id
*/
public function detail($id)
{
$dispatch = $this->model->with([$this->dispatch_type])->where('type', $this->dispatch_type)->where('id', $id)->find();
if (!$dispatch) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $dispatch);
}
/**
* 修改配送方式
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'name', 'type', 'status', 'express', 'autosend'
]);
$this->svalidate($params);
$data = $params[$this->dispatch_type] ?? [];
unset($params['express'], $params['autosend']);
if ($this->dispatch_type == 'express') {
// 验证 express
foreach ($data as $key => $express) {
$this->svalidate($express, '.express');
}
} else if ($this->dispatch_type == 'autosend') {
// 验证 autosend
$this->svalidate($data, '.autosend');
}
$id = explode(',', $id);
$lists = $this->model->whereIn('id', $id)->select();
Db::transaction(function () use ($lists, $params, $data) {
foreach ($lists as $dispatch) {
$dispatch->allowField(true)->save($params);
if ($data) {
if ($this->dispatch_type == 'express') {
// 修改,不是只更新状态
$expressIds = array_column($data, 'id');
DispatchExpressModel::where('dispatch_id', $dispatch->id)->whereNotIn('id', $expressIds)->delete(); // 先删除被删除的记录
foreach ($data as $key => $express) {
if (isset($express['id']) && $express['id']) {
$expressModel = $this->expressModel->find($express['id']);
} else {
$expressModel = new DispatchExpressModel();
$express['dispatch_id'] = $dispatch->id;
}
$express['weigh'] = count($data) - $key; // 权重
unset($express['createtime'], $express['updatetime']);
$expressModel && $expressModel->allowField(true)->save($express);
}
} else if ($this->dispatch_type == 'autosend') {
if (isset($data['id']) && $data['id']) {
$autosendModel = $this->autosendModel->find($data['id']);
} else {
$autosendModel = new DispatchAutosendModel();
$data['dispatch_id'] = $dispatch->id;
}
unset($data['createtime'], $data['updatetime']); // 删除时间
$autosendModel->allowField(true)->save($data);
}
}
}
});
$this->success('更新成功');
}
/**
* 删除配送方式
*
* @param string $id 要删除的配送方式列表
* @return void
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->with([$this->dispatch_type])->where('type', $this->dispatch_type)->where('id', 'in', $id)->select();
Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
if ($this->dispatch_type == 'express') {
// 删除相关的 express 数据
foreach ($item->express as $express) {
$express->delete();
}
} else if ($this->dispatch_type == 'autosend') {
$item->{$this->dispatch_type}->delete();
}
$count += $item->delete();
}
return $count;
});
$this->success('删除成功');
}
/**
* 获取所有配送模板
*/
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$dispatchs = $this->model->sheepFilter()->field('id, name, type, status')->normal()->where('type', $this->dispatch_type)->select();
$this->success('获取成功', null, $dispatchs);
}
}

View File

@@ -0,0 +1,247 @@
<?php
namespace app\admin\controller\shopro\goods;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\goods\Comment as CommentModel;
use app\admin\model\shopro\data\FakeUser as FakeUserModel;
class Comment extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new CommentModel;
}
/**
* 商品评价列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$comments = $this->model->sheepFilter()->with(['goods' => function ($query) {
$query->field('id,image,title');
}, 'order' => function ($query) {
$query->removeOption('soft_delete');
}, 'order_item'])->paginate($this->request->param('list_rows', 10));
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'fake_user' => \app\admin\model\shopro\data\FakeUser::class
];
$comments = morph_to($comments, $morphs, ['user_type', 'user_id']);
$this->success('获取成功', null, $comments);
}
public function detail($id)
{
$comment = $this->model->with(['admin', 'goods' => function ($query) {
$query->field('id,image,title,price');
}, 'order' => function ($query) {
$query->removeOption('soft_delete');
}, 'order_item'])->where('id', $id)->find();
if (!$comment) {
$this->error(__('No Results were found'));
}
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'fake_user' => \app\admin\model\shopro\data\FakeUser::class
];
$comments = morph_to([$comment], $morphs, ['user_type', 'user_id']);
$this->success('获取成功', null, $comments->all()[0]);
}
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'goods_id', 'user_id', 'level', 'content', 'images', 'status'
]);
$params['user_type'] = 'fake_user';
$this->svalidate($params, ".add");
$fakeUser = FakeUserModel::find($params['user_id']);
$params['user_nickname'] = $fakeUser ? $fakeUser->nickname : null;
$params['user_avatar'] = $fakeUser ? $fakeUser->avatar : null;
Db::transaction(function () use ($params) {
$this->model->save($params);
});
$this->success('保存成功');
}
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'status'
]);
$id = explode(',', $id);
$list = $this->model->whereIn('id', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $comment) {
$comment->status = $params['status'] ?? 'hidden';
$count += $comment->save();
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
public function reply($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'content'
]);
$this->svalidate($params, '.reply');
$comment = $this->model->noReply()->find($id);
if (!$comment) {
$this->error(__('No Results were found'));
}
$comment->reply_content = $params['content'];
$comment->reply_time = time();
$comment->admin_id = $this->auth->id;
$comment->save();
$this->success('回复成功');
}
/**
* 删除商品评价
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
$this->success('删除成功');
}
/**
* 评价回收站
*
* @return void
*/
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$comments = $this->model->onlyTrashed()->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $comments);
}
/**
* 还原(支持批量)
*
* @param $id
* @return \think\Response
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$items = $this->model->onlyTrashed()->where('id', 'in', $id)->select();
Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
$count += $item->restore();
}
return $count;
});
$this->success('还原成功');
}
/**
* 销毁(支持批量)
*
* @param $id
* @return \think\Response
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
if ($id !== 'all') {
$items = $this->model->onlyTrashed()->whereIn('id', $id)->select();
} else {
$items = $this->model->onlyTrashed()->select();
}
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $comment) {
// 删除评价
$count += $comment->delete(true);
}
return $count;
});
if ($result) {
$this->success('销毁成功', null, $result);
}
$this->error('销毁失败');
}
}

View File

@@ -0,0 +1,444 @@
<?php
namespace app\admin\controller\shopro\goods;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\goods\Sku as SkuModel;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use app\admin\model\shopro\goods\StockWarning as StockWarningModel;
use app\admin\model\shopro\activity\Activity as ActivityModel;
use app\admin\controller\shopro\traits\SkuPrice as SkuPriceTrait;
use addons\shopro\traits\StockWarning as StockWarningTrait;
use addons\shopro\service\goods\GoodsService;
use think\Db;
/**
* 商品管理
*/
class Goods extends Common
{
use SkuPriceTrait, StockWarningTrait;
protected $noNeedRight = ['getType', 'select', 'activitySelect'];
/**
* 商品模型对象
* @var \app\admin\model\shopro\goods\Goods
*/
protected $model = null;
protected $activityModel = null;
public function _initialize()
{
parent::_initialize();
$this->model = new GoodsModel;
$this->activityModel = new ActivityModel;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$goodsTableName = $this->model->getQuery()->getTable();
$goods = $this->model->sheepFilter()->with(['max_sku_price']);
// 聚合库存 (包含下架的规格)
$skuSql = SkuPriceModel::field('sum(stock) as stock, goods_id as sku_goods_id')->group('goods_id')->buildSql();
$goods = $goods->join([$skuSql => 'sp'], $goodsTableName . '.id = sp.sku_goods_id', 'left')
->field("$goodsTableName.*, sp.stock") // ,score.*
->paginate($this->request->param('list_rows', 10))->each(function ($goods) {
// 获取活动信息
$goods->activities = $goods->activities;
$goods->promos = $goods->promos;
$data_type = request()->param('data_type', ''); // 特殊 type 需要处理的数据
if ($data_type == 'score_shop') {
$goods->is_score_shop = $goods->is_score_shop;
}
});
$this->success('获取成功', null, $goods);
}
// 获取数据类型
public function getType()
{
$activityTypes = $this->activityModel->typeList();
$statusList = $this->model->statusList();
$result = [
'activity_type' => $activityTypes,
'status' => $statusList
];
$data = [];
foreach ($result as $key => $list) {
$data[$key][] = ['name' => '全部', 'type' => 'all'];
foreach ($list as $k => $v) {
$data[$key][] = [
'name' => $v,
'type' => $k
];
}
}
$this->success('获取成功', null, $data);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'type', 'title', 'subtitle', 'category_ids', 'image', 'images', 'image_wh', 'params',
'original_price', 'price', 'is_sku', 'limit_type', 'limit_num', 'sales_show_type',
'stock_show_type', 'show_sales', 'service_ids', 'dispatch_type', 'dispatch_id', 'is_offline', 'status', 'weigh',
]); // likes, views, sales,
$params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params, ".add");
if (!$params['is_sku']) {
// 校验单规格属性
$sku_params = $this->request->only(['stock', 'stock_warning', 'sn', 'weight', 'cost_price', 'original_price', 'price']);
$this->svalidate($sku_params, '.sku_params');
}
$data = Db::transaction(function () use ($params) {
$this->model->save($params);
$this->editSku($this->model, 'add');
});
$this->success('保存成功', null, $data);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$goods = $this->model->where('id', $id)->find();
if (!$goods) {
$this->error(__('No Results were found'));
}
$goods->category_ids_arr = $goods->category_ids_arr;
if ($goods->is_sku) {
$goods->skus = $goods->skus;
$goods->sku_prices = $goods->sku_prices;
} else {
// 将单规格的部分数据直接放到 row 上
$goodsSkuPrice = SkuPriceModel::where('goods_id', $id)->order('id', 'asc')->find();
$goods->stock = $goodsSkuPrice->stock;
$goods->sn = $goodsSkuPrice->sn;
$goods->weight = $goodsSkuPrice->weight;
$goods->stock_warning = $goodsSkuPrice->stock_warning;
$goods->cost_price = $goodsSkuPrice->cost_price;
}
$content = $goods['content'];
$goods = $goods->toArray();
$goods['content'] = $content;
$this->success('保存成功', null, $goods);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'type', 'title', 'subtitle', 'image', 'images', 'image_wh', 'params',
'original_price', 'price', 'is_sku', 'limit_type', 'limit_num', 'sales_show_type',
'stock_show_type', 'show_sales', 'service_ids', 'dispatch_type', 'dispatch_id', 'is_offline', 'status', 'weigh',
]); // likes, views, sales,
$this->request->has('content') && $params['content'] = $this->request->param('content', '', null); // content 不经过全局过滤
$this->svalidate($params);
isset($params['is_sku']) && $params['category_ids'] = $this->request->param('category_ids', ''); // 分类不判空
isset($params['is_sku']) && $params['params'] = $this->request->param('params/a', []); // 编辑如果没有传 params 赋值为空
if (isset($params['is_sku']) && !$params['is_sku']) {
// 校验单规格属性
$sku_params = $this->request->only(['stock_warning', 'sn', 'weight', 'cost_price', 'original_price', 'price']);
$this->svalidate($sku_params, 'sku_params');
}
$id = explode(',', $id);
$items = $this->model->whereIn('id', $id)->select();
Db::transaction(function () use ($items, $params) {
foreach ($items as $goods) {
$goods->save($params);
if (isset($params['is_sku'])) {
// 编辑商品(如果没有 is_sku 就是批量编辑上下架等)
$this->editSku($goods, 'edit');
}
}
});
$this->success('更新成功', null);
}
public function addStock($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$goods = $this->model->where('id', $id)->find();
if (!$goods) {
$this->error(__('No Results were found'));
}
if ($goods->is_sku) {
// 多规格
$skuPrices = $this->request->post('sku_prices/a', []);
foreach ($skuPrices as $skuPrice) {
if (isset($skuPrice['add_stock']) && $skuPrice['add_stock'] != 0 && $skuPrice['id']) {
$skuPriceModel = SkuPriceModel::where('goods_id', $id)->order('id', 'asc')->find($skuPrice['id']);
if ($skuPriceModel) {
Db::transaction(function () use ($skuPriceModel, $skuPrice) {
$this->addStockToSkuPrice($skuPriceModel, $skuPrice['add_stock'], 'goods');
});
}
}
}
} else {
$add_stock = $this->request->param('add_stock', 0);
$skuPriceModel = SkuPriceModel::where('goods_id', $id)->order('id', 'asc')->find();
if ($skuPriceModel) {
Db::transaction(function () use ($skuPriceModel, $add_stock) {
$this->addStockToSkuPrice($skuPriceModel, $add_stock, 'goods');
});
}
}
$this->success('补货成功');
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$type = $this->request->param('type', 'page');
$goodsTableName = $this->model->getQuery()->getTable();
$goods = $this->model->sheepFilter()->with(['max_sku_price']);
// 聚合库存 (包含下架的规格)
$skuSql = SkuPriceModel::field('sum(stock) as stock, goods_id as sku_goods_id')->group('goods_id')->buildSql();
$goods = $goods->join([$skuSql => 'sp'], $goodsTableName . '.id = sp.sku_goods_id', 'left')
->field("$goodsTableName.*, sp.stock"); // ,score.*
if ($type == 'select') {
// 普通结果
$goods = collection($goods->select());
} else {
// 分页结果
$goods = $goods->paginate($this->request->param('list_rows', 10));
}
$goods = $goods->each(function ($goods) {
// 获取活动信息
$goods->activities = $goods->activities;
$goods->promos = $goods->promos;
$data_type = $this->request->param('data_type', ''); // 特殊 type 需要处理的数据
if ($data_type == 'score_shop') {
$goods->is_score_shop = $goods->is_score_shop;
}
});
$this->success('获取成功', null, $goods);
}
/**
* 获取指定活动相关商品
*
* @param Request $request
* @return void
*/
public function activitySelect()
{
$activity_id = $this->request->param('activity_id');
$need_buyers = $this->request->param('need_buyers', 0); // 需要查询哪些人在参与活动
$activity = $this->activityModel->where('id', $activity_id)->find();
if (!$activity) {
$this->error(__('No Results were found'));
}
$goodsIds = $activity->goods_ids ? explode(',', $activity->goods_ids) : [];
// 存一下,获取器获取指定活动的时候会用到
foreach ($goodsIds as $id) {
session('goods-activity_id:' . $id, $activity_id);
}
$service = new GoodsService(function ($goods) use ($need_buyers) {
if ($need_buyers) {
$goods->buyers = $goods->buyers;
}
$goods->activity = $goods->activity;
return $goods;
});
$goods = $service->activity($activity_id)->whereIds($goodsIds)->show()->select();
$goods = collection($goods)->toArray(); // 可以将里面的单个 model也转为数组
foreach ($goods as &$gd) {
unset($gd['new_sku_prices'], $gd['activity']);
}
$this->success('获取成功', null, $goods);
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
// 删除相关库存预警记录
StockWarningModel::destroy(function ($query) use ($item) {
$query->where('goods_id', $item->id);
});
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
public function recyclebin()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$goods = $this->model->onlyTrashed()->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $goods);
}
/**
* 还原(支持批量)
*
* @param $id
* @return \think\Response
*/
public function restore($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$items = $this->model->onlyTrashed()->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $item) {
$count += $item->restore();
}
return $count;
});
if ($result) {
$this->success('还原成功', null, $result);
} else {
$this->error(__('No rows were updated'));
}
}
/**
* 销毁(支持批量)
*
* @param $id
* @return \think\Response
*/
public function destroy($id = null)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
if ($id !== 'all') {
$items = $this->model->onlyTrashed()->whereIn('id', $id)->select();
} else {
$items = $this->model->onlyTrashed()->select();
}
$result = Db::transaction(function () use ($items) {
$count = 0;
foreach ($items as $goods) {
// 删除商品相关的规格,规格记录
SkuModel::where('goods_id', $goods->id)->delete();
SkuPriceModel::where('goods_id', $goods->id)->delete();
// 删除商品
$count += $goods->delete(true);
}
return $count;
});
if ($result) {
$this->success('销毁成功', null, $result);
}
$this->error('销毁失败');
}
}

View File

@@ -0,0 +1,157 @@
<?php
namespace app\admin\controller\shopro\goods;
use app\admin\controller\shopro\Common;
use think\Db;
use app\admin\model\shopro\goods\Service as ServiceModel;
/**
* 服务保障
*/
class Service extends Common
{
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->model = new ServiceModel;
}
/**
* 服务保障列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$services = $this->model->sheepFilter()->paginate(request()->param('list_rows', 10));
$this->success('获取成功', null, $services);
}
/**
* 添加服务保障
*
* @return \think\Response
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only([
'name', 'image', 'description'
]);
$this->svalidate($params, ".add");
Db::transaction(function () use ($params) {
$this->model->save($params);
});
$this->success('保存成功');
}
/**
* 服务保障详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$service = $this->model->where('id', $id)->find();
if (!$service) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $service);
}
/**
* 修改服务保障
*
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$params = $this->request->only([
'name', 'image', 'description'
]);
$this->svalidate($params, ".edit");
$id = explode(',', $id);
$list = $this->model->whereIn('id', $id)->select();
$result = Db::transaction(function () use ($list, $params) {
$count = 0;
foreach ($list as $item) {
$params['id'] = $item->id;
$count += $item->save($params);
}
return $count;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败,未改变任何记录');
}
}
/**
* 删除服务标签
*
* @param string $id 要删除的服务保障列表
* @return void
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
$this->success('删除成功');
}
/**
* 获取所有服务列表
*
* @return \think\Response
*/
public function select()
{
$services = $this->model->field('id, name')->select();
$this->success('获取成功', null, $services);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace app\admin\controller\shopro\goods;
use app\admin\controller\shopro\Common;
use think\Db;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
class SkuPrice extends Common
{
protected $noNeedRight = ['index'];
public function _initialize()
{
parent::_initialize();
$this->model = new SkuPriceModel;
}
/**
* skuPrices列表
*
* @return \think\Response
*/
public function index()
{
$goods_id = $this->request->param('goods_id');
$skuPrices = $this->model->where('goods_id', $goods_id)->select();
$this->success('获取成功', null, $skuPrices);
}
/**
* skuPrices编辑
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
$params = $this->request->only([
'status',
]);
$id = explode(',', $id);
$items = $this->model->whereIn('id', $id)->select();
Db::transaction(function () use ($items, $params) {
foreach ($items as $skuPrice) {
$skuPrice->save($params);
}
});
$this->success('更新成功');
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace app\admin\controller\shopro\goods;
use app\admin\controller\shopro\Common;
use think\Db;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use app\admin\model\shopro\goods\StockLog as StockLogModel;
use addons\shopro\library\Operator;
/**
* 补库存记录
*/
class StockLog extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new StockLogModel;
}
/**
* 库存补货列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$skuPriceTableName = (new SkuPriceModel())->getQuery()->getTable();
$stockLogs = $this->model->sheepFilter()->alias('g')->with(['goods' => function ($query) {
$query->removeOption('soft_delete');
}, 'oper'])
->join($skuPriceTableName . ' sp', 'g.goods_sku_price_id = sp.id', 'left')
->field('g.*,sp.stock as total_stock')
->paginate($this->request->param('list_rows', 10))->toArray();
// 解析操作人信息
foreach ($stockLogs['data'] as &$log) {
$log['oper'] = Operator::info('admin', $log['oper'] ?? null);
}
$this->success('获取成功', null, $stockLogs);
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace app\admin\controller\shopro\goods;
use app\admin\controller\shopro\Common;
use think\Db;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use app\admin\model\shopro\goods\StockWarning as StockWarningModel;
use addons\shopro\traits\StockWarning as StockWarningTrait;
/**
* 库存预警
*/
class StockWarning extends Common
{
use StockWarningTrait;
public function _initialize()
{
parent::_initialize();
$this->model = new StockWarningModel;
}
/**
* 库存预警列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$skuPriceTableName = (new SkuPriceModel())->getQuery()->getTable();
$stockWarnings = $this->model->sheepFilter()->alias('g')->with(['goods' => function ($query) {
$query->removeOption('soft_delete');
}])
->join($skuPriceTableName . ' sp', 'g.goods_sku_price_id = sp.id', 'left')
->field('g.*,sp.stock')
->paginate($this->request->param('list_rows', 10));
$warning_total = $this->model->sheepFilter(false, function ($filters) {
$filters['stock_type'] = 'no_enough';
return $filters;
})->alias('g')
->join($skuPriceTableName . ' sp', 'g.goods_sku_price_id = sp.id', 'left')
->field('g.*,sp.stock')
->count();
$over_total = $this->model->sheepFilter(false, function ($filters) {
$filters['stock_type'] = 'over';
return $filters;
})->alias('g')
->join($skuPriceTableName . ' sp', 'g.goods_sku_price_id = sp.id', 'left')
->field('g.*,sp.stock')
->count();
$result = [
'rows' => $stockWarnings,
'warning_total' => $warning_total,
'over_total' => $over_total,
];
$this->success('获取成功', null, $result);
}
/**
* 补货
*
* @param [type] $ids
* @param [type] $stock
* @return void
*/
public function addStock ($id) {
if ($this->request->isAjax()) {
$params = $this->request->only(['stock']);
$this->svalidate($params, ".add");
$stockWarning = $this->model->with(['sku_price'])->where('id', $id)->find();
if (!$stockWarning) {
$this->error(__('No Results were found'));
}
if (!$stockWarning->sku_price) {
$this->error('库存规格不存在');
}
Db::transaction(function () use ($stockWarning, $params) {
// 补货
$this->addStockToSkuPrice($stockWarning->sku_price, $params['stock'], 'stock_warning');
});
$this->success('补货成功');
}
return $this->view->fetch();
}
public function recyclebin()
{
if ($this->request->isAjax()) {
$skuPriceTableName = (new SkuPriceModel())->getQuery()->getTable();
$stockWarnings = $this->model->onlyTrashed()->sheepFilter()->alias('g')->with(['goods' => function ($query) {
$query->removeOption('soft_delete');
}])
->join($skuPriceTableName . ' sp', 'g.goods_sku_price_id = sp.id', 'left')
->field('g.*,sp.stock')
->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $stockWarnings);
}
return $this->view->fetch();
}
}

View File

@@ -0,0 +1,227 @@
<?php
namespace app\admin\controller\shopro\notification;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\notification\Config as ConfigModel;
use app\admin\controller\shopro\notification\traits\Notification as NotificationTraits;
use addons\shopro\facade\Wechat;
class Config extends Common
{
use NotificationTraits;
public function _initialize()
{
parent::_initialize();
$this->model = new ConfigModel;
}
/**
* 消息通知配置
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$receiver_type = $this->request->param('receiver_type');
$notifications = $this->getNotificationsByReceiverType($receiver_type);
$groupConfigs = $this->getGroupConfigs();
foreach ($notifications as $key => &$notification) {
$currentConfigs = $groupConfigs[$notification['event']] ?? [];
foreach ($notification['channels'] as $channel) {
$notification['configs'][$channel] = [
'status' => isset($currentConfigs[$channel]) ? $currentConfigs[$channel]['status'] : 'disabled',
'send_num' => isset($currentConfigs[$channel]) ? $currentConfigs[$channel]['send_num'] : 0,
];
}
}
$this->success('获取成功', null, $notifications);
}
public function detail()
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
if (!$event || !$channel) {
error_stop('参数错误');
}
$notification = $this->getNotificationByEvent($event);
$notification = $this->formatNotification($notification, $event, $channel);
$this->success('获取成功', null, $notification);
}
// 编辑配置
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$event = $this->request->param('event');
$channel = $this->request->param('channel');
if ($channel == 'Email') {
$content = $this->request->param('content', '');
} else {
$content = $this->request->param('content/a', []);
}
$type = $this->request->param('type', 'default');
if (!$event || !$channel) {
error_stop('参数错误');
}
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
if (!$config) {
$config = $this->model;
$config->event = $event;
$config->channel = $channel;
}
if (in_array($channel, ['WechatOfficialAccount', 'WechatMiniProgram']) && $type == 'default') {
// 自动组装微信默认模板
$content['fields'] = $this->formatWechatTemplateFields($event, $channel, $content['fields']);
}
$config->type = $type;
$config->content = $content;
$config->save();
$this->success('设置成功');
}
// 配置状态
public function setStatus($event, $channel)
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
$status = $this->request->param('status', 'disabled');
if (!$event || !$channel) {
$this->error('参数错误');
}
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
if (!$config) {
$config = $this->model;
$config->event = $event;
$config->channel = $channel;
$config->type = 'default';
}
$config->status = $status;
$config->save();
$this->success('设置成功');
}
/**
* 自动获取微信模板 id
*/
public function getTemplateId()
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
$is_delete = $this->request->param('is_delete', 0);
$template_id = $this->request->param('template_id', '');
if (!$event || !$channel) {
error_stop('参数错误');
}
$notification = $this->getNotificationByEvent($event);
$template = $notification['template'][$channel] ?? null;
if (!$template) {
$this->error('模板不存在');
}
// 请求微信接口
switch ($channel) {
case 'WechatMiniProgram': // 小程序订阅消息
$requestParams['tid'] = $template['tid'];
$requestParams['kid'] = $template['kid'];
$requestParams['sceneDesc'] = $template['scene_desc'];
if (!$requestParams['tid'] || !$requestParams['kid']) {
$this->error('缺少模板参数');
}
$wechat = Wechat::miniProgram()->subscribe_message;
$delete_method = 'deleteTemplate';
$result_key = 'priTmplId';
break;
// case 'WechatOfficialAccount': // 公众号模板消息
// $requestParams['template_id'] = $template['temp_no'];
// if (!$requestParams['template_id']) {
// $this->error('缺少模板参数,获取失败');
// }
// $wechat = Wechat::officialAccount()->template_message; // 微信管理
// $result_key = 'template_id';
// $delete_method = 'deletePrivateTemplate';
// break;
case 'WechatOfficialAccount': // 新版公众号模板消息
$requestParams['template_id'] = $template['temp_no'];
$requestParams['keywords'] = $template['keywords'];
if (!$requestParams['template_id']) {
$this->error('公众号类目模板库目前不完善,请自行在公众号后台->模板消息->选择模板配置');
}
if (!$requestParams['keywords']) {
$this->error('缺少模板关键字,获取失败');
}
$wechat = new \addons\shopro\library\easywechatPlus\WechatOfficialTemplate(Wechat::officialAccount());
$result_key = 'template_id';
$delete_method = 'deletePrivateTemplate';
break;
case 'WechatOfficialAccountBizsend': // 公众号订阅消息(待补充)
$requestParams['tid'] = $template['tid'];
$requestParams['kid'] = $template['kid'];
if (!$requestParams['tid'] || !$requestParams['kid']) {
$this->error('缺少模板参数,获取失败');
}
$wechat = Wechat::officialAccount()->subscribe_message; // 微信管理
$result_key = 'priTmplId';
$delete_method = 'deleteTemplate';
break;
default:
$this->error('当前发送渠道不能获取模板');
break;
}
$result = $wechat->addTemplate(...array_values($requestParams));
if ($result['errcode'] != 0) {
$this->error('获取失败: errcode:' . $result['errcode'] . '; errmsg:' . $result['errmsg']);
} else {
if ($is_delete) {
// 删除传入的老模板
if ($template_id) {
$deleteResult = $wechat->{$delete_method}($template_id);
}
// 删除数据库的老模板
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
$template_id = $config ? ($config->content['template_id'] ?? null) : null;
if ($template_id) {
$deleteResult = $wechat->{$delete_method}($template_id);
}
}
}
$this->success('获取成功', null, ($result[$result_key] ?? null));
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace app\admin\controller\shopro\notification;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\notification\Notification as NotificationModel;
use app\admin\model\shopro\Admin;
class Notification extends Common
{
protected $noNeedRight = ['index', 'read', 'delete', 'notificationType'];
public function _initialize()
{
parent::_initialize();
$this->model = new NotificationModel;
}
/**
* 获取管理员的消息列表
*
* @return \think\Response
*/
public function index()
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
$notifiable_type = $admin->getNotifiableType();
$notifications = NotificationModel::sheepFilter(false)
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->order('createtime', 'desc')
->paginate($this->request->param('list_rows', 10));
$this->success('消息列表', null, $notifications);
}
/**
* 指定消息标记已读
*
* @param string $id
* @return void
*/
public function read($id)
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
$notifiable_type = $admin->getNotifiableType();
$notification = NotificationModel::sheepFilter()
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->where('id', $id)
->find();
if (!$notification) {
$this->error(__('No Results were found'));
}
$notification->read_time = time();
$notification->save();
$this->success('已读成功', null, $notification);
}
/**
* 删除已读消息
*
* @return void
*/
public function delete()
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
// 将已读的消息全部删除
$notifiable_type = $admin->getNotifiableType();
NotificationModel::sheepFilter()
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->whereNotNull('read_time')
->delete();
$this->success('删除成功');
}
/**
* 消息类别,以及未读消息数
*
* @return void
*/
public function notificationType()
{
$admin = auth_admin();
$notificationType = NotificationModel::$notificationType;
$newType = [];
foreach ($notificationType as $type => $name) {
// 未读消息数
$unread_num = NotificationModel::where('notifiable_type', 'admin')->where('notifiable_id', $admin['id'])
->notificationType($type)
->where('read_time', null)
->order('createtime', 'desc')->count();
$newType[] = [
'label' => $name,
'value' => $type,
'unread_num' => $unread_num
];
}
$result = [
'unread_num' => array_sum(array_column($newType, 'unread_num')),
'notification_type' => $newType
];
$this->success('消息类型', null, $result);
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace app\admin\controller\shopro\notification\traits;
/**
* 消息通知,额外方法
*/
trait Notification
{
protected $notificationTypes = [
\addons\shopro\notification\order\OrderNew::class,
\addons\shopro\notification\order\OrderDispatched::class,
\addons\shopro\notification\order\aftersale\OrderAftersaleChange::class,
\addons\shopro\notification\order\aftersale\OrderAdminAftersaleChange::class,
\addons\shopro\notification\order\OrderRefund::class,
\addons\shopro\notification\order\OrderApplyRefund::class,
// 商品
\addons\shopro\notification\goods\StockWarning::class,
// 钱包
\addons\shopro\notification\wallet\CommissionChange::class,
\addons\shopro\notification\wallet\MoneyChange::class,
\addons\shopro\notification\wallet\ScoreChange::class,
// 活动
\addons\shopro\notification\activity\GrouponFail::class,
\addons\shopro\notification\activity\GrouponFinish::class,
];
/**
* 根据接收人类型,获取消息类型
*
* @param array|string $receiverType
* @return array
*/
protected function getNotificationsByReceiverType($receiverType = 'user')
{
$receiverType = is_array($receiverType) ? $receiverType : [$receiverType];
$notifications = $this->getNotifications();
$receiverNotifications = [];
foreach ($notifications as $notification) {
if (in_array($notification['receiver_type'], $receiverType)) {
$receiverNotifications[] = $notification;
}
}
return $receiverNotifications;
}
/**
* 根据事件类型获取消息
*
* @param string $event
* @return void
*/
protected function getNotificationByEvent($event)
{
$notifications = $this->getNotifications();
$notifications = array_column($notifications, null, 'event');
return $notifications[$event] ?? null;
}
/**
* 按照事件类型获取配置分组
*
* @param string $event
* @return array
*/
protected function getGroupConfigs($event = null)
{
// 获取所有配置
$configs = $this->model->select();
$newConfigs = [];
foreach ($configs as $config) {
$newConfigs[$config['event']][$config['channel']] = $config;
}
return $event ? ($newConfigs[$event] ?? []) : $newConfigs;
}
/**
* 获取所有消息类型
*
* @return array
*/
protected function getNotifications()
{
$types = [];
foreach ($this->notificationTypes as $key => $class_name) {
$class = new $class_name();
$currentFields = $class->returnField;
$currentFields['event'] = $class->event;
$currentFields['receiver_type'] = $class->receiver_type;
$currentFields['template'] = $class->template;
$types[] = $currentFields;
}
return $types;
}
/**
* 格式化详情返回结果
*
* @param array $notification
* @param string $event
* @param string $channel
* @return array
*/
protected function formatNotification($notification, $event, $channel)
{
$currentConfigs = $this->getGroupConfigs($event);
$currentConfig = $currentConfigs[$channel] ?? null;
if (in_array($channel, ['WechatOfficialAccount', 'WechatMiniProgram', 'WechatOfficialAccountBizsend'])) {
$currentTemplate = $notification['template'][$channel] ?? [];
unset($notification['template']);
$notification['wechat'] = $currentTemplate;
}
$notification['type'] = $currentConfig['type'] ?? 'default';
$content = $currentConfig['content'] ?? null;
if (!is_array($content)) {
$notification['content_text'] = $content;
}
if ($content && is_array($content)) {
$contentFields = [];
if (isset($content['fields']) && $content['fields']) { // 判断数组是否存在 fields 设置
$contentFields = array_column($content['fields'], null, 'field');
}
$tempFields = array_column($notification['fields'], null, 'field');
$configField = array_merge($tempFields, $contentFields);
$content['fields'] = array_values($configField);
$notification['content'] = $content;
} else {
$notification['content'] = [
'template_id' => '',
'fields' => $notification['fields']
];
}
unset($notification['fields']);
return $notification;
}
/**
* 格式化微信公众号,小程序默认模板时 自动配置 模板字段
*
* @return void
*/
protected function formatWechatTemplateFields($event, $channel, $fields)
{
$notification = $this->getNotificationByEvent($event);
$channelFields = $notification['template'][$channel]['fields'] ?? [];
$channelFields = array_column($channelFields, null, 'field');
foreach ($fields as $key => &$field) {
$field_name = $field['field'] ?? '';
if ($field_name && isset($channelFields[$field_name])) {
$field['template_field'] = $channelFields[$field_name]['template_field'] ?? '';
}
}
return $fields;
}
}

View File

@@ -0,0 +1,339 @@
<?php
namespace app\admin\controller\shopro\order;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\order\Aftersale as OrderAftersaleModel;
use app\admin\model\shopro\order\AftersaleLog as OrderAftersaleLogModel;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\order\OrderItem as OrderItemModel;
use app\admin\model\shopro\order\Action as OrderActionModel;
use addons\shopro\service\order\OrderRefund;
use addons\shopro\library\Operator;
class Aftersale extends Common
{
protected $noNeedRight = ['getType'];
protected $orderModel;
public function _initialize()
{
parent::_initialize();
$this->model = new OrderAftersaleModel;
$this->orderModel = new OrderModel;
}
/**
* 售后单列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
// 查询主表是订单表
$orders = $this->orderModel->withTrashed()->sheepFilter()->with(['user', 'aftersales' => function ($query) {
$query->removeOption('soft_delete');
}])->paginate(request()->param('list_rows', 10));
$this->success('获取成功', null, $orders);
}
// 获取数据类型
public function getType()
{
$type = $this->model->typeList();
$dispatchStatus = $this->model->dispatchStatusList();
$aftersaleStatus = $this->model->aftersaleStatusList();
$refundStatus = $this->model->refundStatusList();
$result = [
'type' => $type,
'dispatch_status' => $dispatchStatus,
'aftersale_status' => $aftersaleStatus,
'refund_status' => $refundStatus,
];
$data = [];
foreach ($result as $key => $list) {
$data[$key][] = ['name' => '全部', 'type' => 'all'];
foreach ($list as $k => $v) {
$data[$key][] = [
'name' => $v,
'type' => $k
];
}
}
$this->success('获取成功', null, $data);
}
/**
* 售后单详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$aftersale = $this->model->withTrashed()->with(['user', 'order' => function ($query) {
$query->removeOption('soft_delete');
}, 'logs'])->where('id', $id)->find();
if (!$aftersale) {
$this->error(__('No Results were found'));
}
// 建议退款金额
$aftersale->suggest_refund_fee = $aftersale->suggest_refund_fee;
// 多态关联 oper
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'admin' => \app\admin\model\Admin::class,
'system' => \app\admin\model\Admin::class,
];
$aftersale['logs'] = morph_to($aftersale['logs'], $morphs, ['oper_type', 'oper_id']);
$aftersale = $aftersale->toArray();
foreach ($aftersale['logs'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('获取成功', null, $aftersale);
}
/**
* 完成售后
*/
public function completed($id)
{
$admin = $this->auth->getUserInfo();
$aftersale = $this->model->withTrashed()->canOper()->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在或不可完成');
}
$order = $this->orderModel->withTrashed()->find($aftersale->order_id);
$orderItem = OrderItemModel::find($aftersale->order_item_id);
if (!$order || !$orderItem) {
$this->error('订单或订单商品不存在');
}
$aftersale = Db::transaction(function () use ($aftersale, $order, $orderItem, $admin) {
$aftersale->aftersale_status = OrderAftersaleModel::AFTERSALE_STATUS_COMPLETED; // 售后完成
$aftersale->save();
// 增加售后单变动记录、
OrderAftersaleLogModel::add($order, $aftersale, $admin, 'admin', [
'log_type' => 'completed',
'content' => '售后订单已完成',
'images' => []
]);
$orderItem->aftersale_status = OrderItemModel::AFTERSALE_STATUS_COMPLETED;
$orderItem->save();
OrderActionModel::add($order, $orderItem, $admin, 'admin', '管理员完成售后');
// 售后单完成之后
$data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem];
\think\Hook::listen('order_aftersale_completed', $data);
return $aftersale;
});
$this->success('操作成功', null, $aftersale);
}
/**
* 拒绝售后
*/
public function refuse($id = 0)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.refuse');
$aftersale = $this->model->withTrashed()->canOper()->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在或不可拒绝');
}
$order = $this->orderModel->withTrashed()->find($aftersale->order_id);
$orderItem = OrderItemModel::find($aftersale->order_item_id);
if (!$order || !$orderItem) {
$this->error('订单或订单商品不存在');
}
$aftersale = Db::transaction(function () use ($aftersale, $order, $orderItem, $params, $admin) {
$aftersale->aftersale_status = OrderAftersaleModel::AFTERSALE_STATUS_REFUSE; // 售后拒绝
$aftersale->save();
// 增加售后单变动记录
OrderAftersaleLogModel::add($order, $aftersale, $admin, 'admin', [
'log_type' => 'refuse',
'content' => $params['refuse_msg'],
'images' => []
]);
$orderItem->aftersale_status = OrderItemModel::AFTERSALE_STATUS_REFUSE; // 拒绝售后
$orderItem->save();
OrderActionModel::add($order, $orderItem, $admin, 'admin', '管理员拒绝订单售后:' . $params['refuse_msg']);
// 售后单拒绝后
$data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem];
\think\Hook::listen('order_aftersale_refuse', $data);
return $aftersale;
});
$this->success('操作成功', null, $aftersale);
}
/**
* 同意退款
*/
public function refund($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.refund');
$refund_money = round(floatval($params['refund_money']), 2);
$refund_type = $params['refund_type'] ?? 'back';
if ($refund_money <= 0) {
$this->error('请输入正确的退款金额');
}
$aftersale = $this->model->withTrashed()->canOper()->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在或不可退款');
}
$order = $this->orderModel->withTrashed()->with('items')->find($aftersale->order_id);
if (!$order) {
$this->error('订单不存在');
}
$items = $order->items;
$items = array_column($items, null, 'id');
// 当前订单已退款总金额
$refunded_money = array_sum(array_column($items, 'refund_fee'));
// 剩余可退款金额
$refund_surplus_money = bcsub($order->pay_fee, (string)$refunded_money, 2);
// 如果退款金额大于订单支付总金额
if (bccomp((string)$refund_money, $refund_surplus_money, 2) === 1) {
$this->error('退款总金额不能大于实际支付金额');
}
$orderItem = $items[$aftersale['order_item_id']];
if (!$orderItem || in_array($orderItem['refund_status'], [
OrderItemModel::REFUND_STATUS_AGREE,
OrderItemModel::REFUND_STATUS_COMPLETED,
])) {
$this->error('订单商品已退款,不能重复退款');
}
$aftersale = Db::transaction(function () use ($aftersale, $order, $orderItem, $refund_money, $refund_type, $refund_surplus_money, $admin) {
$aftersale->aftersale_status = OrderAftersaleModel::AFTERSALE_STATUS_COMPLETED; // 售后同意
$aftersale->refund_status = OrderAftersaleModel::REFUND_STATUS_AGREE; // 同意退款
$aftersale->refund_fee = $refund_money; // 退款金额
$aftersale->save();
// 增加售后单变动记录
OrderAftersaleLogModel::add($order, $aftersale, $admin, 'admin', [
'log_type' => 'refund',
'content' => '售后订单已退款',
'images' => []
]);
$orderItem->aftersale_status = OrderItemModel::AFTERSALE_STATUS_COMPLETED;
$orderItem->save();
OrderActionModel::add($order, $orderItem, $admin, 'admin', '管理员同意售后退款');
// 开始退款
$orderRefund = new OrderRefund($order);
$orderRefund->refund($orderItem, $refund_money, $admin, [
'refund_type' => $refund_type,
'remark' => '管理员同意售后退款'
]);
$data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem];
\think\Hook::listen('order_aftersale_completed', $data);
return $aftersale;
});
$this->success('操作成功', null, $aftersale);
}
/**
* 留言
*/
public function addLog($id = 0)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.add_log');
$aftersale = $this->model->withTrashed()->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在');
}
$order = $this->orderModel->withTrashed()->with('items')->find($aftersale->order_id);
if (!$order) {
$this->error('订单不存在');
}
$aftersale = Db::transaction(function () use ($order, $aftersale, $params, $admin) {
if ($aftersale['aftersale_status'] == 0) {
$aftersale->aftersale_status = OrderAftersaleModel::AFTERSALE_STATUS_ING; // 售后处理中
$aftersale->save();
}
// 增加售后单变动记录
OrderAftersaleLogModel::add($order, $aftersale, $admin, 'admin', [
'log_type' => 'add_log',
'content' => $params['content'],
'images' => $params['images'] ?? []
]);
return $aftersale;
});
$this->success('操作成功', null, $aftersale);
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace app\admin\controller\shopro\order;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\order\Invoice as OrderInvoiceModel;
use app\admin\model\shopro\order\Order as OrderModel;
class Invoice extends Common
{
public function _initialize()
{
parent::_initialize();
$this->model = new OrderInvoiceModel;
}
/**
* 发票列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$invoices = $this->model->sheepFilter()->with(['user', 'order', 'order_items'])
->paginate(request()->param('list_rows', 10))->each(function ($invoice) {
$invoice->order_status = $invoice->order_status;
$invoice->order_status_text = $invoice->order_status_text;
$invoice->order_fee = $invoice->order_fee;
});
$this->success('获取成功', null, $invoices);
}
public function confirm($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->param();
$invoice = $this->model->waiting()->whereIn('id', $id)->find();
if (!$invoice) {
$this->error(__('No Results were found'));
}
$invoice->download_urls = $params['download_urls'] ?? null;
$invoice->invoice_amount = $params['invoice_amount'];
$invoice->status = 'finish';
$invoice->finish_time = time();
$invoice->save();
$this->success('开具成功', null, $invoice);
}
}

View File

@@ -0,0 +1,974 @@
<?php
namespace app\admin\controller\shopro\order;
use think\Db;
use think\exception\HttpResponseException;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\order\Address as OrderAddressModel;
use app\admin\model\shopro\order\OrderItem;
use app\admin\model\shopro\Admin;
use app\admin\model\shopro\user\User;
use app\admin\model\shopro\order\Action as OrderActionModel;
use app\admin\model\shopro\order\Express as OrderExpressModel;
use addons\shopro\service\pay\PayOper;
use addons\shopro\service\order\OrderOper;
use addons\shopro\service\order\OrderRefund;
use app\admin\model\shopro\Pay as PayModel;
use addons\shopro\service\order\OrderDispatch as OrderDispatchService;
use addons\shopro\library\express\Express as ExpressLib;
use addons\shopro\library\Operator;
use addons\shopro\facade\Wechat;
class Order extends Common
{
protected $noNeedRight = ['getType', 'dispatchList'];
public function _initialize()
{
parent::_initialize();
$this->model = new OrderModel;
}
/**
* 订单列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
if (sheep_config('shop.platform.WechatMiniProgram.status')) { // 如果开启了小程序平台
// 设置小程序发货信息管理,消息通知跳转地址,有缓存, 不会每次都设置
$uploadshoppingInfo = new \addons\shopro\library\easywechatPlus\WechatMiniProgramShop(Wechat::miniProgram());
$uploadshoppingInfo->checkAndSetMessageJumpPath();
}
$exportConfig = (new \addons\shopro\library\Export())->getConfig();
$this->assignconfig("save_type", $exportConfig['save_type'] ?? 'download');
return $this->view->fetch();
}
$orders = $this->model->withTrashed()->sheepFilter()->with(['user', 'items', 'address', 'activity_orders'])
->paginate(request()->param('list_rows', 10))->each(function ($order) {
$order->pay_types = $order->pay_types;
$order->pay_types_text = $order->pay_types_text;
$order->items = collection($order->items);
$order->items->each(function ($item) use ($order) {
// 处理每个商品的 activity_order
$item->activity_orders = new \think\Collection;
foreach ($order->activity_orders as $activityOrder) {
if ($activityOrder->goods_ids && in_array($item->goods_id, $activityOrder->goods_ids)) {
$item->activity_orders->push($activityOrder);
}
}
return $item;
});
})->toArray();
foreach ($orders['data'] as &$order) {
$order = $this->model->setOrderItemStatusByOrder($order);
}
$result = [
'orders' => $orders,
];
// 查询各个状态下的订单数量
$searchStatus = $this->model->searchStatusList();
// 所有的数量
$result['all'] = $this->model->withTrashed()->sheepFilter(true, function ($filters) {
unset($filters['status']);
return $filters;
})->count();
foreach ($searchStatus as $status => $text) {
$result[$status] = $this->model->withTrashed()->sheepFilter(true, function ($filters) use ($status) {
$filters['status'] = $status;
return $filters;
})->count();
}
$this->success('获取成功', null, $result);
}
// 获取数据类型
public function getType()
{
$type = $this->model->typeList();
$payType = (new PayModel)->payTypeList();
$platform = $this->model->platformList();
$classify = (new \app\admin\model\shopro\activity\Activity)->classifies();
$activityType = $classify['activity'];
$promoType = $classify['promo'];
$applyRefundStatus = $this->model->applyRefundStatusList();
$status = $this->model->searchStatusList();
$result = [
'type' => $type,
'pay_type' => $payType,
'platform' => $platform,
'activity_type' => $activityType,
'promo_types' => $promoType,
'apply_refund_status' => $applyRefundStatus,
'status' => $status
];
$data = [];
foreach ($result as $key => $list) {
$data[$key][] = ['name' => '全部', 'type' => 'all'];
foreach ($list as $k => $v) {
$data[$key][] = [
'name' => $v,
'type' => $k
];
}
}
$this->success('获取成功', null, $data);
}
/**
* 订单详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
// 更新包裹信息5分钟缓存
(new ExpressLib)->updateOrderExpress($id);
$order = $this->model->withTrashed()->with(['user', 'items', 'address', 'activity_orders', 'pays', 'invoice'])->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order->express = $order->express;
if ($order->invoice) {
$order->invoice->order_status = $order->invoice->order_status;
$order->invoice->order_status_text = $order->invoice->order_status_text;
$order->invoice->order_fee = $order->invoice->order_fee;
}
foreach ($order->activity_orders as $activityOrder) {
// 处理每个活动中参与的商品
$activityOrder->items = new \think\Collection();
foreach ($order->items as $item) {
if ($activityOrder->goods_ids && in_array($item->goods_id, $activityOrder->goods_ids)) {
$activityOrder->items->push($item);
}
}
}
foreach ($order->items as $item) {
// 处理 order_item 建议退款金额
$item->suggest_refund_fee = $item->suggest_refund_fee;
}
// 处理未支付订单 item status_code
$order = $order->setOrderItemStatusByOrder($order);
$this->success('获取成功', null, $order);
}
/**
* 批量发货渲染模板
*
* @return void
*/
public function batchDispatch()
{
return $this->view->fetch();
}
/**
* 批量发货渲染模板
*
* @return void
*/
public function dispatchList()
{
return $this->view->fetch();
}
/**
* 手动发货
*
* @return void
*/
public function customDispatch()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['order_id', 'order_item_ids', 'custom_type', 'custom_content']);
$this->svalidate($params, '.custom_dispatch');
Db::transaction(function () use ($params) {
$service = new OrderDispatchService($params);
$service->customDispatch($params);
});
$this->success('发货成功');
}
/**
* 发货
*
* @description
* 支持分包裹发货
* 支持手动发货
* 支持上传发货单发货
* 支持推送api运单发货 默认使用配置项
* 支持修改发货信息
* 支持取消发货
*
* @remark 此处接口设计如此复杂是因为考虑到权限的问题,订单发货权限可以完成所有发货行为
*
* @param array $action 发货行为(默认:confirm=确认发货, cancel=取消发货, change=修改运单, multiple=解析批量发货单)
* @param int $order_id 订单id
* @param array $order_item_ids 订单商品id
* @param string $method 发货方式input=手动发货, api=推送运单, upload=上传发货单)
* @param array $sender 发货人信息
* @param array $express 物流信息
*
* @return \think\Response
*/
public function dispatch()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['action', 'order_id', 'order_ids', 'order_item_ids', 'method', 'sender', 'express', 'order_express_id']);
$action = $params['action'] ?? 'confirm';
if (!in_array($action, ['confirm', 'cancel', 'change', 'multiple'])) {
$this->error('发货参数错误');
}
$service = new OrderDispatchService($params);
switch ($action) {
case 'confirm':
$express = $service->confirm($params);
$this->success('发货成功', null, $express);
break;
case 'cancel':
$result = $service->cancel($params);
if ($result) {
$this->success('取消发货成功');
}
break;
case 'change':
$express = $service->change($params);
$this->success('修改成功', null, $express);
break;
case 'multiple':
$params['file'] = $this->request->file('file');
$result = $service->multiple($params);
$this->success('待发货列表', null, $result);
break;
}
$this->error('操作失败');
}
/**
* 获取物流快递信息
*/
public function updateExpress($order_express_id = 0)
{
$type = $this->request->param('type');
// 获取包裹
$orderExpress = OrderExpressModel::where('id', $order_express_id)->find();
if (!$orderExpress) {
$this->error('包裹不存在');
}
$orderAddress = OrderAddressModel::where('order_id', $orderExpress->order_id)->find();
if (!$orderAddress) {
$this->error('订单不存在');
}
$expressLib = new ExpressLib();
try {
if ($type == 'subscribe') {
// 重新订阅
$expressLib->subscribe([
'express_code' => $orderExpress['express_code'],
'express_no' => $orderExpress['express_no'],
'phone' => $orderAddress['mobile']
]);
} else {
// 手动查询
$result = $expressLib->search([
'order_id' => $orderExpress['order_id'],
'express_code' => $orderExpress['express_code'],
'express_no' => $orderExpress['express_no'],
'phone' => $orderAddress['mobile']
], $orderExpress);
}
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
$this->error(($type == 'subscribe' ? '订阅失败:' : '刷新失败:') . $e->getMessage());
}
$this->success(($type == 'subscribe' ? '订阅成功' : '刷新成功'));
}
/**
* 线下付款,确认收货
*/
public function offlineConfirm($id)
{
$admin = $this->auth->getUserInfo();
$order = OrderModel::offline()->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order = Db::transaction(function () use ($order, $admin) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
$user = User::get($order->user_id);
$payOper = new PayOper($user);
$order = $payOper->offline($order, $order->remain_pay_fee, 'order'); // 订单会变为已支付 paid
// 触发订单支付完成事件
$data = ['order' => $order, 'user' => $user];
\think\Hook::listen('order_offline_paid_after', $data);
$orderOper = new OrderOper();
// 确认收货
$order = $orderOper->confirm($order, [], $admin, 'admin');
return $order;
});
$this->success('收货成功', $order);
}
/**
* 线下付款,拒收
*/
public function offlineRefuse($id)
{
$admin = $this->auth->getUserInfo();
$order = OrderModel::offline()->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order = Db::transaction(function () use ($order, $admin) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
// 拒收
$orderOper = new OrderOper();
$order = $orderOper->refuse($order, $admin, 'admin');
// 交易关闭
$order = $orderOper->close($order, $admin, 'admin', '用户拒绝收货,管理员关闭订单', ['closed_type' => 'refuse']);
return $order;
});
$this->success('收货成功', $order);
}
/**
* 订单改价,当剩余应支付金额为 0 时,订单将自动支付
*
* @param int $id
* @return void
*/
public function changeFee($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.change_fee');
$order = $this->model->unpaid()->where('id', $id)->find();
if (!$order) {
$this->error('订单不可改价');
}
Db::transaction(function () use ($order, $admin, $params) {
$pay_fee = $params['pay_fee'];
$change_msg = $params['change_msg'];
$payOper = new PayOper($order->user_id);
$payed_fee = $payOper->getPayedFee($order, 'order');
if ($pay_fee < $payed_fee) {
$this->error('改价金额不能低于订单已支付金额');
}
// 记录原始值
$last_pay_fee = $order->pay_fee; // 上次pay_fee,非原始 pay_fee
$order->pay_fee = $pay_fee;
$order->save();
OrderActionModel::add($order, null, $admin, 'admin', "应支付金额由 ¥" . $last_pay_fee . " 改为 ¥" . $pay_fee . ",改价原因:" . $change_msg);
// 检查订单支付状态, 改价可以直接将订单变为已支付
$order = $payOper->checkAndPaid($order, 'order');
});
$this->success('改价成功');
}
/**
* 修改收货人信息
*
* @param Request $request
* @param integer $id
* @return void
*/
public function editConsignee($id)
{
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.edit_consignee');
$order = $this->model->withTrashed()->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
Db::transaction(function () use ($admin, $order, $params) {
$orderAddress = OrderAddressModel::where('order_id', $order->id)->find();
if (!$orderAddress) {
$this->error(__('No Results were found'));
}
$orderAddress->consignee = $params['consignee'];
$orderAddress->mobile = $params['mobile'];
$orderAddress->province_name = $params['province_name'];
$orderAddress->city_name = $params['city_name'];
$orderAddress->district_name = $params['district_name'];
$orderAddress->address = $params['address'];
$orderAddress->province_id = $params['province_id'];
$orderAddress->city_id = $params['city_id'];
$orderAddress->district_id = $params['district_id'];
$orderAddress->save();
OrderActionModel::add($order, null, $admin, 'admin', "修改订单收货人信息");
});
$this->success('收货人信息修改成功');
}
/**
* 编辑商家备注
*
* @param Request $request
* @param integer $id
* @return void
*/
public function editMemo($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.edit_memo');
$order = $this->model->withTrashed()->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
Db::transaction(function () use ($admin, $order, $params) {
$order->memo = $params['memo'];
$order->save();
OrderActionModel::add($order, null, $admin, 'admin', "修改卖家备注:" . $params['memo']);
});
$this->success('卖家备注修改成功');
}
/**
* 拒绝用户全额退款申请
*
* @param Request $request
* @param integer $id
* @return void
*/
public function applyRefundRefuse($id)
{
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
// $this->svalidate($params, '.apply_refund_refuse');
$order = $this->model->withTrashed()->paid()->applyRefundIng()->where('id', $id)->find();
if (!$order) {
$this->error('订单未找到或不可拒绝申请');
}
Db::transaction(function () use ($admin, $order, $params) {
$order->apply_refund_status = OrderModel::APPLY_REFUND_STATUS_REFUSE;
$order->save();
OrderActionModel::add($order, null, $admin, 'admin', "拒绝用户申请全额退款");
});
$this->success('拒绝申请成功');
}
/**
* 全额退款 (必须没有进行过任何退款才能使用)
*
* @param Request $request
* @param integer $id
* @return void
*/
public function fullRefund($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$admin = Admin::where('id', $admin['id'])->find();
$params = $this->request->param();
$refund_type = $params['refund_type'] ?? 'back';
Db::transaction(function () use ($admin, $id, $refund_type) {
$order = $this->model->paid()->where('id', $id)->lock(true)->find();
if (!$order) {
$this->error('订单不存在或不可退款');
}
$orderRefund = new OrderRefund($order);
$orderRefund->fullRefund($admin, [
'refund_type' => $refund_type,
'remark' => '平台主动全额退款'
]);
});
$this->success('全额退款成功');
}
/**
* 订单单商品退款
*
* @param Request $request
* @param integer $id
* @param integer $item_id
* @return void
*/
public function refund($id, $item_id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$admin = $this->auth->getUserInfo();
$params = $this->request->param();
$this->svalidate($params, '.refund');
$refund_money = round(floatval($params['refund_money']), 2);
$refund_type = $params['refund_type'] ?? 'back';
if ($refund_money <= 0) {
$this->error('请输入正确的退款金额');
}
$order = $this->model->paid()->where('id', $id)->find();
if (!$order) {
$this->error('订单不存在或不可退款');
}
$item = OrderItem::where('order_id', $order->id)->where('id', $item_id)->find();
if (!$item) {
$this->error(__('No Results were found'));
}
if (in_array($item['refund_status'], [
OrderItem::REFUND_STATUS_AGREE,
OrderItem::REFUND_STATUS_COMPLETED,
])) {
$this->error('订单商品已退款,不能重复退款');
}
$payOper = new PayOper($order->user_id);
// 获取订单最大可退款金额(不含积分抵扣金额)
$remain_max_refund_money = $payOper->getRemainRefundMoney($order->id);
// 如果退款金额大于订单支付总金额
if (bccomp((string)$refund_money, $remain_max_refund_money, 2) === 1) {
$this->error('退款总金额不能大于实际支付金额');
}
Db::transaction(function () use ($admin, $order, $item, $refund_money, $refund_type) {
// 重新锁定读查询 orderItem
$item = OrderItem::where('order_id', $order->id)->lock(true)->where('id', $item->id)->find();
if (!$item) {
$this->error('订单不存在或不可退款');
}
$orderRefund = new OrderRefund($order);
$orderRefund->refund($item, $refund_money, $admin, [
'refund_type' => $refund_type,
'remark' => '平台主动退款'
]);
});
$this->success('退款成功');
}
/**
* 获取订单操作记录
*
* @param integer $id
* @return void
*/
public function action($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$actions = OrderActionModel::where('order_id', $id)->order('id', 'desc')->select();
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'admin' => \app\admin\model\Admin::class,
'system' => \app\admin\model\Admin::class,
];
$actions = morph_to($actions, $morphs, ['oper_type', 'oper_id']);
foreach ($actions as &$action) {
$action['oper'] = Operator::info($action['oper_type'], $action['oper'] ?? null);
}
$this->success('获取成功', null, $actions);
}
public function export()
{
$cellTitles = [
// 订单表字段
'order_id' => 'Id',
'order_sn' => '订单号',
'type_text' => '订单类型',
'user_nickname' => '下单用户',
'user_mobile' => '手机号',
'status_text' => '订单状态',
'pay_text' => '支付状态',
'pay_types_text' => '支付类型',
'remark' => '用户备注',
'memo' => '卖家备注',
'order_amount' => '订单总金额',
'score_amount' => '积分支付数量',
'dispatch_amount' => '运费',
'pay_fee' => '应付总金额',
'real_pay_fee' => '实付总金额',
'remain_pay_fee' => '剩余支付金额',
'total_discount_fee' => '总优惠金额',
'coupon_discount_fee' => '优惠券金额',
'promo_discount_fee' => '营销优惠金额',
'paid_time' => '支付完成时间',
'platform_text' => '交易平台',
'consignee_info' => '收货信息',
'createtime' => '下单时间',
// 订单商品表字段
'activity_type_text' => '活动',
'promo_types' => '促销',
'goods_title' => '商品名称',
'goods_sku_text' => '商品规格',
'goods_num' => '购买数量',
'goods_original_price' => '商品原价',
'goods_price' => '商品价格',
'goods_weight' => '商品重量',
'discount_fee' => '优惠金额',
'goods_pay_fee' => '商品支付金额',
'dispatch_type_text' => '发货方式',
'dispatch_status_text' => '发货状态',
'aftersale_refund' => '售后/退款',
'comment_status_text' => '评价状态',
'refund_fee' => '退款金额',
'refund_msg' => '退款原因',
'express_name' => '快递公司',
'express_no' => '快递单号',
];
// 数据总条数
$total = $this->model->withTrashed()->sheepFilter()->count();
if ($total <= 0) {
$this->error('导出数据为空');
}
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '订单列表',
'cell_titles' => $cellTitles,
'total' => $total,
'is_sub_cell' => true,
'sub_start_cell' => 'activity_type_text',
'sub_field' => 'items'
];
$total_order_amount = 0;
$total_pay_fee = 0;
$total_real_pay_fee = 0;
$total_discount_fee = 0;
$total_score_amount = 0;
$result = $export->export($params, function ($pages) use (&$total_order_amount, &$total_pay_fee, &$total_real_pay_fee, &$total_discount_fee, &$total_score_amount, $total) {
$datas = $this->model->withTrashed()->sheepFilter()->with(['user', 'items' => function ($query) {
$query->with(['express']);
}, 'address'])
->limit((($pages['page'] - 1) * $pages['list_rows']), $pages['list_rows'])
->select();
$datas = collection($datas);
$datas = $datas->each(function ($order) {
$order->pay_types_text = $order->pay_types_text;
})->toArray();
$newDatas = [];
foreach ($datas as &$order) {
$order = $this->model->setOrderItemStatusByOrder($order);
// 收货人信息
$consignee_info = '';
if ($order['address']) {
$address = $order['address'];
$consignee_info = ($address['consignee'] ? ($address['consignee'] . ':' . $address['mobile'] . '-') : '') . ($address['province_name'] . '-' . $address['city_name'] . '-' . $address['district_name']) . ' ' . $address['address'];
}
$data = [
'order_id' => $order['id'],
'order_sn' => $order['order_sn'],
'type_text' => $order['type_text'],
'user_nickname' => $order['user'] ? $order['user']['nickname'] : '-',
'user_mobile' => $order['user'] ? $order['user']['mobile'] . ' ' : '-',
'status_text' => $order['status_text'],
'pay_text' => in_array($order['status'], [OrderModel::STATUS_PAID, OrderModel::STATUS_COMPLETED]) ? '已支付' : '未支付',
'pay_types_text' => is_array($order['pay_types_text']) ? join(',', $order['pay_types_text']) : ($order['pay_types_text'] ?: ''),
'remark' => $order['remark'],
'memo' => $order['memo'],
'order_amount' => $order['order_amount'],
'score_amount' => $order['score_amount'],
'dispatch_amount' => $order['dispatch_amount'],
'pay_fee' => $order['pay_fee'],
'real_pay_fee' => bcsub($order['pay_fee'], $order['remain_pay_fee'], 2),
'remain_pay_fee' => $order['remain_pay_fee'],
'total_discount_fee' => $order['total_discount_fee'],
'coupon_discount_fee' => $order['coupon_discount_fee'],
'promo_discount_fee' => $order['promo_discount_fee'],
'paid_time' => $order['paid_time'],
'platform_text' => $order['platform_text'],
'consignee_info' => $consignee_info,
'createtime' => $order['createtime'],
];
$items = [];
foreach ($order['items'] as $item) {
$items[] = [
'activity_type_text' => $item['activity_type_text'],
'promo_types_text' => is_array($item['promo_types_text']) ? join(',', $item['promo_types_text']) : ($item['promo_types_text'] ?: '-'),
'goods_title' => $item['goods_title'],
'goods_sku_text' => $item['goods_sku_text'],
'goods_num' => $item['goods_num'],
'goods_original_price' => $item['goods_original_price'],
'goods_price' => $item['goods_price'],
'goods_weight' => $item['goods_weight'],
'discount_fee' => $item['discount_fee'],
'goods_pay_fee' => $item['pay_fee'],
'dispatch_type_text' => $item['dispatch_type_text'],
'dispatch_status_text' => $item['dispatch_status_text'],
'aftersale_refund' => $item['aftersale_status_text'] . '/' . $item['refund_status_text'],
'comment_status_text' => $item['comment_status_text'],
'refund_fee' => $item['refund_fee'],
'refund_msg' => $item['refund_msg'],
'express_name' => $item['express'] ? $item['express']['express_name'] : '-',
'express_no' => $item['express'] ? $item['express']['express_no'] . ' ' : '-',
];
}
$data['items'] = $items;
$newDatas[] = $data;
}
$total_order_amount += array_sum(array_column($newDatas, 'order_amount'));
$total_score_amount += array_sum(array_column($newDatas, 'score_amount'));
$total_pay_fee += array_sum(array_column($newDatas, 'pay_fee'));
$total_real_pay_fee += array_sum(array_column($newDatas, 'real_pay_fee'));
$total_discount_fee += array_sum(array_column($newDatas, 'discount_fee'));
if ($pages['is_last_page']) {
$newDatas[] = ['order_id' => "订单总数:" . $total . ";订单总金额:¥" . $total_order_amount . ";优惠总金额:¥" . $total_discount_fee . ";应付总金额:¥" . $total_pay_fee . ";实付总金额:¥" . $total_real_pay_fee . ";支付总积分:" . $total_score_amount];
}
return $newDatas;
});
$this->success('导出成功' . (isset($result['file_path']) && $result['file_path'] ? ',请在服务器: “' . $result['file_path'] . '” 查看' : ''), null, $result);
}
public function exportDelivery()
{
$cellTitles = [
// 订单表字段
'order_id' => 'Id',
'order_sn' => '订单号',
'type_text' => '订单类型',
'consignee_info' => '收货信息',
'remark' => '用户备注',
'memo' => '商家备注',
'createtime' => '下单时间',
// 订单商品表字段
'order_item_id' => '子订单Id',
'goods_title' => '商品名称',
'goods_sku_text' => '商品规格',
'goods_num' => '购买数量',
// 'dispatch_fee' => '发货费用',
'dispatch_type_text' => '发货方式',
'dispatch_status_text' => '发货状态',
'aftersale_refund' => '售后/退款',
'express_no' => '快递单号',
];
// 数据总条数
$total = $this->model->sheepFilter()->count(); // nosend 加了 noApplyRefund
if ($total <= 0) {
$this->error('导出数据为空');
}
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '订单发货单列表',
'cell_titles' => $cellTitles,
'total' => $total,
'is_sub_cell' => true,
'sub_start_cell' => 'order_item_id',
'sub_field' => 'items'
];
$result = $export->export($params, function ($pages) use (&$total) {
// 未申请全额退款的
$datas = $this->model->sheepFilter()->with(['user', 'items' => function ($query) { // nosend 加了 noApplyRefund
$query->with(['express']);
}, 'address'])
->limit((($pages['page'] - 1) * $pages['list_rows']), $pages['list_rows'])
->select();
$datas = collection($datas)->toArray();
$newDatas = [];
foreach ($datas as &$order) {
$order = $this->model->setOrderItemStatusByOrder($order);
if (in_array($order['status_code'], ['groupon_ing', 'groupon_invalid'])) {
// 拼团正在进行中,不发货
$total--; // total 减少 1
continue;
}
// 收货人信息
$consignee_info = '';
if ($order['address']) {
$address = $order['address'];
$consignee_info = ($address['consignee'] ? ($address['consignee'] . ':' . $address['mobile'] . '-') : '') . ($address['province_name'] . '-' . $address['city_name'] . '-' . $address['district_name']) . ' ' . $address['address'];
}
$data = [
'order_id' => $order['id'],
'order_sn' => $order['order_sn'],
'type_text' => $order['type_text'],
'consignee_info' => $consignee_info,
'remark' => $order['remark'],
'memo' => $order['memo'],
'createtime' => $order['createtime']
];
$items = [];
foreach ($order['items'] as $k => $item) {
// 未发货,并且未退款,并且未在申请售后中,并且是快递物流的
if (
$item['dispatch_status'] == OrderItem::DISPATCH_STATUS_NOSEND
&& !in_array($item['refund_status'], [OrderItem::REFUND_STATUS_AGREE, OrderItem::REFUND_STATUS_COMPLETED])
&& $item['aftersale_status'] != OrderItem::AFTERSALE_STATUS_ING
&& $item['dispatch_type'] == 'express'
) {
$items[] = [
'order_item_id' => $item['id'],
'goods_title' => strpos($item['goods_title'], '=') === 0 ? ' ' . $item['goods_title'] : $item['goods_title'],
'goods_sku_text' => $item['goods_sku_text'],
'goods_num' => $item['goods_num'],
// 'dispatch_fee' => $item['dispatch_fee'],
'dispatch_type_text' => $item['dispatch_type_text'],
'dispatch_status_text' => $item['dispatch_status_text'],
'aftersale_refund' => $item['aftersale_status_text'] . '/' . $item['refund_status_text'],
'express_no' => $item['express'] ? $item['express']['express_no'] . ' ' : '',
];
}
}
$data['items'] = $items;
$newDatas[] = $data;
};
if ($pages['is_last_page']) {
$newDatas[] = ['order_id' => "订单总数(仅快递物流的待发货订单):" . $total . ";备注:订单中同一包裹请填写相同运单号"];
}
return $newDatas;
});
$this->success('导出成功' . (isset($result['file_path']) && $result['file_path'] ? ',请在服务器: “' . $result['file_path'] . '” 查看' : ''), null, $result);
}
}

View File

@@ -0,0 +1,199 @@
<?php
namespace app\admin\controller\shopro\trade;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\trade\Order as TradeOrderModel;
use app\admin\model\shopro\Pay as PayModel;
class Order extends Common
{
protected $noNeedRight = ['getType'];
public function _initialize()
{
parent::_initialize();
$this->model = new TradeOrderModel;
}
/**
* 订单列表
*
* @return \think\Response
*/
public function index()
{
if (!$this->request->isAjax()) {
$exportConfig = (new \addons\shopro\library\Export())->getConfig();
$this->assignconfig("save_type", $exportConfig['save_type'] ?? 'download');
return $this->view->fetch();
}
$orders = $this->model->withTrashed()->sheepFilter()->with(['user'])
->paginate(request()->param('list_rows', 10))->each(function ($order) {
$order->pay_type_text = $order->pay_type_text;
$order->pay_type = $order->pay_type;
})->toArray();
$result = [
'orders' => $orders,
];
// 查询各个状态下的订单数量
$searchStatus = $this->model->searchStatusList();
// 所有的数量
$result['all'] = $this->model->withTrashed()->sheepFilter(true, function ($filters) {
unset($filters['status']);
return $filters;
})->count();
foreach ($searchStatus as $status => $text) {
$result[$status] = $this->model->withTrashed()->sheepFilter(true, function ($filters) use ($status) {
$filters['status'] = $status;
return $filters;
})->count();
}
$this->success('获取成功', null, $result);
}
// 获取数据类型
public function getType()
{
$type = $this->model->typeList();
$payType = (new PayModel)->payTypeList();
$platform = $this->model->platformList();
$status = $this->model->searchStatusList();
$result = [
'type' => $type,
'pay_type' => $payType,
'platform' => $platform,
'status' => $status
];
$data = [];
foreach ($result as $key => $list) {
$data[$key][] = ['name' => '全部', 'type' => 'all'];
foreach ($list as $k => $v) {
$data[$key][] = [
'name' => $v,
'type' => $k
];
}
}
$this->success('获取成功', null, $data);
}
/**
* 订单详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$order = $this->model->withTrashed()->with(['user', 'pays'])->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order->pay_type = $order->pay_type;
$order->pay_type_text = $order->pay_type_text;
$this->success('获取成功', null, $order);
}
public function export()
{
$cellTitles = [
// 订单表字段
'order_id' => 'Id',
'order_sn' => '订单号',
'type_text' => '订单类型',
'user_nickname' => '下单用户',
'user_mobile' => '手机号',
'status_text' => '订单状态',
'pay_type_text' => '支付类型',
'remark' => '用户备注',
'order_amount' => '订单总金额',
'pay_fee' => '应付总金额',
'real_pay_fee' => '实付总金额',
'remain_pay_fee' => '剩余支付金额',
'paid_time' => '支付完成时间',
'platform_text' => '交易平台',
'createtime' => '下单时间',
];
// 数据总条数
$total = $this->model->withTrashed()->sheepFilter()->count();
if ($total <= 0) {
$this->error('导出数据为空');
}
$export = new \addons\shopro\library\Export();
$params = [
'file_name' => '交易订单列表',
'cell_titles' => $cellTitles,
'total' => $total,
];
$total_order_amount = 0;
$total_pay_fee = 0;
$total_real_pay_fee = 0;
$result = $export->export($params, function ($pages) use (&$total_order_amount, &$total_pay_fee, &$total_real_pay_fee, $total) {
$datas = $this->model->withTrashed()->sheepFilter()->with(['user'])
->limit((($pages['page'] - 1) * $pages['list_rows']), $pages['list_rows'])
->select();
$datas = collection($datas);
$datas = $datas->each(function ($order) {
$order->pay_type_text = $order->pay_type_text;
})->toArray();
$newDatas = [];
foreach ($datas as &$order) {
$data = [
'order_id' => $order['id'],
'order_sn' => $order['order_sn'],
'type_text' => $order['type_text'],
'user_nickname' => $order['user'] ? $order['user']['nickname'] : '-',
'user_mobile' => $order['user'] ? $order['user']['mobile'] . ' ' : '-',
'status_text' => $order['status_text'],
'pay_type_text' => is_array($order['pay_type_text']) ? join(',', $order['pay_type_text']) : ($order['pay_type_text'] ?: ''),
'remark' => $order['remark'],
'order_amount' => $order['order_amount'],
'pay_fee' => $order['pay_fee'],
'real_pay_fee' => bcsub($order['pay_fee'], $order['remain_pay_fee'], 2),
'remain_pay_fee' => $order['remain_pay_fee'],
'paid_time' => $order['paid_time'],
'platform_text' => $order['platform_text'],
'createtime' => $order['createtime'],
];
$newDatas[] = $data;
}
$total_order_amount += array_sum(array_column($newDatas, 'order_amount'));
$total_pay_fee += array_sum(array_column($newDatas, 'pay_fee'));
$total_real_pay_fee += array_sum(array_column($newDatas, 'real_pay_fee'));
if ($pages['is_last_page']) {
$newDatas[] = ['order_id' => "订单总数:" . $total . ";订单总金额:¥" . $total_order_amount . ";应付总金额:¥" . $total_pay_fee . ";实付总金额:¥" . $total_real_pay_fee];
}
return $newDatas;
});
$this->success('导出成功' . (isset($result['file_path']) && $result['file_path'] ? ',请在服务器: “' . $result['file_path'] . '” 查看' : ''), null, $result);
}
}

View File

@@ -0,0 +1,303 @@
<?php
namespace app\admin\controller\shopro\traits;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\goods\Sku as SkuModel;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use addons\shopro\traits\StockWarning as StockWarningTrait;
trait SkuPrice
{
use StockWarningTrait;
/**
* 编辑规格
*
* @param GoodsModel $goods
* @param array $sku
* @param string $type
* @return void
*/
private function editSku($goods, $type = 'add')
{
if ($goods['is_sku']) {
// 多规格
$this->editMultSku($goods, $type);
} else {
$this->editSimSku($goods, $type);
}
}
/**
* 添加编辑单规格
*
* @param GoodsModel $goods
* @param string $type
* @return void
*/
protected function editSimSku($goods, $type = 'add')
{
$params = $this->request->only([
'stock', 'stock_warning', 'sn', 'weight', 'cost_price', 'original_price', 'price'
]);
$data = [
"goods_sku_ids" => null,
"goods_sku_text" => null,
"image" => null,
"goods_id" => $goods->id,
"stock" => $params['stock'] ?? 0,
"stock_warning" => isset($params['stock_warning']) && is_numeric($params['stock_warning'])
? $params['stock_warning'] : null,
"sn" => $params['sn'] ?? "",
"weight" => isset($params['weight']) ? floatval($params['weight']) : 0,
"cost_price" => $params['cost_price'] ?? 0,
"original_price" => $params['original_price'] ?? 0,
"price" => $params['price'] ?? 0,
"status" => 'up'
];
if ($type == 'edit') {
// 查询
$skuPrice = SkuPriceModel::where('goods_id', $goods->id)->order('id', 'asc')->find();
if ($skuPrice) {
// 删除多余的这个商品的其他规格以及规格项(防止多规格改为了单规格,遗留一批多余的 sku_price)
SkuPriceModel::where('goods_id', $goods->id)->where('id', '<>', $skuPrice->id)->delete();
SkuModel::where('goods_id', $goods->id)->delete();
}
unset($data['stock']); // 移除库存(库存只能通过补货增加)
}
if (!isset($skuPrice) || !$skuPrice) {
$skuPrice = new SkuPriceModel();
}
$skuPrice->save($data);
if ($type == 'add') {
// 增加补货记录
$this->addStockLog($skuPrice, 0, $data['stock'], $type);
// 检测库存预警
$this->checkStockWarning($skuPrice, $type);
}
}
/**
* 添加编辑多规格
*
* @param GoodsModel $goods
* @param string $type
* @return void
*/
protected function editMultSku($goods, $type = 'add')
{
$params = $this->request->only([
'skus', 'sku_prices'
]);
$skus = $params['skus'] ?? [];
$skuPrices = $params['sku_prices'] ?? [];
$this->checkMultSku($skus, $skuPrices);
// 编辑保存规格项
$allChildrenSku = $this->saveSkus($goods, $skus, $type);
if ($type == 'edit') {
// 编辑旧商品,先删除老的不用的 skuPrice
$oldSkuPriceIds = array_column($skuPrices, 'id');
// 删除当前商品老的除了在基础上修改的skuPrice
SkuPriceModel::where('goods_id', $goods->id)
->whereNotIn('id', $oldSkuPriceIds)->delete();
// 删除失效的库存预警记录
$this->delNotStockWarning($oldSkuPriceIds, $goods->id);
}
$min_key = null; // 最小加个对应的键值
$min_price = min(array_column($skuPrices, 'price')); // 规格最小价格
$originPrices = array_filter(array_column($skuPrices, 'original_price'));
$min_original_price = $originPrices ? min($originPrices) : 0; // 规格最小原始价格
foreach ($skuPrices as $key => &$skuPrice) {
$skuPrice['goods_sku_ids'] = $this->getRealSkuIds($skuPrice['goods_sku_temp_ids'], $allChildrenSku);
$skuPrice['goods_id'] = $goods->id;
$skuPrice['goods_sku_text'] = is_array($skuPrice['goods_sku_text']) ? join(',', $skuPrice['goods_sku_text']) : $skuPrice['goods_sku_text'];
$skuPrice['stock_warning'] = isset($skuPrice['stock_warning']) && is_numeric($skuPrice['stock_warning'])
? $skuPrice['stock_warning'] : null; // null 为关闭商品库存预警, 采用默认库存预警
// 移除无用 属性
if ($type == 'add') {
// 添加直接移除 id
unset($skuPrice['id']);
}
unset($skuPrice['temp_id']); // 前端临时 id
unset($skuPrice['goods_sku_temp_ids']); // 前端临时规格 id,查找真实 id 用
unset($skuPrice['createtime'], $skuPrice['updatetime']); // 删除时间
$skuPriceModel = new SkuPriceModel();
if (isset($skuPrice['id']) && $skuPrice['id']) {
// type == 'edit'
unset($skuPrice['stock']); // 编辑商品 不能编辑库存,只能通过补货
$skuPriceModel = $skuPriceModel->find($skuPrice['id']);
}
if ($skuPriceModel) {
$skuPriceModel->allowField(true)->save($skuPrice);
if ($type == 'add') {
// 增加补货记录
$this->addStockLog($skuPriceModel, 0, $skuPrice['stock'], 'add'); // 记录库存记录
// 检测库存预警
$this->checkStockWarning($skuPriceModel, $type);
}
}
if (is_null($min_key) && $min_price == $skuPrice['price']) {
$min_key = $key;
}
}
// 重新赋值最小价格和原价
$goods->original_price = $skuPrices[$min_key]['original_price'] ?? $min_original_price; // 最小价格规格对应的原价
$goods->price = $min_price;
$goods->save();
}
/**
* 校验多规格是否填写完整
*
* @param array $skus
* @param array $skuPrices
* @return void
*/
private function checkMultSku($skus, $skuPrices)
{
if (count($skus) < 1) {
error_stop('请填写规格列表');
}
foreach ($skus as $key => $sku) {
if (count($sku['children']) <= 0) {
error_stop('主规格至少要有一个子规格');
}
// 验证子规格不能为空
foreach ($sku['children'] as $k => $child) {
if (!isset($child['name']) || empty(trim($child['name']))) {
error_stop('子规格不能为空');
}
}
}
if (count($skuPrices) < 1) {
error_stop('请填写规格价格');
}
foreach ($skuPrices as &$price) {
// 校验多规格属性
$this->svalidate($price, '.sku_params');
}
}
/**
* 根据前端临时 temp_id 获取真实的数据库 id
*
* @param array $newGoodsSkuIds
* @param array $allChildrenSku
* @return string
*/
private function getRealSkuIds($newGoodsSkuIds, $allChildrenSku)
{
$newIdsArray = [];
foreach ($newGoodsSkuIds as $id) {
$newIdsArray[] = $allChildrenSku[$id];
}
return join(',', $newIdsArray);
}
/**
* 差异更新 规格规格项(多的删除,少的添加)
*
* @param GoodsModel $goods
* @param array $skus
* @param string $type
* @return array
*/
private function saveSkus($goods, $skus, $type = 'add')
{
$allChildrenSku = [];
if ($type == 'edit') {
// 删除无用老规格
// 拿出需要更新的老规格
$oldSkuIds = [];
foreach ($skus as $key => $sku) {
$oldSkuIds[] = $sku['id'];
$childSkuIds = [];
if ($sku['children']) {
// 子项 id
$childSkuIds = array_column($sku['children'], 'id');
}
$oldSkuIds = array_merge($oldSkuIds, $childSkuIds);
$oldSkuIds = array_unique($oldSkuIds);
}
// 删除老的除了在基础上修改的规格项
SkuModel::where('goods_id', $goods->id)->whereNotIn('id', $oldSkuIds)->delete();
}
foreach ($skus as $s1 => &$k1) {
//添加主规格
$current_id = $k1['id'] ?? 0;
if ($k1['id']) {
// 编辑
SkuModel::where('id', $k1['id'])->update([
'name' => $k1['name'],
]);
} else {
// 新增
$k1Model = new SkuModel();
$k1Model->save([
'name' => $k1['name'],
'parent_id' => 0,
'goods_id' => $goods->id
]);
$k1['id'] = $current_id = $k1Model->id;
}
foreach ($k1['children'] as $s2 => &$k2) {
$current_child_id = $k2['id'] ?? 0;
if ($k2['id']) {
// 编辑
SkuModel::where('id', $k2['id'])->update([
'name' => $k2['name'],
]);
} else {
// 新增
$k2Model = new SkuModel();
$k2Model->save([
'name' => $k2['name'],
'parent_id' => $current_id,
'goods_id' => $goods->id
]);
$current_child_id = $k2Model->id;
}
$allChildrenSku[$k2['temp_id']] = $current_child_id;
$k2['id'] = $current_child_id;
$k2['parent_id'] = $current_id;
}
}
return $allChildrenSku;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace app\admin\controller\shopro\user;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\user\Coupon as UserCouponModel;
class Coupon extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new UserCouponModel;
}
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$coupon_id = $this->request->param('coupon_id');
$coupons = $this->model->sheepFilter()->with(['user', 'order'])
->where('coupon_id', $coupon_id)
->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $coupons);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace app\admin\controller\shopro\user;
use think\Db;
use app\admin\controller\shopro\Common;
use app\admin\model\UserGroup as GroupModel;
class Group extends Common
{
protected $noNeedRight = ['select'];
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new GroupModel;
}
public function select()
{
$list = \app\admin\model\UserGroup::field('id,name,status')->select();
$this->success('', null, $list);
}
}

View File

@@ -0,0 +1,152 @@
<?php
namespace app\admin\controller\shopro\user;
use think\Db;
use app\admin\controller\shopro\Common;
use addons\shopro\service\Wallet as WalletService;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\shopro\user\Coupon as UserCouponModel;
class User extends Common
{
protected $model = null;
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->model = new UserModel;
}
/**
* 用户列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$data = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $data);
}
/**
* 用户详情
*
* @param $id
*/
public function detail($id)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$user = $this->model->with(['third_oauth', 'parent_user'])->where('id', $id)->find();
if (!$user) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $user);
}
/**
* 更新用户
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
$params = $this->request->only(['username', 'nickname', 'mobile', 'password', 'avatar', 'gender', 'email', 'status']);
if (empty($params['password'])) unset($params['password']);
if (empty($params['username'])) unset($params['username']);
$params['id'] = $id;
$this->svalidate($params, '.edit');
unset($params['id']);
$user = $this->model->where('id', $id)->find();
$user->save($params);
$this->success('更新成功', null, $user);
}
/**
* 删除用户(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$id = explode(',', $id);
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
public function recharge()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['id', 'type', 'amount', 'memo']);
if (!in_array($params['type'], ['money', 'score'])) {
error_stop('参数错误');
}
$result = Db::transaction(function () use ($params) {
return WalletService::change($params['id'], $params['type'], $params['amount'], 'admin_recharge', [], $params['memo']);
});
if ($result) {
$this->success('充值成功');
}
$this->error('充值失败');
}
/**
* 用户优惠券列表
*/
public function coupon($id)
{
$userCoupons = UserCouponModel::sheepFilter()->with('coupon')->where('user_id', $id)
->order('id', 'desc')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $userCoupons);
}
public function select()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$data = $this->model->sheepFilter()->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', null, $data);
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace app\admin\controller\shopro\user;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\user\WalletLog as WalletLogModel;
use addons\shopro\library\Operator;
class WalletLog extends Common
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new WalletLogModel;
}
/**
* 余额记录
*/
public function money($id)
{
$list_rows = $this->request->param('list_rows', 10);
$walletLogs = WalletLogModel::where('user_id', $id)->money()->order('id', 'desc')->paginate($list_rows);
// 多态关联 oper
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'admin' => \app\admin\model\Admin::class,
'system' => \app\admin\model\Admin::class,
];
$walletLogs = morph_to($walletLogs, $morphs, ['oper_type', 'oper_id']);
$walletLogs = $walletLogs->toArray();
// 解析操作人信息
foreach ($walletLogs['data'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('', null, $walletLogs);
}
/**
* 积分记录
*/
public function score($id)
{
$list_rows = $this->request->param('list_rows', 10);
$walletLogs = WalletLogModel::where('user_id', $id)->score()->order('id', 'desc')->paginate($list_rows);
// 多态关联 oper
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'admin' => \app\admin\model\Admin::class,
'system' => \app\admin\model\Admin::class,
];
$walletLogs = morph_to($walletLogs, $morphs, ['oper_type', 'oper_id']);
$walletLogs = $walletLogs->toArray();
// 解析操作人信息
foreach ($walletLogs['data'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('', null, $walletLogs);
}
/**
* 佣金记录
*/
public function commission($id)
{
$list_rows = $this->request->param('list_rows', 10);
$walletLogs = WalletLogModel::where('user_id', $id)->commission()->order('id', 'desc')->paginate($list_rows);
// 多态关联 oper
$morphs = [
'user' => \app\admin\model\shopro\user\User::class,
'admin' => \app\admin\model\Admin::class,
'system' => \app\admin\model\Admin::class,
];
$walletLogs = morph_to($walletLogs, $morphs, ['oper_type', 'oper_id']);
$walletLogs = $walletLogs->toArray();
// 解析操作人信息
foreach ($walletLogs['data'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success('', null, $walletLogs);
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace app\admin\controller\shopro\wechat;
use fast\Random;
use addons\shopro\facade\Wechat;
use app\admin\model\shopro\ThirdOauth;
use app\admin\controller\shopro\Common;
class Admin extends Common
{
protected $wechat;
protected $noNeedRight = ['getQrcode', 'checkScan', 'unbind'];
public function _initialize()
{
parent::_initialize();
$this->wechat = Wechat::officialAccountManage();
}
// 获取公众号二维码
public function getQrcode()
{
$event = $this->request->param('event');
if (!in_array($event, ['bind'])) {
$this->error('参数错误');
}
$adminId = $this->auth->id;
$thirdOauth = ThirdOauth::where([
'provider' => 'wechat',
'platform' => 'admin',
'admin_id' => $adminId
])->find();
if ($thirdOauth) {
error_stop('已绑定微信账号', -2, $thirdOauth);
}
// 二维码和缓存过期时间
$expireTime = 1 * 60;
// 事件唯一标识
$eventId = Random::uuid();
$cacheKey = "wechatAdmin.{$event}.{$eventId}";
cache($cacheKey, ['id' => 0], $expireTime);
try {
$result = $this->wechat->qrcode->temporary($cacheKey, $expireTime);
$qrcode = $this->wechat->qrcode->url($result['ticket']);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success('', null, [
'url' => $qrcode,
'eventId' => $eventId
]);
}
// 检查扫码结果
public function checkScan()
{
$event = $this->request->param('event');
$eventId = $this->request->param('eventId');
if (!in_array($event, ['bind'])) {
error_stop('参数错误');
}
$cacheKey = "wechatAdmin.{$event}.{$eventId}";
$cacheValue = cache($cacheKey);
if (empty($cacheValue)) {
error_stop('二维码已过期, 请重新扫码');
}
if ($cacheValue['id'] === 0) {
error_stop('等待扫码', -1);
}
if ($cacheValue['id'] !== 0) {
switch ($event) {
case 'bind':
$adminId = $this->auth->id;
$thirdOauth = ThirdOauth::where([
'provider' => 'wechat',
'platform' => 'admin',
'openid' => $cacheValue['id'],
])->find();
if ($thirdOauth && $thirdOauth->admin_id !== 0) {
error_stop('该微信账号已被绑定');
}
if (!$thirdOauth) {
$thirdOauth = ThirdOauth::create([
'provider' => 'wechat',
'platform' => 'admin',
'openid' => $cacheValue['id'],
'admin_id' => $adminId
]);
} else {
$thirdOauth->admin_id = $adminId;
$thirdOauth->save();
}
break;
}
$this->success();
}
}
// 解绑
public function unbind()
{
$adminId = $this->auth->id;
$thirdOauth = ThirdOauth::where([
'provider' => 'wechat',
'platform' => 'admin',
'admin_id' => $adminId
])->find();
if ($thirdOauth) {
$thirdOauth->admin_id = 0;
$thirdOauth->save();
}
$this->success();
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\admin\controller\shopro\wechat;
use app\admin\model\shopro\Config as ShoproConfig;
use app\admin\controller\shopro\Common;
class Config extends Common
{
/**
* 公众号配置
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
if ('GET' === $this->request->method()) {
$configs = ShoproConfig::getConfigs('wechat.officialAccount', false);
$configs['server_url'] = request()->domain() . '/addons/shopro/wechat.serve';
} elseif ('POST' === $this->request->method()) {
$configs = ShoproConfig::setConfigs('wechat.officialAccount', $this->request->param());
}
$this->success('操作成功', null, $configs);
}
}

View File

@@ -0,0 +1,178 @@
<?php
namespace app\admin\controller\shopro\wechat;
use app\admin\controller\shopro\Common;
use addons\shopro\facade\Wechat;
use think\Db;
use addons\shopro\exception\ShoproException;
class Material extends Common
{
protected $wechat = null;
protected $model = null;
protected $noNeedRight = ['select'];
public function _initialize()
{
parent::_initialize();
$this->wechat = Wechat::officialAccountManage();
$this->model = new \app\admin\model\shopro\wechat\Material;
}
/**
* 素材列表
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$list_rows = intval($this->request->param('list_rows', 10));
$page = intval($this->request->param('page', 1));
$type = $this->request->param('type', 'news');
$offset = intval(($page - 1) * $list_rows);
if (in_array($type, ['text', 'link'])) {
$data = $this->model->sheepFilter()->where('type', $type)->paginate(request()->param('list_rows', 10));
} else {
// 使用微信远程素材列表
try {
$res = $this->wechat->material->list($type, $offset, $list_rows);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$data = [
'current_page' => $page,
'data' => $res['item'],
'last_page' => intval(ceil($res['total_count'] / $list_rows)),
'per_page' => $list_rows,
'total' => intval($res['total_count']),
];
}
$this->success('', null, $data);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->get($id);
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 添加
*
* @return \think\Response
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['type', 'content']);
if ($params['type'] === 'text') {
$params['content'] = urldecode($params['content']);
}
Db::transaction(function () use ($params) {
$this->model->save($params);
});
$this->success('保存成功');
}
/**
* 编辑
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$material = $this->model->get($id);
$params = $this->request->only(['type', 'content']);
if ($params['type'] === 'text') {
$params['content'] = urldecode($params['content']);
}
Db::transaction(function () use ($params, $material) {
$material->save($params);
});
$this->success('更新成功');
}
/**
* 删除
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
$is_real = $this->request->param('is_real', 0);
Db::transaction(function () use ($id, $is_real) {
$menu = $this->model->get($id);
if ($is_real) {
$menu->force()->delete();
} else {
$menu->delete();
}
});
$this->success('删除成功');
}
/**
* 菜单列表
*
* @return Response
*/
public function select()
{
$list_rows = intval($this->request->param('list_rows', 10));
$page = intval($this->request->param('page', 1));
$type = $this->request->param('type', 'news');
$offset = intval(($page - 1) * $list_rows);
if (in_array($type, ['text', 'link'])) {
$data = $this->model->where('type', $type)->order('id desc')->paginate(request()->param('list_rows', 10));
} else {
// 使用微信远程素材列表
try {
$res = $this->wechat->material->list($type, $offset, $list_rows);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$data = [
'current_page' => $page,
'data' => $res['item'],
'last_page' => intval(ceil($res['total_count'] / $list_rows)),
'per_page' => $list_rows,
'total' => intval($res['total_count']),
];
}
$this->success('获取成功', null, $data);
}
}

View File

@@ -0,0 +1,223 @@
<?php
namespace app\admin\controller\shopro\wechat;
use app\admin\controller\shopro\Common;
use addons\shopro\facade\Wechat;
use think\Db;
use addons\shopro\exception\ShoproException;
class Menu extends Common
{
protected $wechat = null;
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->wechat = Wechat::officialAccountManage();
$this->model = new \app\admin\model\shopro\wechat\Menu;
}
/**
* 公众号配置
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$current = $this->getCurrentMenu();
$data = $this->model->sheepFilter()->paginate(request()->param('list_rows', 10));
$this->success('操作成功', null, ['current' => $current, 'list' => $data]);
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->get($id);
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 添加菜单
*
* @param int $publish 发布状态:0=不发布,1=直接发布
* @return \think\Response
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$publish = $this->request->param('publish', 0);
$params = $this->request->only(['name', 'rules']);
// 参数校验
$this->svalidate($params, '.add');
Db::transaction(function () use ($params, $publish) {
$menu = $this->model->save($params);
if ($menu && $publish) {
$this->publishMenu($this->model->id);
}
return $menu;
});
$this->success('保存成功');
}
/**
* 编辑
*
* @param $id
* @return \think\Response
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$menu = $this->model->get($id);
$publish = $this->request->param('publish', 0);
$params = $this->request->only(['name', 'rules']);
// 参数校验
$this->svalidate($params);
$menu = Db::transaction(function () use ($params, $menu, $publish) {
$menu->save($params);
if ($publish) {
$this->publishMenu($menu->id);
}
return $menu;
});
$this->success('更新成功');
}
/**
* 删除
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
Db::transaction(function () use ($id) {
$menu = $this->model->get($id);
$menu->delete();
});
$this->success('删除成功');
}
/**
* 发布菜单
*
* @param $id
* @return \think\Response
*/
public function publish($id)
{
Db::transaction(function () use ($id) {
return $this->publishMenu($id);
});
$this->success('发布成功');
}
/**
* 复制菜单
*
* @return Response
*/
public function copy($id = 0)
{
if ($id == 0) {
$data = [
'name' => '复制 当前菜单',
'rules' => $this->getCurrentMenu(),
];
} else {
$menu = $this->model->get($id);
$data = [
'name' => '复制 ' . $menu->name,
'rules' => $menu->rules
];
}
$menu = $this->model->save($data);
$this->success('复制成功');
}
// 发布菜单
private function publishMenu($id)
{
$menu = $this->model->get($id);
if ($this->setCurrentMenu($menu->rules)) {
$this->model->where('id', '<>', $menu->id)->update(['status' => 0]);
return $menu->save([
'status' => 1,
'publishtime' => time()
]);
}
return false;
}
// 获取当前菜单
private function getCurrentMenu()
{
try {
$currentMenu = $this->wechat->menu->current();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if (isset($currentMenu['selfmenu_info']['button'])) {
$buttons = $currentMenu['selfmenu_info']['button'];
foreach ($buttons as &$button) {
if (isset($button['sub_button'])) {
$button['sub_button'] = $button['sub_button']['list'];
}
}
return $buttons;
} else {
return [];
}
}
// 设置菜单
private function setCurrentMenu($rules)
{
try {
$result = $this->wechat->menu->create($rules);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if (isset($result['errcode']) && $result['errcode'] === 0) {
return true;
} else {
$this->error($result['errmsg'] ?? '发布失败');
}
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace app\admin\controller\shopro\wechat;
use app\admin\controller\shopro\Common;
use think\Db;
/**
* 常见问题
*/
class Reply extends Common
{
/**
* Faq模型对象
* @var \app\admin\model\shopro\wechat\Reply
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\shopro\wechat\Reply;
}
/**
* 查看
*
* @return string|Json
* @throws \think\Exception
* @throws DbException
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$group = $this->request->param('group', 'keywords');
$data = $this->model->sheepFilter()->where('group', $group)->select();
$this->success('操作成功', null, $data);
}
/**
* 添加
*/
public function add()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$params = $this->request->only(['group', 'keywords', 'type', 'status', 'content']);
Db::transaction(function () use ($params) {
$result = $this->model->save($params);
if($result) {
$reply = $this->model;
if($reply->group !== 'keywords' && $reply->status === 'enable') {
$this->model->where('group', $reply->group)->where('id', '<>', $reply->id)->enable()->update(['status' => 'disabled']);
}
}
return $result;
});
$this->success('保存成功');
}
/**
* 详情
*
* @param $id
* @return \think\Response
*/
public function detail($id)
{
$detail = $this->model->get($id);
if (!$detail) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', null, $detail);
}
/**
* 编辑(支持批量)
*/
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch('add');
}
$reply = $this->model->get($id);
$params = $this->request->only(['keywords', 'type', 'status', 'content']);
// 参数校验
// $this->svalidate($params);
$result = Db::transaction(function () use ($params, $reply) {
$result = $reply->save($params);
if($result) {
if($reply->group !== 'keywords' && $reply->status === 'enable') {
$this->model->where('group', $reply->group)->where('id', '<>', $reply->id)->enable()->update(['status' => 'disabled']);
}
}
return $result;
});
if ($result) {
$this->success('更新成功', null, $result);
} else {
$this->error('更新失败');
}
}
/**
* 删除(支持批量)
*
* @param $id
* @return \think\Response
*/
public function delete($id)
{
if (empty($id)) {
$this->error(__('Parameter %s can not be empty', 'id'));
}
$list = $this->model->where('id', 'in', $id)->select();
$result = Db::transaction(function () use ($list) {
$count = 0;
foreach ($list as $item) {
$count += $item->delete();
}
return $count;
});
if ($result) {
$this->success('删除成功', null, $result);
} else {
$this->error(__('No rows were deleted'));
}
}
}