diff --git a/Server/application/cunkebao/service/ContentItemService.php b/Server/application/cunkebao/service/ContentItemService.php new file mode 100644 index 00000000..20f1a2aa --- /dev/null +++ b/Server/application/cunkebao/service/ContentItemService.php @@ -0,0 +1,158 @@ +save($this->prepareItemData($data, $libraryId)); + + if (!$result) { + Db::rollback(); + return ['code' => 500, 'msg' => '创建内容项目失败']; + } + + Db::commit(); + return ['code' => 200, 'msg' => '创建成功', 'data' => ['id' => $item->id]]; + } catch (\Exception $e) { + Db::rollback(); + return ['code' => 500, 'msg' => '创建失败:' . $e->getMessage()]; + } + } + + /** + * 准备内容项目数据 + * @param array $data 原始数据 + * @param int $libraryId 内容库ID + * @return array + */ + private function prepareItemData($data, $libraryId) + { + return [ + 'libraryId' => $libraryId, + 'title' => $data['title'] ?? '', + 'content' => $data['content'] ?? '', + 'images' => isset($data['images']) ? json_encode($data['images']) : json_encode([]), + 'videos' => isset($data['videos']) ? json_encode($data['videos']) : json_encode([]), + 'status' => $data['status'] ?? 0, + 'createTime' => time(), + 'updateTime' => time() + ]; + } + + /** + * 删除内容项目 + * @param int $itemId 内容项目ID + * @return array + */ + public function deleteItem($itemId) + { + try { + $result = ContentItem::where('id', $itemId) + ->update(['isDel' => 1, 'updateTime' => time()]); + + if ($result === false) { + return ['code' => 500, 'msg' => '删除失败']; + } + + return ['code' => 200, 'msg' => '删除成功']; + } catch (\Exception $e) { + return ['code' => 500, 'msg' => '删除失败:' . $e->getMessage()]; + } + } + + // ==================== 查询相关 ==================== + + /** + * 获取内容项目列表 + * @param array $params 查询参数 + * @param int $libraryId 内容库ID + * @return array + */ + public function getItemList($params, $libraryId) + { + $where = [ + ['libraryId', '=', $libraryId], + ['isDel', '=', 0] + ]; + + if (!empty($params['keyword'])) { + $where[] = ['title', 'like', '%' . $params['keyword'] . '%']; + } + + if (isset($params['status'])) { + $where[] = ['status', '=', $params['status']]; + } + + $list = ContentItem::where($where) + ->field('id,title,content,images,videos,status,createTime,updateTime') + ->order('id', 'desc') + ->page($params['page'], $params['limit']) + ->select(); + + $this->processItemList($list); + + $total = ContentItem::where($where)->count(); + + return [ + 'code' => 200, + 'msg' => '获取成功', + 'data' => [ + 'list' => $list, + 'total' => $total, + 'page' => $params['page'] + ] + ]; + } + + /** + * 处理内容项目列表数据 + * @param array $list 内容项目列表 + */ + private function processItemList(&$list) + { + foreach ($list as &$item) { + $item['images'] = json_decode($item['images'] ?: '[]', true); + $item['videos'] = json_decode($item['videos'] ?: '[]', true); + } + } + + // ==================== 状态管理 ==================== + + /** + * 更新内容项目状态 + * @param int $itemId 内容项目ID + * @param int $status 状态 + * @return array + */ + public function updateItemStatus($itemId, $status) + { + try { + $result = ContentItem::where('id', $itemId) + ->update(['status' => $status, 'updateTime' => time()]); + + if ($result === false) { + return ['code' => 500, 'msg' => '更新状态失败']; + } + + return ['code' => 200, 'msg' => '更新成功']; + } catch (\Exception $e) { + return ['code' => 500, 'msg' => '更新失败:' . $e->getMessage()]; + } + } +} \ No newline at end of file diff --git a/Server/application/cunkebao/service/ContentLibraryService.php b/Server/application/cunkebao/service/ContentLibraryService.php new file mode 100644 index 00000000..23f0d9cf --- /dev/null +++ b/Server/application/cunkebao/service/ContentLibraryService.php @@ -0,0 +1,185 @@ + $data['name'], + 'userId' => $userId, + 'isDel' => 0 + ])->find(); + + if ($exists) { + return ['code' => 400, 'msg' => '内容库名称已存在']; + } + + Db::startTrans(); + try { + $library = new ContentLibrary; + $result = $library->save($this->prepareLibraryData($data, $userId)); + + if (!$result) { + Db::rollback(); + return ['code' => 500, 'msg' => '创建内容库失败']; + } + + Db::commit(); + return ['code' => 200, 'msg' => '创建成功', 'data' => ['id' => $library->id]]; + } catch (\Exception $e) { + Db::rollback(); + return ['code' => 500, 'msg' => '创建失败:' . $e->getMessage()]; + } + } + + /** + * 准备内容库数据 + * @param array $data 原始数据 + * @param int $userId 用户ID + * @return array + */ + private function prepareLibraryData($data, $userId) + { + return [ + 'name' => $data['name'], + 'sourceFriends' => $data['sourceType'] == 1 ? json_encode($data['friends']) : json_encode([]), + 'sourceGroups' => $data['sourceType'] == 2 ? json_encode($data['groups']) : json_encode([]), + 'groupMembers' => $data['sourceType'] == 2 ? json_encode($data['groupMembers']) : json_encode([]), + 'keywordInclude' => isset($data['keywordInclude']) ? json_encode($data['keywordInclude'], 256) : json_encode([]), + 'keywordExclude' => isset($data['keywordExclude']) ? json_encode($data['keywordExclude'], 256) : json_encode([]), + 'aiEnabled' => $data['aiEnabled'] ?? 0, + 'aiPrompt' => $data['aiPrompt'] ?? '', + 'timeEnabled' => $data['timeEnabled'] ?? 0, + 'timeStart' => isset($data['startTime']) ? strtotime($data['startTime']) : 0, + 'timeEnd' => isset($data['endTime']) ? strtotime($data['endTime']) : 0, + 'sourceType' => $data['sourceType'] ?? 1, + 'status' => $data['status'] ?? 0, + 'userId' => $userId, + 'createTime' => time(), + 'updateTime' => time() + ]; + } + + // ==================== 查询相关 ==================== + + /** + * 获取内容库列表 + * @param array $params 查询参数 + * @param int $userId 用户ID + * @return array + */ + public function getLibraryList($params, $userId) + { + $where = [ + ['userId', '=', $userId], + ['isDel', '=', 0] + ]; + + if (!empty($params['keyword'])) { + $where[] = ['name', 'like', '%' . $params['keyword'] . '%']; + } + + if (!empty($params['sourceType'])) { + $where[] = ['sourceType', '=', $params['sourceType']]; + } + + $list = ContentLibrary::where($where) + ->field('id,name,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,sourceType,userId,createTime,updateTime') + ->with(['user' => function($query) { + $query->field('id,username'); + }]) + ->order('id', 'desc') + ->page($params['page'], $params['limit']) + ->select(); + + $this->processLibraryList($list); + + $total = ContentLibrary::where($where)->count(); + + return [ + 'code' => 200, + 'msg' => '获取成功', + 'data' => [ + 'list' => $list, + 'total' => $total, + 'page' => $params['page'] + ] + ]; + } + + /** + * 处理内容库列表数据 + * @param array $list 内容库列表 + */ + private function processLibraryList(&$list) + { + foreach ($list as &$item) { + $item['sourceFriends'] = json_decode($item['sourceFriends'] ?: '[]', true); + $item['sourceGroups'] = json_decode($item['sourceGroups'] ?: '[]', true); + $item['keywordInclude'] = json_decode($item['keywordInclude'] ?: '[]', true); + $item['keywordExclude'] = json_decode($item['keywordExclude'] ?: '[]', true); + $item['creatorName'] = $item['user']['username'] ?? ''; + + if (!empty($item['sourceFriends']) && $item['sourceType'] == 1) { + $item['selectedFriends'] = $this->getFriendsInfo($item['sourceFriends']); + } + + if (!empty($item['sourceGroups']) && $item['sourceType'] == 2) { + $item['selectedGroups'] = $this->getGroupsInfo($item['sourceGroups']); + } + + unset($item['user']); + } + } + + // ==================== 数据关联查询 ==================== + + /** + * 获取好友信息 + * @param array $friendIds 好友ID列表 + * @return array + */ + private function getFriendsInfo($friendIds) + { + if (empty($friendIds)) { + return []; + } + + return Db::name('wechat_friend')->alias('wf') + ->field('wf.id,wf.wechatId, wa.nickname, wa.avatar') + ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') + ->whereIn('wf.id', $friendIds) + ->select(); + } + + /** + * 获取群组信息 + * @param array $groupIds 群组ID列表 + * @return array + */ + private function getGroupsInfo($groupIds) + { + if (empty($groupIds)) { + return []; + } + + return Db::name('wechat_group')->alias('g') + ->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId') + ->whereIn('g.id', $groupIds) + ->select(); + } +} \ No newline at end of file diff --git a/Server/database/create_menu_table.sql b/Server/database/create_menu_table.sql deleted file mode 100644 index 106bf7af..00000000 --- a/Server/database/create_menu_table.sql +++ /dev/null @@ -1,35 +0,0 @@ --- 创建菜单表 -CREATE TABLE IF NOT EXISTS `tk_menus` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单ID', - `title` varchar(50) NOT NULL COMMENT '菜单名称', - `path` varchar(100) NOT NULL COMMENT '路由路径', - `icon` varchar(50) DEFAULT NULL COMMENT '图标名称', - `parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '父菜单ID,0表示顶级菜单', - `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1启用,0禁用', - `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序,数值越小越靠前', - `create_time` int(11) DEFAULT NULL COMMENT '创建时间', - `update_time` int(11) DEFAULT NULL COMMENT '更新时间', - PRIMARY KEY (`id`), - KEY `idx_parent_id` (`parent_id`), - KEY `idx_status` (`status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统菜单表'; - --- 插入超级管理员顶级菜单 -INSERT INTO `tk_menus` (`title`, `path`, `icon`, `parent_id`, `status`, `sort`, `create_time`, `update_time`) VALUES -('仪表盘', '/dashboard', 'LayoutDashboard', 0, 1, 10, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('项目管理', '/dashboard/projects', 'FolderKanban', 0, 1, 20, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('客户池', '/dashboard/customers', 'Users', 0, 1, 30, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('管理员权限', '/dashboard/admins', 'Settings', 0, 1, 40, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('系统设置', '/settings', 'Cog', 0, 1, 50, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()); - --- 插入子菜单 -INSERT INTO `tk_menus` (`title`, `path`, `icon`, `parent_id`, `status`, `sort`, `create_time`, `update_time`) VALUES -('项目列表', '/dashboard/projects', 'List', 2, 1, 21, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('新建项目', '/dashboard/projects/new', 'PlusCircle', 2, 1, 22, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('客户管理', '/dashboard/customers', 'Users', 3, 1, 31, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('客户分析', '/dashboard/customers/analytics', 'BarChart', 3, 1, 32, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('管理员列表', '/dashboard/admins', 'UserCog', 4, 1, 41, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('角色管理', '/dashboard/admins/roles', 'ShieldCheck', 4, 1, 42, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('权限设置', '/dashboard/admins/permissions', 'Lock', 4, 1, 43, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('基本设置', '/settings/general', 'Settings', 5, 1, 51, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), -('安全设置', '/settings/security', 'Shield', 5, 1, 52, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()); \ No newline at end of file diff --git a/Server/database/flow_order.sql b/Server/database/flow_order.sql deleted file mode 100644 index 6b7ac147..00000000 --- a/Server/database/flow_order.sql +++ /dev/null @@ -1,24 +0,0 @@ --- 创建流量订单表 -CREATE TABLE IF NOT EXISTS `tk_flow_order` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `userId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户ID', - `packageId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '套餐ID', - `orderNo` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号', - `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '支付价格', - `originalPrice` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '原价', - `payType` varchar(20) NOT NULL DEFAULT '' COMMENT '支付类型(wxpay|alipay|nopay)', - `tradeNo` varchar(64) NOT NULL DEFAULT '' COMMENT '支付平台交易号', - `createTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', - `updateTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', - `payTime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '支付时间', - `status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '状态(0:待支付 1:已完成 2:已取消)', - `payStatus` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '支付状态(0:未支付 10:已支付)', - `memo` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', - `isDel` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否删除(0:否 1:是)', - PRIMARY KEY (`id`), - UNIQUE KEY `idx_order_no` (`orderNo`), - KEY `idx_user_id` (`userId`), - KEY `idx_package_id` (`packageId`), - KEY `idx_create_time` (`createTime`), - KEY `idx_status` (`status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流量订单表'; \ No newline at end of file diff --git a/Server/database/seeds/FlowPackageSeeder.php b/Server/database/seeds/FlowPackageSeeder.php deleted file mode 100644 index a2dc27dd..00000000 --- a/Server/database/seeds/FlowPackageSeeder.php +++ /dev/null @@ -1,61 +0,0 @@ - '基础套餐', - 'tag' => '入门级', - 'original_price' => 999.00, - 'price' => 899.00, - 'monthly_flow' => 20, - 'duration' => 1, - 'privileges' => "基础客服支持\n自动化任务\n每日数据报表", - 'sort' => 1, - 'status' => 1 - ], - [ - 'name' => '标准套餐', - 'tag' => '热销', - 'original_price' => 2799.00, - 'price' => 2499.00, - 'monthly_flow' => 50, - 'duration' => 3, - 'privileges' => "优先客服支持\n高级自动化任务\n每日数据报表\n好友数据分析\n一对一培训支持", - 'sort' => 2, - 'status' => 1 - ], - [ - 'name' => '专业套餐', - 'tag' => '推荐', - 'original_price' => 5999.00, - 'price' => 4999.00, - 'monthly_flow' => 100, - 'duration' => 6, - 'privileges' => "24小时专属客服\n全部自动化任务\n实时数据报表\n深度数据分析\n个性化培训支持\n专属策略顾问\n优先功能更新", - 'sort' => 3, - 'status' => 1 - ], - [ - 'name' => '企业套餐', - 'tag' => '高级', - 'original_price' => 11999.00, - 'price' => 9999.00, - 'monthly_flow' => 200, - 'duration' => 12, - 'privileges' => "24小时专属客服\n全部自动化任务\n实时数据报表\n深度数据分析\n个性化培训支持\n专属策略顾问\n优先功能更新\n企业API对接\n专属功能定制\n全平台数据打通", - 'sort' => 4, - 'status' => 1 - ] - ]; - - $this->table('flow_package')->insert($data)->save(); - } -} \ No newline at end of file