- 框架初始化
 - 安装插件
 - 修复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,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);
}
}