From 1914cc99581b3aa3eb3e87410df188e3c74c615c Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Thu, 15 Jan 2026 15:21:46 +0800 Subject: [PATCH] =?UTF-8?q?Merge:=20=E5=90=88=E5=B9=B6=E7=94=B5=E5=AD=90?= =?UTF-8?q?=E5=90=8D=E7=89=87=E5=8F=8A=E6=96=B0=E7=BB=84=E4=BB=B6=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E8=A7=86=E9=A2=91=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/diy/RADEME.md | 42 ++++++- src/addon/personnel/config/diy_view.php | 86 ++++++++------ src/addon/personnel/config/info.php | 31 +++-- src/addon/personnel/config/menu_shop.php | 39 +++++- src/addon/personnel/data/install.sql | 37 +++++- src/addon/personnel/data/uninstall.sql | 6 + src/addon/personnel/event/Install.php | 40 ++++--- src/addon/personnel/event/UnInstall.php | 49 ++++---- src/addon/personnel/model/Enterprise.php | 103 ++++++++++++++++ src/addon/personnel/model/Personnel.php | 50 ++++---- .../personnel/shop/controller/Enterprise.php | 112 +++++++++++++++++- .../personnel/shop/view/personnel/diy.html | 89 +++++++++++++- src/addon/personnel/shop/view/public/diy.css | 32 +++++ src/addon/personnel/shop/view/public/diy.js | 107 +++++++++++++---- .../shop/view/public/img/mingpian.png | Bin 14387 -> 9574 bytes upgrade.sql | 46 ++++++- 16 files changed, 732 insertions(+), 137 deletions(-) diff --git a/docs/diy/RADEME.md b/docs/diy/RADEME.md index c9a6a0b2a..a1134b8a2 100644 --- a/docs/diy/RADEME.md +++ b/docs/diy/RADEME.md @@ -24,4 +24,44 @@ create table if not exists lucky_diy_view_util constraint name unique (name) ) -``` \ No newline at end of file +``` + +## 页面设计及组件展示 + +- src\app\model\web\DiyView.php +- src\app\shop\view\diy\edit.html +- src\public\static\ext\diyview\js\components.js + +## 如何添加新组件 + + +### 1. 添加组件到数据表中 + +```sql +insert into lucky_diy_view_util (name, title, type, value, addon_name, sort, support_diy_view, max_count, is_delete, icon, icon_type) +values ('test', '测试', 'SYSTEM', '{"test": "test"}', '', 0, '', 0, 0, '', 0); + +--- 微信视频号组件 +-- 仅当WechatChannel不存在时添加记录 +INSERT INTO lucky_diy_view_util (`name`, `title`, `type`, `value`, `addon_name`, `sort`, `support_diy_view`, `max_count`, `is_delete`, `icon`, `icon_type`) +SELECT 'WechatChannel', '微信视频号', 'SYSTEM', '{ "list": [{ "channelName":"", "finderUserName": "", "avatarImageType": "url", "avatarUrl": "", "videoTitle": "", "coverImageType": "url", "coverUrl": "", "feedId": "", "feedToken": "", "viewCount": 0, "showViewCount": true, "embedMode": false, "channelType":"wechat" }], "rowCount": 2, "showStyle": "fixed", "aspectRatio":"16:9", "titleLineClamp": 1, "showPlayBtn": true}', '', 100110, '', 0, 0, '/public/static/img/svg/xuanxiangka.svg', 0 +WHERE NOT EXISTS ( + SELECT 1 FROM lucky_diy_view_util WHERE name = 'WechatChannel' +); + +``` + + +### 2. 建立组件的控制器 +在 `src\app\component\controller` 目录下创建对应的控制器文件,处理组件的业务逻辑。 + +例如:创建 `src\app\component\controller\TestController.php` 文件,用于处理测试组件的业务逻辑。 + +### 3. 建立组件的视图 +在 src\app\component\view 目录下创建对应的视图文件,处理组件的前端展示。 + +例如:创建 `src\app\component\view\test.php` 文件,用于展示测试组件。 + + +### 4. 在前端页面中使用组件 +在前端页面中使用组件,需要在页面中添加对应的组件标签。 \ No newline at end of file diff --git a/src/addon/personnel/config/diy_view.php b/src/addon/personnel/config/diy_view.php index 0fe9cf839..1872e00c4 100644 --- a/src/addon/personnel/config/diy_view.php +++ b/src/addon/personnel/config/diy_view.php @@ -1,40 +1,48 @@ - '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据,json格式' ] - 'template' => [], - - // 后台自定义组件——装修 - 'util' => [], - - // 自定义页面路径 - 'link' => [ - [ - 'name' => 'MINGPIAN_INFO', - 'title' => '电子名片', - 'parent' => 'BASICS_LINK', - 'wap_url' => '/pages/contact/contact', - 'web_url' => '', - 'sort' => 0 - ] - ], - - // 自定义图标库 - 'icon_library' => [], - - // uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ],多个逗号隔开,自定义组件名称前缀必须是diy-,也可以引用第三方组件 - 'component' => [], - - // uni-app 页面,多个逗号隔开 - 'pages' => [], - - // 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述' - 'info' => [], - - // 主题风格配色,格式可以自由定义扩展,【在uni-app中通过:this.themeStyle... 获取定义的颜色字段,例如:this.themeStyle.main_color】 - 'theme' => [], - - // 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据,json格式] ] - 'data' => [] + '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据,json格式' ] + 'template' => [], + + // 后台自定义组件——装修 + 'util' => [], + + // 自定义页面路径 + 'link' => [ + [ + 'name' => 'MINGPIAN_INFO', + 'title' => '电子名片', + 'parent' => 'BASICS_LINK', + 'wap_url' => '/pages/contact/contact', + 'web_url' => '', + 'sort' => 0 + ] + ], + + // 自定义图标库 + 'icon_library' => [], + + // uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ],多个逗号隔开,自定义组件名称前缀必须是diy-,也可以引用第三方组件 + 'component' => [], + + // uni-app 页面,多个逗号隔开 + 'pages' => [], + + // 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述' + 'info' => [], + + // 主题风格配色,格式可以自由定义扩展,【在uni-app中通过:this.themeStyle... 获取定义的颜色字段,例如:this.themeStyle.main_color】 + 'theme' => [], + + // 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据,json格式] ] + 'data' => [] ]; \ No newline at end of file diff --git a/src/addon/personnel/config/info.php b/src/addon/personnel/config/info.php index b15cf8082..73bae96f3 100644 --- a/src/addon/personnel/config/info.php +++ b/src/addon/personnel/config/info.php @@ -1,12 +1,21 @@ - 'personnel', - 'title' => '电子名片', - 'description' => '展示公司人员名片信息', - 'type' => 'tool', //插件类型 system :系统插件(自动安装), promotion:扩展营销插件 tool:工具插件 - 'status' => 1, - 'author' => '', - 'version' => '5.3.1', - 'version_no' => '525231212001', - 'content' => '', + 'personnel', + 'title' => '电子名片', + 'description' => '展示公司人员名片信息', + 'type' => 'tool', //插件类型 system :系统插件(自动安装), promotion:扩展营销插件 tool:工具插件 + 'status' => 1, + 'author' => '', + 'version' => '5.3.1', + 'version_no' => '525231212001', + 'content' => '', ]; \ No newline at end of file diff --git a/src/addon/personnel/config/menu_shop.php b/src/addon/personnel/config/menu_shop.php index 1decf3c0e..5159956b0 100644 --- a/src/addon/personnel/config/menu_shop.php +++ b/src/addon/personnel/config/menu_shop.php @@ -112,13 +112,46 @@ return [ ], ] ], + [ + 'name' => 'PERSONNEL_CHANNEL_LIST', + 'title' => '视频号', + 'url' => 'personnel://shop/enterprise/channellists', + 'is_show' => 1, + 'sort' => 4, + 'child_list' => [ + [ + 'name' => 'PERSONNEL_CHANNEL_ADD', + 'title' => '添加视频号', + 'url' => 'personnel://shop/enterprise/channeladd', + 'sort' => 1, + 'is_show' => 0, + 'is_control' => 1, + ], + [ + 'name' => 'PERSONNEL_CHANNEL_EDIT', + 'title' => '编辑视频号', + 'url' => 'personnel://shop/enterprise/channeledit', + 'sort' => 1, + 'is_show' => 0, + 'is_control' => 1, + ], + [ + 'name' => 'PERSONNEL_CHANNEL_DELETE', + 'title' => '删除视频号', + 'url' => 'personnel://shop/enterprise/channeldelete', + 'sort' => 2, + 'is_show' => 0, + 'is_control' => 1, + ], + ] + ], [ 'name' => 'MESSAGE_ROOT', 'title' => '留言列表', 'url' => 'personnel://shop/personnel/message', 'is_show' => 1, - 'sort' => 4, + 'sort' => 5, 'child_list' => [ ], @@ -128,7 +161,7 @@ return [ 'title' => '电子名片', 'url' => 'personnel://shop/personnel/diy', 'is_show' => 1, - 'sort' => 5, + 'sort' => 6, 'child_list' => [ ], @@ -138,7 +171,7 @@ return [ 'title' => '设置', 'url' => 'personnel://shop/personnel/set', 'is_show' => 1, - 'sort' => 6, + 'sort' => 7, 'child_list' => [ ], diff --git a/src/addon/personnel/data/install.sql b/src/addon/personnel/data/install.sql index 22c382dd4..30637d6de 100644 --- a/src/addon/personnel/data/install.sql +++ b/src/addon/personnel/data/install.sql @@ -1 +1,36 @@ -SET NAMES 'utf8'; \ No newline at end of file +SET NAMES 'utf8'; + +-- 创建视频号表 +CREATE TABLE IF NOT EXISTS `lucky_personnel_channel` +( + `channel_id` int unsigned NOT NULL AUTO_INCREMENT, + `site_id` int unsigned NOT NULL DEFAULT 0 COMMENT '站点ID', + `create_time` int unsigned NOT NULL DEFAULT 0 COMMENT '创建时间', + `channel_type` varchar(30) NOT NULL DEFAULT 'wechat' COMMENT '视频号类型:wechat-微信视频号,douyin-抖音,kuaishou-快手,redbook-小红书,bilibili-B站', + `channel_name` varchar(200) NOT NULL DEFAULT '' COMMENT '视频号ID', + `feed_id` varchar(500) NOT NULL DEFAULT '' COMMENT '视频号内容ID', + `feed_token` varchar(255) NOT NULL DEFAULT '' COMMENT '视频号视频的标识', + `avatar_image_type` varchar(20) NOT NULL DEFAULT 'upload' COMMENT '头像类型:upload-上传图片,url-URL', + `avatar_url` varchar(500) NOT NULL DEFAULT '' COMMENT '头像URL', + `video_title` varchar(500) NOT NULL DEFAULT '' COMMENT '视频标题', + `cover_image_type` varchar(20) NOT NULL DEFAULT 'upload' COMMENT '封面类型:upload-上传图片,url-URL', + `cover_url` varchar(500) NOT NULL DEFAULT '' COMMENT '封面URL', + `view_count` int unsigned NOT NULL DEFAULT 0 COMMENT '视频观看次数', + `show_view_count` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否显示视频观看次数:0-不显示,1-显示', + `show_follow` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否显示关注按钮:0-不显示,1-显示', + `is_show` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否显示:0-隐藏,1-显示', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序,数值越小越靠前', + PRIMARY KEY (`channel_id`), + KEY `idx_site_id` (`site_id`), + KEY `idx_channel_type` (`channel_type`), + KEY `idx_is_show` (`is_show`), + KEY `idx_sort` (`sort`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='电子名片视频号资源表'; + +-- 插入视频号菜单权限(使用 IGNORE 避免重复插入报错) +INSERT IGNORE INTO `lucky_menu` (`app_module`, `addon`, `title`, `name`, `parent`, `level`, `url`, `is_show`, `sort`, `desc`, `is_icon`, `picture`, `picture_select`, `is_control`) +VALUES +('shop', 'personnel', '视频号', 'PERSONNEL_CHANNEL_LIST', 'PERSONNEL_ROOT', 4, 'personnel://shop/enterprise/channellists', 1, 4, '', 0, '', '', 1), +('shop', 'personnel', '添加视频号', 'PERSONNEL_CHANNEL_ADD', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeladd', 0, 1, '', 0, '', '', 1), +('shop', 'personnel', '编辑视频号', 'PERSONNEL_CHANNEL_EDIT', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeledit', 0, 1, '', 0, '', '', 1), +('shop', 'personnel', '删除视频号', 'PERSONNEL_CHANNEL_DELETE', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeldelete', 0, 2, '', 0, '', '', 1); \ No newline at end of file diff --git a/src/addon/personnel/data/uninstall.sql b/src/addon/personnel/data/uninstall.sql index 0b4cf1b2f..c14f8bb57 100644 --- a/src/addon/personnel/data/uninstall.sql +++ b/src/addon/personnel/data/uninstall.sql @@ -1 +1,7 @@ SET NAMES 'utf8'; + +-- 删除视频号菜单权限 +DELETE FROM `lucky_menu` WHERE `name` IN ('PERSONNEL_CHANNEL_LIST', 'PERSONNEL_CHANNEL_ADD', 'PERSONNEL_CHANNEL_EDIT', 'PERSONNEL_CHANNEL_DELETE'); + +-- 删除视频号表 +DROP TABLE IF EXISTS `lucky_personnel_channel`; \ No newline at end of file diff --git a/src/addon/personnel/event/Install.php b/src/addon/personnel/event/Install.php index 1c9bfebe5..3a95457d9 100644 --- a/src/addon/personnel/event/Install.php +++ b/src/addon/personnel/event/Install.php @@ -1,17 +1,25 @@ -getMessage()); - } - } +getMessage()); + } + } } \ No newline at end of file diff --git a/src/addon/personnel/model/Enterprise.php b/src/addon/personnel/model/Enterprise.php index 3c877a5d5..70fd166c7 100644 --- a/src/addon/personnel/model/Enterprise.php +++ b/src/addon/personnel/model/Enterprise.php @@ -264,4 +264,107 @@ class Enterprise extends BaseModel return $this->success($res); } + //视频号 + /** + * 获取视频号分页列表 + * @param array $condition + * @param number $page + * @param string $page_size + * @param string $order + * @param string $field + */ + public function getChannelPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'create_time desc', $field = '*') + { + $check_condition = array_column($condition, 2, 0); + $site_id = $check_condition['site_id'] ?? ''; + if ($site_id === '') { + return $this->error('', 'REQUEST_SITE_ID'); + } + + $list = model('personnel_channel')->pageList($condition, $field, $order, $page, $page_size); + return $this->success($list); + } + + /** + * 获取视频号列表 + * @param array $condition + * @param string $field + * @param string $order + * @param string $limit + */ + public function getChannelList($condition = [], $field = '*', $order = '', $limit = null) + { + $list = model('personnel_channel')->getList($condition, $field, $order, '', '', '', $limit); + return $this->success($list); + } + + /** + * 添加视频号 + * @param array $data + */ + public function addChannel($data) + { + $site_id = $data['site_id'] ?? ''; + if ($site_id === '') { + return $this->error('', 'REQUEST_SITE_ID'); + } + + $data['create_time'] = time(); + // 默认视频号类型为微信 + if (!isset($data['channel_type']) || empty($data['channel_type'])) { + $data['channel_type'] = 'wechat'; + } + $channel_id = model('personnel_channel')->add($data); + return $this->success($channel_id); + } + + /** + * 获取视频号信息 + * @param array $condition + * @param string $field + */ + public function getChannelInfo($condition = [], $field = '*') + { + $list = model('personnel_channel')->getInfo($condition, $field); + return $this->success($list); + } + + /** + * 修改视频号 + * @param array $data + */ + public function editChannel($data) + { + $site_id = $data['site_id'] ?? ''; + if ($site_id === '') { + return $this->error('', 'REQUEST_SITE_ID'); + } + + model('personnel_channel')->startTrans(); + try { + model('personnel_channel')->update($data, [ [ 'site_id', '=', $data[ 'site_id' ] ], [ 'channel_id', '=', $data[ 'channel_id' ] ] ]); + model('personnel_channel')->commit(); + return $this->success(); + } catch (\Exception $e) { + model('personnel_channel')->rollback(); + return $this->error('', $e->getMessage()); + } + } + + /** + * 删除视频号 + * @param array $condition + */ + public function deleteChannel($condition) + { + $check_condition = array_column($condition, 2, 0); + $site_id = $check_condition['site_id'] ?? ''; + if ($site_id === '') { + return $this->error('', 'REQUEST_SITE_ID'); + } + + $res = model('personnel_channel')->delete($condition); + return $this->success($res); + } + } \ No newline at end of file diff --git a/src/addon/personnel/model/Personnel.php b/src/addon/personnel/model/Personnel.php index bb353680c..41cb97840 100644 --- a/src/addon/personnel/model/Personnel.php +++ b/src/addon/personnel/model/Personnel.php @@ -9,8 +9,8 @@ class Personnel extends BaseModel { - - /** + + /** * 获取名片设置 * @param $site_id * @param $app_module @@ -18,16 +18,20 @@ class Personnel extends BaseModel */ public function getPersonnelSet($site_id, $app_module) { + $DEFAULT_CONFIG_VALUE = '{"is_kefu":1,"is_mp":1,"is_file":1,"is_channel":1,"is_video":1,"is_map":1}'; $config = new ConfigModel(); - $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'DIY_PERSONNEL' ] ]); - if (empty($res[ 'data' ][ 'value' ])){ - $res[ 'data' ][ 'value' ] = [ + $res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'DIY_PERSONNEL']]); + if (empty($res['data']['value'])) { + $res['data']['value'] = [ 'personnel_bg' => '', - 'value'=>'{"is_kefu":1,"is_mp":1,"is_file":1,"is_video":1,"is_map":1}' + 'value' => $DEFAULT_CONFIG_VALUE ]; - }else{ - if(!isset($res['data']['value']['value'])) $res['data']['value']['value'] = '{"is_kefu":1,"is_mp":1,"is_file":1,"is_video":1,"is_map":1}'; + } else { + if (!isset($res['data']['value']['value'])) + $res['data']['value']['value'] = $DEFAULT_CONFIG_VALUE; } + + //public/static/img/diy_view/member_info_bg.png return $res; } @@ -42,7 +46,7 @@ class Personnel extends BaseModel public function setPersonnelSet($data, $site_id, $app_module) { $config = new ConfigModel(); - $res = $config->setConfig($data, '名片设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'DIY_PERSONNEL' ] ]); + $res = $config->setConfig($data, '名片设置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'DIY_PERSONNEL']]); return $res; } @@ -63,9 +67,9 @@ class Personnel extends BaseModel public function getMessagePageList($condition = [], $field = true, $order = '', $page = 1, $list_rows = PAGE_LIST_ROWS, $alias = 'a', $join = []) { $data = model('personnel_message')->pageList($condition, $field, $order, $page, $list_rows, $alias, $join); - if (!empty($data[ 'list' ])) { - foreach ($data[ 'list' ] as $k => $item) { - $data[ 'list' ][ $k ][ 'createtime' ] = date('Y-m-d H:i:s',$item['createtime']); + if (!empty($data['list'])) { + foreach ($data['list'] as $k => $item) { + $data['list'][$k]['createtime'] = date('Y-m-d H:i:s', $item['createtime']); } } return $this->success($data); @@ -87,9 +91,9 @@ class Personnel extends BaseModel * 编辑人员 * @param $param */ - public function editPersonnel($condition,$data) + public function editPersonnel($condition, $data) { - $result = model('personnel')->update($condition,$data); + $result = model('personnel')->update($condition, $data); return $this->success($result); } @@ -100,13 +104,14 @@ class Personnel extends BaseModel */ public function deletePersonnel($id, $site_id) { - $info = model('personnel')->getInfo([ [ 'site_id', '=', $site_id ], [ 'id', '=', $id ] ], 'id'); - if (empty($info)) return $this->error('', '未获取到人员信息'); - $res = model('personnel')->delete([ [ 'site_id', '=', $site_id ], [ 'id', '=', $id ] ]); + $info = model('personnel')->getInfo([['site_id', '=', $site_id], ['id', '=', $id]], 'id'); + if (empty($info)) + return $this->error('', '未获取到人员信息'); + $res = model('personnel')->delete([['site_id', '=', $site_id], ['id', '=', $id]]); return $this->success($res); } - /** + /** * 获取电子名片人员列表 * @param array $condition * @param bool $field @@ -123,16 +128,17 @@ class Personnel extends BaseModel return $this->success($data); } - /** + /** * 删除留言 * @param $id * @param $site_id */ public function deleteMessage($id, $site_id) { - $info = model('personnel_message')->getInfo([ [ 'site_id', '=', $site_id ], [ 'id', '=', $id ] ], 'id'); - if (empty($info)) return $this->error('', '未获取到留言信息'); - $res = model('personnel_message')->delete([ [ 'site_id', '=', $site_id ], [ 'id', '=', $id ] ]); + $info = model('personnel_message')->getInfo([['site_id', '=', $site_id], ['id', '=', $id]], 'id'); + if (empty($info)) + return $this->error('', '未获取到留言信息'); + $res = model('personnel_message')->delete([['site_id', '=', $site_id], ['id', '=', $id]]); return $this->success($res); } } \ No newline at end of file diff --git a/src/addon/personnel/shop/controller/Enterprise.php b/src/addon/personnel/shop/controller/Enterprise.php index fb0a35253..05892feec 100644 --- a/src/addon/personnel/shop/controller/Enterprise.php +++ b/src/addon/personnel/shop/controller/Enterprise.php @@ -168,7 +168,117 @@ class Enterprise extends BaseShop if (request()->isJson()) { $video_id = input('video_id', 0); $model = new EnterpriseModel(); - return $model->deleteVideo([ [ 'video_id', '=', $video_id],['site_id','=',$this->site_id] ]); + return $model->deleteVideo([ [ 'video_id', '=', $video_id ], [ 'site_id', '=', $this->site_id ] ]); + } + } + + /***************************************视频号部分****************************************/ + /** + * 视频号列表 + */ + public function channellists(){ + if (request()->isJson()) { + $page = input('page', 1); + $page_size = input('page_size', PAGE_LIST_ROWS); + $search_text = input('search_text', ''); + $channel_type = input('channel_type', ''); + $is_show = input('is_show', ''); + $order = input('order', ''); + $condition = [ [ 'site_id', '=', $this->site_id ] ]; + if ($search_text) { + $condition[] = [ 'channel_name', 'like', '%' . $search_text . '%' ]; + } + if ($channel_type) { + $condition[] = [ 'channel_type', '=', $channel_type ]; + } + if ($is_show !== '') { + $condition[] = [ 'is_show', '=', $is_show ]; + } + $order_by = $order ? $order : 'create_time desc'; + $model = new EnterpriseModel(); + $list = $model->getChannelPageList($condition, $page, $page_size, $order_by); + return $list; + } else { + return $this->fetch('enterprise/channel/lists'); + } + } + + /** + * 添加视频号 + */ + public function channeladd() + { + $model = new EnterpriseModel(); + if (request()->isJson()) { + $data = [ + 'site_id' => $this->site_id, + 'channel_type' => input('channel_type', 'wechat'), + 'channel_name' => input('channel_name', ''), + 'avatar_image_type' => input('avatar_image_type', 'upload'), + 'avatar_url' => input('avatar_url', ''), + 'video_title' => input('video_title', ''), + 'feed_id' => input('feed_id', ''), + 'cover_image_type' => input('cover_image_type', 'upload'), + 'cover_url' => input('cover_url', ''), + 'sort' => input('sort', 0), + 'is_show' => input('is_show', 1), + 'feed_token' => input('feed_token', ''), + 'view_count' => input('view_count', 0), + 'show_view_count' => input('show_view_count', 0), + 'show_follow' => input('show_follow', 0), + 'create_time' => time() + ]; + return $model->addChannel($data); + } else { + return $this->fetch('enterprise/channel/edit'); + } + } + + /** + * 编辑视频号 + */ + public function channeledit() + { + $channel_id = input('channel_id', 0); + $model = new EnterpriseModel(); + if (request()->isJson()) { + $data = [ + 'channel_id' => $channel_id, + 'site_id' => $this->site_id, + 'channel_type' => input('channel_type', 'wechat'), + 'channel_name' => input('channel_name', ''), + 'avatar_image_type' => input('avatar_image_type', 'upload'), + 'avatar_url' => input('avatar_url', ''), + 'video_title' => input('video_title', ''), + 'feed_id' => input('feed_id', ''), + 'cover_image_type' => input('cover_image_type', 'upload'), + 'cover_url' => input('cover_url', ''), + 'sort' => input('sort', 0), + 'is_show' => input('is_show', 1), + 'feed_token' => input('feed_token', ''), + 'view_count' => input('view_count', 0), + 'show_view_count' => input('show_view_count', 0), + 'show_follow' => input('show_follow', 0), + ]; + return $model->editChannel($data); + } else { + $this->assign('channel_id', $channel_id); + $article_info = $model->getChannelInfo([ [ 'channel_id', '=', $channel_id ] ]); + $this->assign('info', $article_info[ 'data' ]); + // 返回统一的 add.html 模板,前端会根据 channel_id 判断是否为编辑模式 + return $this->fetch('enterprise/channel/edit'); + } + } + + /** + * 删除视频号 + */ + public function channeldelete() + { + if (request()->isJson()) { + $channel_id = input('channel_id', 0); + $model = new EnterpriseModel(); + return $model->deleteChannel([ [ 'channel_id', '=', $channel_id ], [ 'site_id', '=', $this->site_id ] ]); } } } \ No newline at end of file diff --git a/src/addon/personnel/shop/view/personnel/diy.html b/src/addon/personnel/shop/view/personnel/diy.html index 463feeb7c..16aa948f1 100644 --- a/src/addon/personnel/shop/view/personnel/diy.html +++ b/src/addon/personnel/shop/view/personnel/diy.html @@ -13,7 +13,7 @@
-
+
+
+ 视频号 +
+
@@ -99,6 +103,89 @@
+
+ +
+ 隐藏显示 +
+ +
+
+
+
+ +
+
+
+
+ 视频号内容设置 + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ 隐藏显示 +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ 隐藏显示 +
+ +
+
+
+
+
+
+
+
diff --git a/src/addon/personnel/shop/view/public/diy.css b/src/addon/personnel/shop/view/public/diy.css index e69de29bb..a12e88f79 100644 --- a/src/addon/personnel/shop/view/public/diy.css +++ b/src/addon/personnel/shop/view/public/diy.css @@ -0,0 +1,32 @@ +.collapse-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 15px; + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 4px; + cursor: pointer; + margin-bottom: 10px; +} + +.collapse-header:hover { + background-color: #e9ecef; +} + +.collapse-title { + font-weight: 600; + color: #333; +} + +.collapse-content { + padding: 10px 15px; + border-radius: 4px; + background-color: #fff; + box-sizing: border-box; + border: 1px dashed #8a8a8a; +} + +.channel-settings .layui-form-item { + margin-bottom: 15px; +} diff --git a/src/addon/personnel/shop/view/public/diy.js b/src/addon/personnel/shop/view/public/diy.js index 645b1b94a..55cc08b6d 100644 --- a/src/addon/personnel/shop/view/public/diy.js +++ b/src/addon/personnel/shop/view/public/diy.js @@ -3,7 +3,7 @@ */ var vue = new Vue({ el: "#diyView", - data: { + data: () => ({ lazyLoad: false, global: { title: "电子名片", @@ -13,29 +13,44 @@ var vue = new Vue({ textNavColor: "#333333", textImgPosLink: 'center', }, - is_kefu:1, + is_kefu: 1, is_mp: 1, is_file: 1, is_video: 1, + is_channel: 1, is_map: 1, - }, + // 视频号设置 + channel_display_style: 'fixed', // 显示样式:carousel, fixed, singleSlide,默认fixed + channel_aspect_ratio: '16:9', // 显示比例:16:9 和 3:4,默认16:9 + channel_show_view_count: true, // 是否显示观看次数,默认显示 + channel_row_count: 2, // 每行显示数量:1,2,3,4,默认2 + channel_title_line_clamp: 2, // 标题最多行数:1,2,3,默认2 + channel_show_play_btn: true, // 是否显示播放按钮,默认显示 + channelCollapsed: false, // 视频号设置是否折叠,默认展开 + }), created: function () { if ($("#guessYouLikeConfig").val()) { $('#diyView').css('visibility', 'visible'); $('.preview-wrap .preview-restore-wrap').css('visibility', 'visible'); var self = this; - setTimeout(() => { - var data = JSON.parse($("#guessYouLikeConfig").val()); - console.log(this.data) - this.is_kefu = data.is_kefu - this.is_mp = data.is_mp - this.is_file = data.is_file - this.is_video = data.is_video - this.is_map = data.is_map - fullScreenSize(function () { - self.lazyLoad = true; - }); - }, 10); + + var data = JSON.parse($("#guessYouLikeConfig").val()); + this.is_kefu = data.is_kefu; + this.is_mp = data.is_mp; + this.is_file = data.is_file; + this.is_video = data.is_video; + this.is_map = data.is_map; + this.is_channel = data.is_channel; + // 视频号设置初始化 + this.channel_display_style = data.channel_display_style || 'fixed'; + this.channel_aspect_ratio = data.channel_aspect_ratio || '16:9'; + this.channel_show_view_count = !!data.channel_show_view_count; + this.channel_row_count = data.channel_row_count || 2; + this.channel_title_line_clamp = data.channel_title_line_clamp || 2; + this.channel_show_play_btn = !!data.channel_show_play_btn; + fullScreenSize(function () { + self.lazyLoad = true; + }); } else { $('#diyView').css('visibility', 'visible'); $('.preview-wrap .preview-restore-wrap').css('visibility', 'visible'); @@ -73,6 +88,47 @@ layui.use(['form'], function () { form.render(); fullScreenSize(); + + // 初始化layui的select元素的默认值和事件绑定 + const initLayuiSelectBindings = (() => { + // 特别注意:layui的select元素,不能使用v-model绑定数据, 只能使用layui的form.on('select')事件监听和form.val()方法设置默认值 + [`channel_display_style`, `channel_aspect_ratio`, `channel_row_count`, `channel_title_line_clamp`].forEach((key) => { + // 根据vue数据, 初始化layui的select元素的默认值 + if (vue.hasOwnProperty(key)) { + // form.val 必须指定form的lay-filter属性值,才能设置默认值 + form.val('diy-form', { + [`${key}`]: vue[key] + }); + console.log(`form.val(${key}, ${vue[key]})`); + } + + // 监听select事件, 并更新vue数据, layui + vue. 针对select元素,不能使用v-model绑定数据, 只能使用layui的form.on('select')事件监听 + form.on('select(' + key + ')', function (data) { + if (vue.hasOwnProperty(key)) { + vue[key] = data.value; + console.log(`vue.${key} = ${data.value}`); + } + }); + }); + }); + + initLayuiSelectBindings(); // 启动默认绑定事件一次 + + // FIX: 当切换视频号隐藏还是显示时,需要重新渲染layui的select元素 + // 监听视频号设置是否折叠 + form.on('switch(channelCollapsed)', function (data) { + vue.channelCollapsed = data.elem.checked; + form.render('select'); + initLayuiSelectBindings(); + }); + + // FIX: 当切换视频号隐藏还是显示时,需要重新渲染layui的select元素,重新渲染后,需要重新绑定初始化数据和事件 + vue.$watch('is_channel', function (newVal, oldVal) { + if (newVal !== oldVal) { + form.render('select'); + initLayuiSelectBindings(); + } + }); $("body").off("click", ".edit-attribute .attr-wrap .restore-wrap .attr-title .tab-wrap span").on("click", ".edit-attribute .attr-wrap .restore-wrap .attr-title .tab-wrap span", function () { $(this).addClass('active bg-color').siblings().removeClass('active bg-color'); @@ -83,15 +139,24 @@ layui.use(['form'], function () { }); form.on('submit(save)', function (data) { + console.log('submit save:', { data, vue }); if (repeat_flag) return; repeat_flag = true; var formData = { - is_kefu:vue.is_kefu, - is_mp:vue.is_mp, - is_file:vue.is_file, - is_video:vue.is_video, - is_map:vue.is_map - } + is_kefu: vue.is_kefu, + is_mp: vue.is_mp, + is_file: vue.is_file, + is_video: vue.is_video, + is_channel: vue.is_channel, + is_map: vue.is_map, + // 视频号设置 + channel_display_style: vue.channel_display_style, + channel_aspect_ratio: vue.channel_aspect_ratio, + channel_show_view_count: vue.channel_show_view_count, + channel_row_count: vue.channel_row_count, + channel_title_line_clamp: vue.channel_title_line_clamp, + channel_show_play_btn: vue.channel_show_play_btn + }; $.ajax({ type: "post", url: ns.url('personnel://shop/personnel/diy'), diff --git a/src/addon/personnel/shop/view/public/img/mingpian.png b/src/addon/personnel/shop/view/public/img/mingpian.png index a5452612781e83241e667926d159bc4ed9c9351f..71b4634d785c7ca8a9dde46613356a4f60ff1a0c 100644 GIT binary patch literal 9574 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 diff --git a/upgrade.sql b/upgrade.sql index 5f260d106..b33451869 100644 --- a/upgrade.sql +++ b/upgrade.sql @@ -122,4 +122,48 @@ ALTER DATABASE shop_mallnew CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci -- 修改表字符集 ALTER TABLE lucky_aikefu_conversation CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -ALTER TABLE lucky_aikefu_message CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; \ No newline at end of file +ALTER TABLE lucky_aikefu_message CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + + +-- 创建视频号表 +CREATE TABLE IF NOT EXISTS `lucky_personnel_channel` +( + `channel_id` int unsigned NOT NULL AUTO_INCREMENT, + `site_id` int unsigned NOT NULL DEFAULT 0 COMMENT '站点ID', + `create_time` int unsigned NOT NULL DEFAULT 0 COMMENT '创建时间', + `channel_type` varchar(30) NOT NULL DEFAULT 'wechat' COMMENT '视频号类型:wechat-微信视频号,douyin-抖音,kuaishou-快手,redbook-小红书,bilibili-B站', + `channel_name` varchar(200) NOT NULL DEFAULT '' COMMENT '视频号ID', + `feed_id` varchar(500) NOT NULL DEFAULT '' COMMENT '视频号内容ID', + `feed_token` varchar(255) NOT NULL DEFAULT '' COMMENT '视频号视频的标识', + `avatar_image_type` varchar(20) NOT NULL DEFAULT 'upload' COMMENT '头像类型:upload-上传图片,url-URL', + `avatar_url` varchar(500) NOT NULL DEFAULT '' COMMENT '头像URL', + `video_title` varchar(500) NOT NULL DEFAULT '' COMMENT '视频标题', + `cover_image_type` varchar(20) NOT NULL DEFAULT 'upload' COMMENT '封面类型:upload-上传图片,url-URL', + `cover_url` varchar(500) NOT NULL DEFAULT '' COMMENT '封面URL', + `view_count` int unsigned NOT NULL DEFAULT 0 COMMENT '视频观看次数', + `show_view_count` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否显示视频观看次数:0-不显示,1-显示', + `show_follow` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否显示关注按钮:0-不显示,1-显示', + `is_show` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否显示:0-隐藏,1-显示', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序,数值越小越靠前', + PRIMARY KEY (`channel_id`), + KEY `idx_site_id` (`site_id`), + KEY `idx_channel_type` (`channel_type`), + KEY `idx_is_show` (`is_show`), + KEY `idx_sort` (`sort`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='电子名片视频号资源表'; + +-- 插入视频号菜单权限(使用 IGNORE 避免重复插入报错) +INSERT IGNORE INTO `lucky_menu` (`app_module`, `addon`, `title`, `name`, `parent`, `level`, `url`, `is_show`, `sort`, `desc`, `is_icon`, `picture`, `picture_select`, `is_control`) +VALUES +('shop', 'personnel', '视频号', 'PERSONNEL_CHANNEL_LIST', 'PERSONNEL_ROOT', 4, 'personnel://shop/enterprise/channellists', 1, 4, '', 0, '', '', 1), +('shop', 'personnel', '添加视频号', 'PERSONNEL_CHANNEL_ADD', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeladd', 0, 1, '', 0, '', '', 1), +('shop', 'personnel', '编辑视频号', 'PERSONNEL_CHANNEL_EDIT', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeledit', 0, 1, '', 0, '', '', 1), +('shop', 'personnel', '删除视频号', 'PERSONNEL_CHANNEL_DELETE', 'PERSONNEL_CHANNEL_LIST', 5, 'personnel://shop/enterprise/channeldelete', 0, 2, '', 0, '', '', 1); + +-- 微信视频号组件 +-- 仅当WechatChannel不存在时添加记录 +INSERT INTO lucky_diy_view_util (`name`, `title`, `type`, `value`, `addon_name`, `sort`, `support_diy_view`, `max_count`, `is_delete`, `icon`, `icon_type`) +SELECT 'WechatChannel', '微信视频号', 'SYSTEM', '{ "list": [{ "channelName":"", "finderUserName": "", "avatarImageType": "url", "avatarUrl": "", "videoTitle": "", "coverImageType": "url", "coverUrl": "", "feedId": "", "feedToken": "", "viewCount": 0, "showViewCount": true, "embedMode": false, "channelType":"wechat" }], "rowCount": 2, "showStyle": "fixed", "aspectRatio":"16:9", "titleLineClamp": 1, "showPlayBtn": true}', '', 100110, '', 0, 0, '/public/static/img/svg/xuanxiangka.svg', 0 +WHERE NOT EXISTS ( + SELECT 1 FROM lucky_diy_view_util WHERE name = 'WechatChannel' +); \ No newline at end of file