1.1.40
This commit is contained in:
parent
1d59f59117
commit
dd83a2e9da
@ -10,6 +10,13 @@
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v1.1.40
|
||||
```
|
||||
新增:微信小程序直播功能
|
||||
优化:商品评价过滤无效内容
|
||||
|
||||
注:本次更新须重新发布小程序
|
||||
```
|
||||
### v1.1.39
|
||||
|
||||
```
|
||||
@ -27,7 +34,6 @@
|
||||
修复:小程序端订单页未支付提示
|
||||
|
||||
注:本次更新须重新发布小程序
|
||||
|
||||
```
|
||||
|
||||
### v1.1.38
|
||||
|
@ -4716,6 +4716,12 @@ INSERT INTO `yoshop_store_access` VALUES ('10438', '积分管理', 'market.point
|
||||
|
||||
INSERT INTO `yoshop_store_access` VALUES ('11003', '数据统计', 'statistics.data/index', '0', '138', '1572507520', '1572507520');
|
||||
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10462', '小程序直播', 'apps.live', '10074', '125', '1585120375', '1585120375');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10463', '直播间管理', 'apps.live.room/index', '10462', '100', '1585120404', '1585120404');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10464', '同步刷新', 'apps.live.room/refresh', '10463', '100', '1585120404', '1585120404');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10465', '设置置顶状态', 'apps.live.room/refresh', '10463', '100', '1585120404', '1585120404');
|
||||
|
||||
|
||||
|
||||
|
||||
# 商家用户角色表
|
||||
|
28
doc/database/upgrade/v1.1.40.sql
Normal file
28
doc/database/upgrade/v1.1.40.sql
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
CREATE TABLE `yoshop_wxapp_live_room` (
|
||||
`room_id` int(11) unsigned NOT NULL COMMENT '直播间id',
|
||||
`room_name` varchar(200) NOT NULL DEFAULT '' COMMENT '直播间名称',
|
||||
`cover_img` varchar(255) DEFAULT '' COMMENT '分享卡片封面',
|
||||
`share_img` varchar(255) DEFAULT '' COMMENT '直播间背景墙封面',
|
||||
`anchor_name` varchar(30) NOT NULL DEFAULT '' COMMENT '主播昵称',
|
||||
`start_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '开播时间',
|
||||
`end_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '结束时间',
|
||||
`live_status` tinyint(3) unsigned NOT NULL DEFAULT '102' COMMENT '直播状态(101: 直播中, 102: 未开始, 103: 已结束, 104: 禁播, 105: 暂停中, 106: 异常, 107: 已过期)',
|
||||
`is_top` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '置顶状态(0未置顶 1已置顶)',
|
||||
`is_delete` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '软删除(0未删除 1已删除)',
|
||||
`wxapp_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '小程序id',
|
||||
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
|
||||
PRIMARY KEY (`room_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='微信小程序直播间记录表';
|
||||
|
||||
|
||||
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10462', '小程序直播', 'apps.live', '10074', '125', '1585120375', '1585120375');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10463', '直播间管理', 'apps.live.room/index', '10462', '100', '1585120404', '1585120404');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10464', '同步刷新', 'apps.live.room/refresh', '10463', '100', '1585120404', '1585120404');
|
||||
INSERT INTO `yoshop_store_access` (`access_id`, `name`, `url`, `parent_id`, `sort`, `create_time`, `update_time`) VALUES ('10465', '设置置顶状态', 'apps.live.room/refresh', '10463', '100', '1585120404', '1585120404');
|
||||
|
||||
|
||||
|
26
source/application/api/controller/live/Room.php
Normal file
26
source/application/api/controller/live/Room.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller\live;
|
||||
|
||||
use app\api\controller\Controller;
|
||||
use app\api\model\wxapp\LiveRoom as LiveRoomModel;
|
||||
|
||||
/**
|
||||
* 微信小程序直播列表
|
||||
* Class Room
|
||||
* @package app\api\controller\live
|
||||
*/
|
||||
class Room extends Controller
|
||||
{
|
||||
/**
|
||||
* 获取直播间列表
|
||||
* @return mixed
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
$model = new LiveRoomModel;
|
||||
$list = $model->getList();
|
||||
return $this->renderSuccess(compact('list'));
|
||||
}
|
||||
}
|
@ -41,8 +41,8 @@ class Comment extends Controller
|
||||
}
|
||||
// 提交商品评价
|
||||
if ($this->request->isPost()) {
|
||||
$formData = $this->request->post('formData', '', null);
|
||||
if ($model->addForOrder($order, $goodsList, $formData)) {
|
||||
$post = $this->request->post('formData');
|
||||
if ($model->addForOrder($order, $goodsList, $post)) {
|
||||
return $this->renderSuccess([], '评价发表成功');
|
||||
}
|
||||
return $this->renderError($model->getError() ?: '评价发表失败');
|
||||
|
@ -4,7 +4,7 @@ namespace app\api\model;
|
||||
|
||||
use app\common\exception\BaseException;
|
||||
use app\common\model\Comment as CommentModel;
|
||||
use think\Db;
|
||||
use app\common\library\helper;
|
||||
|
||||
/**
|
||||
* 商品评价模型
|
||||
@ -107,14 +107,14 @@ class Comment extends CommentModel
|
||||
* 根据已完成订单商品 添加评价
|
||||
* @param Order $order
|
||||
* @param \think\Collection|OrderGoods $goodsList
|
||||
* @param $formJsonData
|
||||
* @param $post
|
||||
* @return boolean
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addForOrder($order, $goodsList, $formJsonData)
|
||||
public function addForOrder($order, $goodsList, $post)
|
||||
{
|
||||
// 生成 formData
|
||||
$formData = $this->formatFormData($formJsonData);
|
||||
$formData = $this->formatFormData($post);
|
||||
// 生成评价数据
|
||||
$data = $this->createCommentData($order['user_id'], $order['order_id'], $goodsList, $formData);
|
||||
if (empty($data)) {
|
||||
@ -173,6 +173,7 @@ class Comment extends CommentModel
|
||||
throw new BaseException(['msg' => '提交的数据不合法']);
|
||||
}
|
||||
$item = $formData[$goods['order_goods_id']];
|
||||
$item['content'] = trim($item['content']);
|
||||
!empty($item['content']) && $data[$goods['order_goods_id']] = [
|
||||
'score' => $item['score'],
|
||||
'content' => $item['content'],
|
||||
@ -191,12 +192,13 @@ class Comment extends CommentModel
|
||||
|
||||
/**
|
||||
* 格式化 formData
|
||||
* @param string $formJsonData
|
||||
* @param string $post
|
||||
* @return array
|
||||
*/
|
||||
private function formatFormData($formJsonData)
|
||||
private function formatFormData($post)
|
||||
{
|
||||
return array_column(json_decode($formJsonData, true), null, 'order_goods_id');
|
||||
$formJsonData = htmlspecialchars_decode($post);
|
||||
return helper::arrayColumn2Key(helper::jsonDecode($formJsonData), 'order_goods_id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
77
source/application/api/model/wxapp/LiveRoom.php
Normal file
77
source/application/api/model/wxapp/LiveRoom.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model\wxapp;
|
||||
|
||||
use app\common\model\wxapp\LiveRoom as LiveRoomModel;
|
||||
use app\common\enum\live\LiveStatus as LiveStatusEnum;
|
||||
|
||||
/**
|
||||
* 微信小程序直播间模型
|
||||
* Class LiveRoom
|
||||
* @package app\api\model\wxapp
|
||||
*/
|
||||
class LiveRoom extends LiveRoomModel
|
||||
{
|
||||
/**
|
||||
* 隐藏的字段
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [
|
||||
'is_delete',
|
||||
'wxapp_id',
|
||||
'create_time',
|
||||
'update_time',
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取直播间列表
|
||||
* @return \think\Paginator
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
// 直播间列表
|
||||
// mix: 可设置live_status条件来显示不同直播状态的房间
|
||||
$this->where('live_status', '<>', 107); // 已过期的不显示
|
||||
$list = $this->where('is_delete', '=', 0)
|
||||
->order([
|
||||
'is_top' => 'desc',
|
||||
'live_status' => 'asc',
|
||||
'create_time' => 'desc'
|
||||
])->paginate(15, false, [
|
||||
'query' => \request()->request()
|
||||
]);
|
||||
// 整理api数据
|
||||
foreach ($list as &$item) {
|
||||
$item['live_status_text_1'] = LiveStatusEnum::data()[$item['live_status']]['name'];
|
||||
$item['live_status_text_2'] = $item['live_status_text_1'];
|
||||
$item['live_status'] == 101 && $item['live_status_text_1'] = '正在直播中';
|
||||
$item['live_status'] == 102 && $item['live_status_text_1'] = $this->semanticStartTime($item->getData('start_time')) . ' 开播';
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 语义化开播时间
|
||||
* @param $startTime
|
||||
* @return string
|
||||
*/
|
||||
private function semanticStartTime($startTime)
|
||||
{
|
||||
// 转换为 YYYYMMDD 格式
|
||||
$startDate = date('Ymd', $startTime);
|
||||
// 获取今天的 YYYY-MM-DD 格式
|
||||
$todyDate = date('Ymd');
|
||||
// 获取明天的 YYYY-MM-DD 格式
|
||||
$tomorrowDate = date('Ymd', strtotime('+1 day'));
|
||||
// 使用IF当作字符串判断是否相等
|
||||
if ($startDate == $todyDate) {
|
||||
return date('今天H:i', $startTime);
|
||||
} elseif ($startDate == $tomorrowDate) {
|
||||
return date('明天H:i', $startTime);
|
||||
}
|
||||
// 常规日期格式
|
||||
return date('m/d H:i', $startTime);
|
||||
}
|
||||
|
||||
}
|
52
source/application/common/enum/live/LiveStatus.php
Normal file
52
source/application/common/enum/live/LiveStatus.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\enum\live;
|
||||
|
||||
use app\common\enum\EnumBasics;
|
||||
|
||||
/**
|
||||
* 微信小程序直播间状态枚举类
|
||||
* Class Room
|
||||
* @package app\common\enum\live
|
||||
*/
|
||||
class LiveStatus extends EnumBasics
|
||||
{
|
||||
/**
|
||||
* 获取枚举数据
|
||||
* @return array
|
||||
*/
|
||||
public static function data()
|
||||
{
|
||||
return [
|
||||
101 => [
|
||||
'name' => '直播中',
|
||||
'value' => 101,
|
||||
],
|
||||
102 => [
|
||||
'name' => '未开始',
|
||||
'value' => 102,
|
||||
],
|
||||
103 => [
|
||||
'name' => '已结束',
|
||||
'value' => 103,
|
||||
],
|
||||
104 => [
|
||||
'name' => '禁播',
|
||||
'value' => 104,
|
||||
],
|
||||
105 => [
|
||||
'name' => '暂停中',
|
||||
'value' => 105,
|
||||
],
|
||||
106 => [
|
||||
'name' => '异常',
|
||||
'value' => 106,
|
||||
],
|
||||
107 => [
|
||||
'name' => '已过期',
|
||||
'value' => 107,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -56,8 +56,8 @@ class WxBase
|
||||
// 请求API获取 access_token
|
||||
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
|
||||
$result = $this->get($url);
|
||||
$data = $this->jsonDecode($result);
|
||||
if (array_key_exists('errcode', $data)) {
|
||||
$response = $this->jsonDecode($result);
|
||||
if (array_key_exists('errcode', $response)) {
|
||||
throw new BaseException(['msg' => "access_token获取失败,错误信息:{$result}"]);
|
||||
}
|
||||
// 记录日志
|
||||
@ -68,7 +68,7 @@ class WxBase
|
||||
'result' => $result
|
||||
]);
|
||||
// 写入缓存
|
||||
Cache::set($cacheKey, $data['access_token'], 6000); // 7000
|
||||
Cache::set($cacheKey, $response['access_token'], 6000); // 7000
|
||||
}
|
||||
return Cache::get($cacheKey);
|
||||
}
|
||||
|
43
source/application/common/library/wechat/live/Room.php
Normal file
43
source/application/common/library/wechat/live/Room.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library\wechat\live;
|
||||
|
||||
use app\common\library\wechat\WxBase;
|
||||
|
||||
/**
|
||||
* 微信小程序直播接口
|
||||
* Class Room
|
||||
* @package app\common\library\wechat\live
|
||||
*/
|
||||
class Room extends WxBase
|
||||
{
|
||||
/**
|
||||
* 微信小程序直播-获取直播房间列表接口
|
||||
* api文档: https://developers.weixin.qq.com/miniprogram/dev/framework/liveplayer/live-player-plugin.html
|
||||
* @throws \app\common\exception\BaseException
|
||||
*/
|
||||
public function getLiveRoomList()
|
||||
{
|
||||
// 微信接口url
|
||||
$accessToken = $this->getAccessToken();
|
||||
$apiUrl = "http://api.weixin.qq.com/wxa/business/getliveinfo?access_token={$accessToken}";
|
||||
// 请求参数
|
||||
$params = $this->jsonEncode(['start' => 0, 'limit' => 100]);
|
||||
// 执行请求
|
||||
$result = $this->post($apiUrl, $params);
|
||||
// 记录日志
|
||||
$this->doLogs(['describe' => '微信小程序直播-获取直播房间列表接口', 'url' => $apiUrl, 'params' => $params, 'result' => $result]);
|
||||
// 返回结果
|
||||
$response = $this->jsonDecode($result);
|
||||
if (!isset($response['errcode'])) {
|
||||
$this->error = 'not found errcode';
|
||||
return false;
|
||||
}
|
||||
if ($response['errcode'] != 0) {
|
||||
$this->error = $response['errmsg'];
|
||||
return false;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@ -31,26 +31,28 @@ class Wxapp extends BaseModel
|
||||
*/
|
||||
public static function detail($wxapp_id = null)
|
||||
{
|
||||
return self::get($wxapp_id ?: []);
|
||||
return static::get($wxapp_id ?: []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中获取小程序信息
|
||||
* @param null $wxapp_id
|
||||
* @return mixed|null|static
|
||||
* @param int|null $wxappId 小程序id
|
||||
* @return array $data
|
||||
* @throws BaseException
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public static function getWxappCache($wxapp_id = null)
|
||||
public static function getWxappCache($wxappId = null)
|
||||
{
|
||||
if (is_null($wxapp_id)) {
|
||||
$self = new static();
|
||||
$wxapp_id = $self::$wxapp_id;
|
||||
}
|
||||
if (!$data = Cache::get('wxapp_' . $wxapp_id)) {
|
||||
$data = self::detail($wxapp_id);
|
||||
if (empty($data)) throw new BaseException(['msg' => '未找到当前小程序信息']);
|
||||
Cache::tag('cache')->set('wxapp_' . $wxapp_id, $data);
|
||||
// 小程序id
|
||||
is_null($wxappId) && $wxappId = static::$wxapp_id;
|
||||
if (!$data = Cache::get("wxapp_{$wxappId}")) {
|
||||
// 获取小程序详情, 解除hidden属性
|
||||
$detail = self::detail($wxappId)->hidden([], true);
|
||||
if (empty($detail)) throw new BaseException(['msg' => '未找到当前小程序信息']);
|
||||
// 写入缓存
|
||||
$data = $detail->toArray();
|
||||
Cache::tag('cache')->set("wxapp_{$wxappId}", $data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
47
source/application/common/model/wxapp/LiveRoom.php
Normal file
47
source/application/common/model/wxapp/LiveRoom.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model\wxapp;
|
||||
|
||||
use app\common\model\BaseModel;
|
||||
|
||||
/**
|
||||
* 微信小程序直播间模型
|
||||
* Class LiveRoom
|
||||
* @package app\common\model\wxapp
|
||||
*/
|
||||
class LiveRoom extends BaseModel
|
||||
{
|
||||
protected $name = 'wxapp_live_room';
|
||||
|
||||
/**
|
||||
* 获取器: 开播时间
|
||||
* @param $value
|
||||
* @return false|string
|
||||
*/
|
||||
public function getStartTimeAttr($value)
|
||||
{
|
||||
return \format_time($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取器: 结束时间
|
||||
* @param $value
|
||||
* @return false|string
|
||||
*/
|
||||
public function getEndTimeAttr($value)
|
||||
{
|
||||
return \format_time($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取直播间详情
|
||||
* @param $roomId
|
||||
* @return static|null
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public static function detail($roomId)
|
||||
{
|
||||
return static::get($roomId);
|
||||
}
|
||||
|
||||
}
|
60
source/application/store/controller/apps/live/Room.php
Normal file
60
source/application/store/controller/apps/live/Room.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace app\store\controller\apps\live;
|
||||
|
||||
use app\store\controller\Controller;
|
||||
use app\store\model\wxapp\LiveRoom as LiveRoomModel;
|
||||
|
||||
/**
|
||||
* 小程序直播间管理
|
||||
* Class Room
|
||||
* @package app\store\controller\apps\live
|
||||
*/
|
||||
class Room extends Controller
|
||||
{
|
||||
/**
|
||||
* 直播间列表页
|
||||
* @param string $search 检索词
|
||||
* @return mixed
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function index($search = '')
|
||||
{
|
||||
$model = new LiveRoomModel;
|
||||
$list = $model->getList($search);
|
||||
return $this->fetch('index', compact('list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步刷新直播间列表
|
||||
* @return array|bool
|
||||
* @throws \app\common\exception\BaseException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
$model = new LiveRoomModel;
|
||||
if ($model->refreshLiveList()) {
|
||||
return $this->renderSuccess('同步成功');
|
||||
}
|
||||
return $this->renderError($model->getError() ?: '同步失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改直播间置顶状态
|
||||
* @param $room_id
|
||||
* @param $is_top
|
||||
* @return array|bool
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function settop($room_id, $is_top)
|
||||
{
|
||||
// 商品详情
|
||||
$model = LiveRoomModel::detail($room_id);
|
||||
if (!$model->setIsTop($is_top)) {
|
||||
return $this->renderError('操作失败');
|
||||
}
|
||||
return $this->renderSuccess('操作成功');
|
||||
}
|
||||
|
||||
}
|
@ -544,7 +544,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => '好物圈',
|
||||
'index' => 'apps.wow.order/index',
|
||||
'index' => 'apps.wow.shoping/index',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => '商品收藏',
|
||||
@ -560,6 +560,16 @@ return [
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => '小程序直播',
|
||||
'index' => 'apps.live.room/index',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => '直播间管理',
|
||||
'index' => 'apps.live.room/index',
|
||||
],
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
'setting' => [
|
||||
|
201
source/application/store/model/wxapp/LiveRoom.php
Normal file
201
source/application/store/model/wxapp/LiveRoom.php
Normal file
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace app\store\model\wxapp;
|
||||
|
||||
use app\common\exception\BaseException;
|
||||
use app\store\model\Wxapp as WxappModel;
|
||||
use app\common\model\wxapp\LiveRoom as LiveRoomModel;
|
||||
use app\common\library\wechat\live\Room as LiveRoomApi;
|
||||
|
||||
/**
|
||||
* 微信小程序直播间模型
|
||||
* Class LiveRoom
|
||||
* @package app\store\model\wxapp
|
||||
*/
|
||||
class LiveRoom extends LiveRoomModel
|
||||
{
|
||||
/**
|
||||
* 获取直播间列表
|
||||
* @param string $search 检索词
|
||||
* @return \think\Paginator
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function getList($search = '')
|
||||
{
|
||||
!empty($search) && $this->where('room_name|anchor_name', 'like', "%{$search}%");
|
||||
return $this->where('is_delete', '=', 0)
|
||||
->order([
|
||||
'is_top' => 'desc',
|
||||
'live_status' => 'asc',
|
||||
'create_time' => 'desc'
|
||||
])
|
||||
->paginate(15, false, [
|
||||
'query' => \request()->request()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置直播间置顶状态
|
||||
* @param $isTop
|
||||
* @return false|int
|
||||
*/
|
||||
public function setIsTop($isTop)
|
||||
{
|
||||
return $this->save(['is_top' => (int)$isTop]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新直播间列表(同步微信api)
|
||||
* 每次拉取上限100条数据
|
||||
* @throws BaseException
|
||||
* @throws \think\exception\DbException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function refreshLiveList()
|
||||
{
|
||||
// 获取微信api最新直播间列表信息
|
||||
$originRoomList = $this->getOriginRoomList();
|
||||
// 获取微信直播间的房间id集
|
||||
$originRoomIds = $this->getOriginRoomIds($originRoomList);
|
||||
// 已存储的所有房间id集
|
||||
$localRoomIds = $this->getLocalRoomIds();
|
||||
// 同步新增直播间
|
||||
$this->refreshLiveNew($localRoomIds, $originRoomIds, $originRoomList);
|
||||
// 同步删除直播间
|
||||
$this->refreshLiveRemove($localRoomIds, $originRoomIds);
|
||||
// 同步更新直播间
|
||||
$this->refreshLiveUpdate($localRoomIds, $originRoomIds, $originRoomList);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信api最新直播间列表信息
|
||||
* @return array
|
||||
* @throws BaseException
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
private function getOriginRoomList()
|
||||
{
|
||||
// 小程序配置信息
|
||||
$wxConfig = WxappModel::getWxappCache();
|
||||
// 请求api数据
|
||||
$LiveRoomApi = new LiveRoomApi($wxConfig['app_id'], $wxConfig['app_secret']);
|
||||
$response = $LiveRoomApi->getLiveRoomList();
|
||||
if ($response === false) {
|
||||
throw new BaseException(['msg' => '直播房间列表api请求失败:' . $LiveRoomApi->getError()]);
|
||||
}
|
||||
// 格式化返回的列表数据
|
||||
$originRoomList = [];
|
||||
foreach ($response['room_info'] as $item) {
|
||||
$originRoomList[$item['roomid']] = $item;
|
||||
}
|
||||
return $originRoomList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信直播间的房间id集
|
||||
* @param $originRoomList
|
||||
* @return array
|
||||
*/
|
||||
private function getOriginRoomIds($originRoomList)
|
||||
{
|
||||
$originRoomIds = [];
|
||||
foreach ($originRoomList as $item) {
|
||||
$originRoomIds[] = $item['roomid'];
|
||||
}
|
||||
return $originRoomIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库中已存在的roomid
|
||||
* @return array
|
||||
*/
|
||||
private function getLocalRoomIds()
|
||||
{
|
||||
return $this->where('is_delete', '=', 0)->column('room_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步新增直播间
|
||||
* @param array $localRoomIds 本地直播间id集
|
||||
* @param array $originRoomIds 最新直播间id集
|
||||
* @param array $originRoomList 最新直播间列表
|
||||
* @return array|bool|false
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function refreshLiveNew($localRoomIds, $originRoomIds, $originRoomList)
|
||||
{
|
||||
// 需要新增的直播间ID
|
||||
$newLiveRoomIds = array_values(array_diff($originRoomIds, $localRoomIds));
|
||||
if (empty($newLiveRoomIds)) return true;
|
||||
// 整理新增数据
|
||||
$saveData = [];
|
||||
foreach ($newLiveRoomIds as $roomId) {
|
||||
$item = $originRoomList[$roomId];
|
||||
$saveData[] = [
|
||||
'room_id' => $roomId,
|
||||
'room_name' => $item['name'],
|
||||
'cover_img' => $item['cover_img'],
|
||||
'share_img' => $item['share_img'],
|
||||
'anchor_name' => $item['anchor_name'],
|
||||
'start_time' => $item['start_time'],
|
||||
'end_time' => $item['end_time'],
|
||||
'live_status' => $item['live_status'],
|
||||
'wxapp_id' => self::$wxapp_id,
|
||||
];
|
||||
}
|
||||
// 批量新增直播间
|
||||
return $this->isUpdate(false)->saveAll($saveData, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步更新直播间
|
||||
* @param array $localRoomIds 本地直播间id集
|
||||
* @param array $originRoomIds 最新直播间id集
|
||||
* @param array $originRoomList 最新直播间列表
|
||||
* @return array|bool|false
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function refreshLiveUpdate($localRoomIds, $originRoomIds, $originRoomList)
|
||||
{
|
||||
// 需要新增的直播间ID
|
||||
$updatedLiveRoomIds = array_values(array_intersect($originRoomIds, $localRoomIds));
|
||||
if (empty($updatedLiveRoomIds)) return true;
|
||||
// 整理新增数据
|
||||
$saveData = [];
|
||||
foreach ($updatedLiveRoomIds as $roomId) {
|
||||
$item = $originRoomList[$roomId];
|
||||
$saveData[] = [
|
||||
'room_id' => $roomId,
|
||||
'room_name' => $item['name'],
|
||||
'cover_img' => $item['cover_img'],
|
||||
'share_img' => $item['share_img'],
|
||||
'anchor_name' => $item['anchor_name'],
|
||||
'start_time' => $item['start_time'],
|
||||
'end_time' => $item['end_time'],
|
||||
'live_status' => $item['live_status'],
|
||||
'wxapp_id' => self::$wxapp_id,
|
||||
];
|
||||
}
|
||||
// 批量新增直播间
|
||||
return $this->isUpdate(true)->saveAll($saveData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步删除直播间
|
||||
* @param array $localRoomIds 本地直播间id集
|
||||
* @param array $originRoomIds 最新直播间id集
|
||||
* @return array|bool|false
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function refreshLiveRemove($localRoomIds, $originRoomIds)
|
||||
{
|
||||
// 需要新增的直播间ID
|
||||
$removedLiveRoomIds = array_values(array_diff($localRoomIds, $originRoomIds));
|
||||
if (empty($removedLiveRoomIds)) return true;
|
||||
// 批量删除直播间
|
||||
return self::destroy($removedLiveRoomIds);
|
||||
}
|
||||
|
||||
}
|
151
source/application/store/view/apps/live/room/index.php
Normal file
151
source/application/store/view/apps/live/room/index.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
use app\common\enum\live\LiveStatus as LiveStatusEnum;
|
||||
|
||||
?>
|
||||
<div class="row-content am-cf">
|
||||
<div class="row">
|
||||
<div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
|
||||
<div class="widget am-cf">
|
||||
<div class="widget-head am-cf">
|
||||
<div class="widget-title am-cf"> 小程序直播间列表</div>
|
||||
</div>
|
||||
<div class="widget-body am-fr">
|
||||
<div class="tips am-margin-bottom am-u-sm-12">
|
||||
<div class="pre">
|
||||
<p class="am-padding-bottom-xs"> 小程序直播操作说明:</p>
|
||||
<p>1. 登录 <a href="https://mp.weixin.qq.com/" target="_blank">微信小程序运营平台</a>,点击左侧菜单栏 “直播”,点击
|
||||
“创建直播间” 按钮。</p>
|
||||
<p>2. 点击本页面中的 "同步直播间" 按钮,将直播间列表导入商城系统中。</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 工具栏 -->
|
||||
<div class="page_toolbar am-margin-bottom am-cf">
|
||||
<form class="toolbar-form" action="">
|
||||
<input type="hidden" name="s" value="/<?= $request->pathinfo() ?>">
|
||||
<div class="am-u-sm-12 am-u-md-3">
|
||||
<div class="am-form-group">
|
||||
<div class="am-btn-toolbar">
|
||||
<?php if (checkPrivilege('apps.live.room/refresh')): ?>
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
<a class="j-refresh am-btn am-btn-default am-btn-success am-radius"
|
||||
href="javascript:void(0);">
|
||||
<span class="am-icon-refresh"></span> 同步直播间
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="am-u-sm-12 am-u-md-9">
|
||||
<div class="am fr">
|
||||
<div class="am-form-group am-fl">
|
||||
<div class="am-input-group am-input-group-sm tpl-form-border-form">
|
||||
<input type="text" class="am-form-field" name="search"
|
||||
placeholder="请输入直播间名称/主播昵称"
|
||||
value="<?= $request->get('search') ?>">
|
||||
<div class="am-input-group-btn">
|
||||
<button class="am-btn am-btn-default am-icon-search"
|
||||
type="submit"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="am-scrollable-horizontal am-u-sm-12">
|
||||
<table width="100%" class="am-table am-table-compact am-table-striped
|
||||
tpl-table-black am-text-nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>直播间ID</th>
|
||||
<th>直播间名称</th>
|
||||
<th>主播昵称</th>
|
||||
<th>直播时间</th>
|
||||
<th>直播状态</th>
|
||||
<th>置顶</th>
|
||||
<th>更新时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!$list->isEmpty()): foreach ($list as $item): ?>
|
||||
<tr>
|
||||
<td class="am-text-middle"><?= $item['room_id'] ?></td>
|
||||
<td class="am-text-middle"><?= $item['room_name'] ?></td>
|
||||
<td class="am-text-middle"><?= $item['anchor_name'] ?></td>
|
||||
<td class="am-text-middle">
|
||||
<p class="">
|
||||
<span class="title">开始:</span>
|
||||
<span class="value"><?= $item['start_time'] ?></span>
|
||||
</p>
|
||||
<p class="">
|
||||
<span class="title">结束:</span>
|
||||
<span class="value"><?= $item['end_time'] ?></span>
|
||||
</p>
|
||||
</td>
|
||||
<td class="am-text-middle">
|
||||
<?= LiveStatusEnum::data()[$item['live_status']]['name'] ?>
|
||||
</td>
|
||||
<td class="am-text-middle">
|
||||
<span class="j-setTop x-cur-p am-badge am-badge-<?= $item['is_top'] ? 'success' : 'warning' ?>"
|
||||
data-id="<?= $item['room_id'] ?>" data-istop="<?= $item['is_top'] ?>">
|
||||
<?= $item['is_top'] ? '是' : '否' ?></span>
|
||||
</td>
|
||||
<td class="am-text-middle"><?= $item['update_time'] ?></td>
|
||||
</tr>
|
||||
<?php endforeach; else: ?>
|
||||
<tr>
|
||||
<td colspan="7" class="am-text-center">暂无记录</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="am-u-lg-12 am-cf">
|
||||
<div class="am-fr"><?= $list->render() ?> </div>
|
||||
<div class="am-fr pagination-total am-margin-right">
|
||||
<div class="am-vertical-align-middle">总记录:<?= $list->total() ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
|
||||
/**
|
||||
* 同步直播间
|
||||
*/
|
||||
$('.j-refresh').on('click', function () {
|
||||
var url = "<?= url('apps.live.room/refresh') ?>";
|
||||
var load = layer.load();
|
||||
$.post(url, {}, function (result) {
|
||||
result.code === 1 ? $.show_success(result.msg, result.url)
|
||||
: $.show_error(result.msg);
|
||||
layer.close(load);
|
||||
});
|
||||
});
|
||||
|
||||
// 商品状态
|
||||
$('.j-setTop').click(function () {
|
||||
var data = $(this).data();
|
||||
layer.confirm('确定要' + (parseInt(data['istop']) === 1 ? '取消' : '') + '置顶该房间吗?'
|
||||
, {title: '友情提示'}
|
||||
, function (index) {
|
||||
var url = "<?= url('apps.live.room/settop') ?>";
|
||||
$.post(url
|
||||
, {room_id: data['id'], is_top: Number(!(parseInt(data['istop']) === 1))}
|
||||
, function (result) {
|
||||
result['code'] === 1 ? $.show_success(result['msg'], result['url'])
|
||||
: $.show_error(result['msg']);
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
@ -178,7 +178,6 @@
|
||||
});
|
||||
layer.close(index);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// 删除元素
|
||||
|
@ -419,6 +419,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="link-item">
|
||||
<div class="row page-name">小程序直播列表页</div>
|
||||
<div class="row am-cf">
|
||||
<div class="am-fl">地址:</div>
|
||||
<div class="am-fl">
|
||||
<span class="x-color-green">pages/live/index</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "1.1.39"
|
||||
"version": "1.1.40"
|
||||
}
|
||||
|
36
安装说明..md
36
安装说明..md
@ -110,6 +110,42 @@ http://www.你的域名.com/index.php?s=/admin
|
||||
##### 二、小程序首页设计
|
||||
|
||||
可在该页面修改小程序端的页面元素、顶部导航栏和标题等信息,可自定义DIY排版。
|
||||
# 微信小程序直播
|
||||
> 受疫情影响,商家纷纷转型线上,直播也成为了链接“暂停营业”商家与“闭门在家”消费者的重要销售渠道!
|
||||
萤火小程序商城直播功能今日正式上线,商家可通过微信小程序直播实现用户互动与商品销售的闭环,达成私域流量的激活与转化。
|
||||
微信小程序直播插件免费使用,商业用户可升级到v1.1.40版本免费领取该插件。
|
||||
|
||||
### 一、如何开通小程序直播?
|
||||
登录 “[微信小程序运营平台](https://mp.weixin.qq.com/ "微信小程序运营平台")”,点击左侧菜单栏 “直播”,符合微信准入要求可直接开通
|
||||
|
||||
点击此处查看[《微信小程序直播功能准入要求》](https://res.wx.qq.com/mmbizwxampnodelogicsvr_node/dist/images/access_02b58d.pdf "《微信小程序直播功能准入要求》")
|
||||
|
||||
### 二、如何在小程序商城中使用直播功能
|
||||
|
||||
##### 1.首先将萤火小程序商城系统升级到v1.1.40及以上版本
|
||||
|
||||
打开小程序端项目 **app.json** 文件,添加如下插件代码
|
||||
|
||||
**注意**:如果没有开通直播权限,添加该插件代码会报错。小程序端添加完成后,需提交代码发布上线
|
||||
|
||||
```json
|
||||
"plugins": {
|
||||
"live-player-plugin": {
|
||||
"version": "1.0.3",
|
||||
"provider": "wx2b03c6e691cd7370"
|
||||
}
|
||||
},
|
||||
```
|
||||
##### 2.在 “[微信小程序运营平台](https://mp.weixin.qq.com/ "微信小程序运营平台")” 中创建直播间
|
||||
|
||||
##### 3.打开萤火小程序商城商户后台
|
||||
|
||||
找到 [应用管理] - [小程序直播] - [直播间管理],点击 “同步直播间”按钮,将直播间列表导入商城系统中。
|
||||
|
||||
##### 4.将小程序直播页面路径,添加到首页入口
|
||||
|
||||
直播页路径:`pages/live/index`
|
||||
|
||||
|
||||
# 常见问题
|
||||
|
||||
|
Reference in New Issue
Block a user