chore: 针对ThinkPHP 6.x 系列,支持自定义.env 文件加载

This commit is contained in:
2025-11-18 18:35:05 +08:00
parent 4654bca6c3
commit 7ad78f1ee6
17 changed files with 81 additions and 3729 deletions

View File

@@ -1,261 +0,0 @@
<?php
/**
* AI聊天历史记录模型
* 负责处理AI对话中的聊天记录数据存储和管理
*/
namespace app\model\ai;
use think\facade\Db;
use app\model\BaseModel;
use Exception;
class AiChatHistory extends BaseModel
{
/**
* 日志文件名称
* @var string
*/
private $log_file = 'ai_chat_history.log';
/**
* 表名
* @var string
*/
protected $name = 'ai_chat_history';
/**
* 保存聊天记录
* @param array $data 聊天记录数据
* @return array
*/
public function saveHistory($data)
{
try {
// 验证必要字段
if (empty($data['site_id']) || empty($data['user_id']) || empty($data['session_id']) ||
empty($data['platform']) || empty($data['user_message']) || empty($data['ai_message'])) {
return $this->error('', 'PARAMETERS_INCOMPLETE');
}
// 补充默认字段
$data['create_time'] = $data['create_time'] ?? time();
$data['ip'] = $data['ip'] ?? request()->ip();
// 保存数据
$result = Db::name($this->name)->insert($data);
if ($result) {
return $this->success(['id' => Db::name($this->name)->getLastInsID()]);
} else {
return $this->error('', 'SAVE_FAILED');
}
} catch (Exception $e) {
// 记录错误日志
log_write('Save chat history error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'SAVE_EXCEPTION');
}
}
/**
* 获取聊天历史记录列表
* @param array $where 条件数组
* @param array $field 查询字段
* @param string $order 排序方式
* @param int $page 页码
* @param int $page_size 每页数量
* @return array
*/
public function getHistoryList($where = [], $field = ['*'], $order = 'create_time ASC', $page = 1, $page_size = 20)
{
try {
// 计算偏移量
$offset = ($page - 1) * $page_size;
// 查询列表
$list = Db::name($this->name)
->field($field)
->where($where)
->order($order)
->limit($offset, $page_size)
->select();
// 查询总数
$total = Db::name($this->name)
->where($where)
->count();
return $this->success([
'list' => $list,
'total' => $total,
'page' => $page,
'page_size' => $page_size,
'total_page' => ceil($total / $page_size)
]);
} catch (Exception $e) {
log_write('Get chat history list error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'GET_LIST_FAILED');
}
}
/**
* 根据会话ID获取聊天记录
* @param string $session_id 会话ID
* @param array $where 额外条件
* @param int $page 页码
* @param int $page_size 每页数量
* @return array
*/
public function getHistoryBySessionId($session_id, $where = [], $page = 1, $page_size = 20)
{
if (empty($session_id)) {
return $this->error('', 'SESSION_ID_EMPTY');
}
$where['session_id'] = $session_id;
return $this->getHistoryList($where, ['*'], 'create_time ASC', $page, $page_size);
}
/**
* 获取用户的所有聊天记录
* @param string $user_id 用户ID
* @param array $where 额外条件
* @param int $page 页码
* @param int $page_size 每页数量
* @return array
*/
public function getUserHistory($user_id, $where = [], $page = 1, $page_size = 20)
{
if (empty($user_id)) {
return $this->error('', 'USER_ID_EMPTY');
}
$where['user_id'] = $user_id;
return $this->getHistoryList($where, ['*'], 'create_time DESC', $page, $page_size);
}
/**
* 删除聊天记录
* @param array $where 条件数组
* @return array
*/
public function deleteHistory($where)
{
try {
if (empty($where)) {
return $this->error('', 'DELETE_CONDITION_EMPTY');
}
$result = Db::name($this->name)->where($where)->delete();
if ($result !== false) {
return $this->success(['deleted' => $result]);
} else {
return $this->error('', 'DELETE_FAILED');
}
} catch (Exception $e) {
log_write('Delete chat history error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'DELETE_EXCEPTION');
}
}
/**
* 根据会话ID删除聊天记录
* @param string $session_id 会话ID
* @param array $where 额外条件
* @return array
*/
public function deleteHistoryBySessionId($session_id, $where = [])
{
if (empty($session_id)) {
return $this->error('', 'SESSION_ID_EMPTY');
}
$where['session_id'] = $session_id;
return $this->deleteHistory($where);
}
/**
* 获取用户的会话消息统计
* @param string $user_id 用户ID
* @param array $where 额外条件
* @return array
*/
public function getUserMessageStats($user_id, $where = [])
{
try {
if (empty($user_id)) {
return $this->error('', 'USER_ID_EMPTY');
}
$where['user_id'] = $user_id;
// 统计总消息数
$total_count = Db::name($this->name)->where($where)->count();
// 统计今日消息数
$today_count = Db::name($this->name)
->where($where)
->whereTime('create_time', 'today')
->count();
// 统计最近消息时间
$last_message = Db::name($this->name)
->where($where)
->order('create_time DESC')
->find();
return $this->success([
'total_count' => $total_count,
'today_count' => $today_count,
'last_message_time' => $last_message ? $last_message['create_time'] : 0
]);
} catch (Exception $e) {
log_write('Get user message stats error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'GET_STATS_FAILED');
}
}
/**
* 清理过期的聊天记录
* @param int $days 保留天数
* @param array $where 额外条件
* @return array
*/
public function cleanupExpiredHistory($days = 30, $where = [])
{
try {
$expire_time = time() - ($days * 24 * 60 * 60);
$where['create_time'] = ['<', $expire_time];
return $this->deleteHistory($where);
} catch (Exception $e) {
log_write('Cleanup expired history error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'CLEANUP_FAILED');
}
}
/**
* 批量保存聊天记录
* @param array $data 聊天记录数组
* @return array
*/
public function batchSaveHistory($data)
{
try {
if (empty($data) || !is_array($data)) {
return $this->error('', 'DATA_EMPTY');
}
// 批量插入数据
$result = Db::name($this->name)->insertAll($data);
if ($result) {
return $this->success(['count' => $result]);
} else {
return $this->error('', 'BATCH_SAVE_FAILED');
}
} catch (Exception $e) {
log_write('Batch save chat history error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'BATCH_SAVE_EXCEPTION');
}
}
}

View File

@@ -1,266 +0,0 @@
<?php
/**
* AI聊天会话模型
* 用于管理AI聊天的会话信息
*/
namespace app\model\ai;
use \app\model\BaseModel;
use think\facade\Db;
class AiChatSession extends BaseModel
{
/**
* 日志文件名称
* @var string
*/
private $log_file = 'ai_chat_session.log';
/**
* 表名
* @var string
*/
protected $name = 'ai_chat_session';
/**
* 获取会话信息
* @param array $where 条件
* @param array $field 字段
* @return array
*/
public function getSessionInfo($where = [], $field = ['*'])
{
try {
$data = Db::name($this->name)
->where($where)
->field($field)
->find();
return $this->success($data);
} catch (\Exception $e) {
log_write('Get session info error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'GET_SESSION_INFO_ERROR');
}
}
/**
* 获取会话列表
* @param array $where 条件
* @param array $field 字段
* @param string $order 排序
* @param int $page 页码
* @param int $page_size 每页数量
* @return array
*/
public function getSessionList($where = [], $field = ['*'], $order = 'last_active_time DESC', $page = 1, $page_size = 20)
{
try {
$count = Db::name($this->name)
->where($where)
->count();
$list = [];
if ($count > 0) {
$list = Db::name($this->name)
->where($where)
->field($field)
->order($order)
->page($page, $page_size)
->select();
}
return $this->success(json_encode([
'list' => $list,
'total' => $count,
'page' => $page,
'page_size' => $page_size
]));
} catch (\Exception $e) {
log_write('Get session list error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'GET_SESSION_LIST_ERROR');
}
}
/**
* 创建会话
* @param array $data 数据
* @return array
*/
public function createSession($data = [])
{
try {
// 确保必要字段存在
if (empty($data['session_id']) || empty($data['user_id']) || empty($data['site_id'])) {
return $this->error('', 'MISSING_REQUIRED_FIELDS');
}
// 检查会话是否已存在
$exists = Db::name($this->name)
->where('session_id', $data['session_id'])
->count();
if ($exists > 0) {
return $this->error('', 'SESSION_ALREADY_EXISTS');
}
// 设置默认值
$data['create_time'] = $data['create_time'] ?? time();
$data['last_active_time'] = $data['last_active_time'] ?? time();
$result = Db::name($this->name)->insert($data);
if ($result) {
return $this->success(json_encode(['session_id' => $data['session_id']]));
} else {
return $this->error('', 'CREATE_SESSION_FAILED');
}
} catch (\Exception $e) {
log_write('Create session error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'CREATE_SESSION_ERROR');
}
}
/**
* 更新会话
* @param array $where 条件
* @param array $data 数据
* @return array
*/
public function updateSession($where = [], $data = [])
{
try {
if (empty($where)) {
return $this->error('', 'WHERE_CONDITION_EMPTY');
}
$result = Db::name($this->name)
->where($where)
->update($data);
return $this->success(['affected_rows' => $result]);
} catch (\Exception $e) {
log_write('Update session error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'UPDATE_SESSION_ERROR');
}
}
/**
* 删除会话
* @param array $where 条件
* @return array
*/
public function deleteSession($where = [])
{
try {
if (empty($where)) {
return $this->error('', 'WHERE_CONDITION_EMPTY');
}
// 开启事务
Db::startTrans();
try {
// 删除会话
$result = Db::name($this->name)
->where($where)
->delete();
// 删除相关的聊天历史
Db::name('shop_ai_chat_history')
->where($where)
->delete();
Db::commit();
return $this->success(['affected_rows' => $result]);
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
} catch (\Exception $e) {
log_write('Delete session error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'DELETE_SESSION_ERROR');
}
}
/**
* 更新会话最后活动时间
* @param string $session_id 会话ID
* @param int $time 时间戳
* @return array
*/
public function updateLastActiveTime($session_id, $time = null)
{
$time = $time ?? time();
return $this->updateSession(['session_id' => $session_id], ['last_active_time' => $time]);
}
/**
* 获取用户的活跃会话数
* @param int $user_id 用户ID
* @param int $site_id 站点ID
* @param int $days 天数
* @return array
*/
public function getUserActiveSessionsCount($user_id, $site_id, $days = 7)
{
try {
$start_time = time() - ($days * 24 * 3600);
$count = Db::name($this->name)
->where('user_id', $user_id)
->where('site_id', $site_id)
->where('last_active_time', '>=', $start_time)
->count();
return $this->success(['count' => $count]);
} catch (\Exception $e) {
log_write('Get active sessions count error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'GET_ACTIVE_SESSIONS_COUNT_ERROR');
}
}
/**
* 清理过期会话
* @param int $days 天数
* @return array
*/
public function cleanupExpiredSessions($days = 30)
{
try {
$expire_time = time() - ($days * 24 * 3600);
// 开启事务
Db::startTrans();
try {
// 找出所有过期会话ID
$expired_sessions = Db::name($this->name)
->where('last_active_time', '<', $expire_time)
->column('session_id');
if (!empty($expired_sessions)) {
// 删除过期会话
$session_result = Db::name($this->name)
->where('session_id', 'in', $expired_sessions)
->delete();
// 删除相关聊天历史
$history_result = Db::name('shop_ai_chat_history')
->where('session_id', 'in', $expired_sessions)
->delete();
}
Db::commit();
return $this->success([
'expired_count' => count($expired_sessions),
'session_deleted' => $session_result ?? 0,
'history_deleted' => $history_result ?? 0
]);
} catch (\Exception $e) {
Db::rollback();
throw $e;
}
} catch (\Exception $e) {
log_write('Cleanup expired sessions error: ' . $e->getMessage(), 'error', $this->log_file);
return $this->error('', 'CLEANUP_EXPIRED_SESSIONS_ERROR');
}
}
}

View File

@@ -93,19 +93,6 @@ class Config extends BaseModel
return $res;
}
/**
* 获取支持的应用模块
* @return array
*/
public function getSupportAppModules()
{
return [
['value' => 'shop', 'label' => '商家'],
['value' => 'h5', 'label' => 'H5轻应用'],
['value' => 'weixin', 'label' => '微信小程序'],
];
}
/**
* 默认图上传配置
* @param $data
@@ -299,300 +286,6 @@ class Config extends BaseModel
return $res;
}
/**
* 获取支持的AI平台类型
* @return array
*/
public function getSupportAIPlatformTypes()
{
return [
['value' => 'dify', 'label' => 'Dify'],
['value' => 'ragflow', 'label' => 'Ragflow'],
];
}
/**
* 通用AI相关配置获取方法
* @param int $site_id 站点ID, 默认为-1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为*,表示所有应用模块都生效
* @param string $config_key 配置键, 默认为空字符串, 表示获取通用配置信息
* @param array $common_config 通用配置信息, 默认为空数组
* @return array
*/
private function _getAIConfig($site_id = -1, $app_module = '*', $config_key ='', $common_config = [])
{
// 应用模块配置获取
try {
// 站点ID为-1时获取通用配置信息
if ($site_id == -1) {
return $this->error('', 'MISSING_SITE_ID');
}
// 配置键为空字符串, 表示获取通用配置信息
if (empty($config_key)) {
return $this->error('', 'MISSING_CONFIG_KEY');
}
$config = new ConfigModel();
$support_app_modules = $this->getSupportAppModules();
// 检查应用模块是否支持, 如果是*,则表示所有应用模块都生效
if ($app_module != '*') {
if (!in_array($app_module, array_column($support_app_modules, 'value'))) {
return $this->error('', 'APP_MODULE_NOT_SUPPORTED');
}
}
// 如果是*,则表示所有应用模块都生效, 遍历所有应用模块,根据应用模块获取配置信息, 为每一种应用模块生成独立的配置信息,每一种类型的应用模块,对应自己的配置信息,然后将所有的配置信息返回
$app_module_config = [];
foreach ($support_app_modules as $item) {
$app_module = $item['value'];
// 检查应用模块是否支持
try {
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', $config_key]]);
if (empty($res['data']['value'])) {
$res['data']['value'] = $common_config;
}
} catch (\Exception $e) {
$res['data']['value'] = $common_config;
}
$app_module_config[$app_module] = $res['data']['value'];
}
$res['data']['value'] = $app_module_config;
return $res;
} catch (\Exception $e) {
return $this->error('', 'GET_CONFIG_ERROR' . $e->getMessage());
}
}
/**
* 通用AI相关配置设置方法
* @param $data 配置信息
* @param int $site_id 站点ID, 默认为-1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为空字符串
* @param string $config_key 配置键, 默认为空字符串
* @param string $data_desc 配置描述, 默认为空字符串
* @return array
*/
private function _setAIConfig($data, $site_id = -1, $app_module = '', $config_key = '', $data_desc = '')
{
// 站点ID为-1时设置通用配置信息
if ($site_id == -1) {
return $this->error('', 'MISSING_SITE_ID');
}
// 应用模块为空字符串
if (empty($app_module)) {
return $this->error('', 'MISSING_APP_MODULE');
}
// 配置键为空字符串
if (empty($config_key)) {
return $this->error('', 'MISSING_CONFIG_KEY');
}
$config = new ConfigModel();
$res = $config->setConfig($data, $data_desc, 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', $config_key]]);
return $res;
}
/**
* 设置AI第三平台提供的配置信息
* @param $data 配置信息
* @param int $site_id 站点ID, 默认为-1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为*, 表示所有应用模块都生效
* @return array
*/
public function setAIPlatformConfig($data, $site_id = -1, $app_module = '')
{
return $this->_setAIConfig($data, $site_id, $app_module, 'AI_PLATFORM_CONFIG', 'AI第三平台提供的配置信息');
}
/**
* 设置AI智能客服配置信息
* @param $data 配置信息
* @param int $site_id 站点ID, 默认为1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为*, 表示所有应用模块都生效
* @return array
*/
public function setAIAgentServicesConfig($data, $site_id = 1, $app_module = '*')
{
return $this->_setAIConfig($data, $site_id, $app_module, 'AI_AGENT_SERVICES_CONFIG', 'AI智能客服配置信息');
}
/**
* 获取AI第三平台提供的通用配置信息
* @return array
*/
private function getCommonAIPlatformConfig()
{
// 默认ID
$id = time();
// 通用配置
return [
'default' => ['id' => $id, 'name' => 'dify-demo'],
'list' => [
// Dify Demo 版本,
['id' => $id, 'name' => 'dify-demo', 'type' => 'dify', 'type_label' => 'Dify', 'desc' => 'Dify 线上Demo 版本', 'enable' => 1, 'base_url' => 'https://localhost/api/ai', 'api_key' => 'xxxxxxx', 'create_time' => time()],
]
];
}
/**
* 获取AI第三平台提供的配置信息
* @param int $site_id 站点ID, 默认为1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为*, 表示所有应用模块都生效
* @return array
*/
public function getAIPlatformConfig($site_id = 1, $app_module = '*')
{
return $this->_getAIConfig($site_id, $app_module, 'AI_PLATFORM_CONFIG', $this->getCommonAIPlatformConfig());
}
/**
* 获取AI智能客服的通用配置信息
* @return array
*/
private function getCommonAIAgentServicesConfig()
{
return [
// 是否开启AI功能
'enable' => false,
// 用户头像url
'user_avatar' => [
'en' => '',
'zh_CN' => '',
],
// AI客服头像url
'ai_avatar' => [
'en' => '',
'zh_CN' => '',
],
// AI客服姓名
'ai_name' => [
'en' => '',
'zh_CN' => '',
],
// 欢迎语, 也称为开场白,初始化消息
'welcome_messages' => [
'en' => [],
'zh_CN' => [],
],
// 是否显示加载更多按钮
'show_load_more_button' => true,
// 最大消息数量
'max_messages' => 100,
// 是否启用流式响应
'stream_mode' => true,
// 流式响应的超时时间,单位:秒
'stream_timeout' => 30,
// 流式响应速度(字符/秒)
'stream_speed' => 20,
// 是否开启支持语音输入
'support_voice_input' => false,
// 语音输入的提示信息
'voice_input_prompt' => [
'en' => 'Please click the microphone icon to start recording',
'zh_CN' => '请点击麦克风图标开始录音',
],
// 是否开启语音输入提示
'support_voice_input_prompt' => false,
// 输入文本内容提示
'text_input_prompt' => [
'en' => 'Please enter your problem',
'zh_CN' => '请输入您的问题',
],
// 输入的问题描述的字符长度限制
'max_char_length_for_problem' => 500,
// 是否支持显示更多工具面板
'tool_panel_config' => [
'enable' => false,
'title' => [
'en' => 'More Tools',
'zh_CN' => '更多功能',
],
'icon' => 'icon-more',
// 工具面板中的工具项
'tools' => [
'image' => [
'enable' => false,
'name' => [
'en' => 'Image',
'zh_CN' => '图片',
],
'description' => [
'en' => 'Upload image',
'zh_CN' => '上传图片',
],
'icon' => 'icon-image',
],
'video' => [
'enable' => false,
'name' => [
'en' => 'Video',
'zh_CN' => '视频',
],
'description' => [
'en' => 'Upload video',
'zh_CN' => '上传视频',
],
'icon' => 'icon-video',
],
'file' => [
'enable' => false,
'name' => [
'en' => 'File',
'zh_CN' => '文件',
],
'description' => [
'en' => 'Upload file',
'zh_CN' => '上传文件',
],
'icon' => 'icon-file',
],
'voice' => [
'enable' => false,
'name' => [
'en' => 'Voice',
'zh_CN' => '语音',
],
'description' => [
'en' => 'Voice input',
'zh_CN' => '语音输入',
],
'icon' => 'icon-voice',
],
'location' => [
'enable' => false,
'name' => [
'en' => 'Location',
'zh_CN' => '位置',
],
'description' => [
'en' => 'Location input',
'zh_CN' => '位置输入',
],
'icon' => 'icon-location',
],
],
]
];
}
/**
* 获得AI智能客服配置信息
* @param int $site_id 站点ID, 默认为1, 业务站点uniacid值与site_id保持一致
* @param string $app_module 应用模块, 默认为*, 表示所有应用模块都生效
* @return array
*/
public function getAIAgentServicesConfig($site_id = 1, $app_module = '*')
{
return $this->_getAIConfig($site_id, $app_module, 'AI_AGENT_SERVICES_CONFIG', $this->getCommonAIAgentServicesConfig());
}
/**
* 设置获取H5域名配置
* @param $data