临时保存

This commit is contained in:
2025-11-05 18:35:17 +08:00
parent 370e790d9d
commit 6bad32d9b1
9 changed files with 1039 additions and 46 deletions

102
docs/common/map.md Normal file
View File

@@ -0,0 +1,102 @@
# 这个文件在哪里被用到了,请给出详细的说明
我需要搜索代码库中对 map.html 文件的引用,以确定它在哪里被使用。
toolName: search_codebase
status: success
query: 查找对 /src/app/shop/view/config/map.html 文件的引用
我需要使用正则表达式进行更精确的搜索,查找对 map.html 文件的直接引用。
toolName: search_by_regex
status: success
query: shop/config/map
让我查看处理 'shop/config/map' 路由的控制器文件,以确定它是如何被使用的。
toolName: search_by_regex
status: success
query: class.*Config.*Controller|function.*map
我需要查看 Config.php 控制器中的 map() 方法实现,了解 map.html 文件是如何被使用的。
toolName: view_files
status: success
filePath: src/app/shop/controller/Config.php
`/src/app/shop/view/config/map.html` 文件在项目中主要用于店铺的地图配置功能。以下是详细说明:
## 文件用途
该文件是一个视图模板,用于展示和配置腾讯地图相关的设置,主要包括腾讯地图 KEY 的配置和手机端定位功能的启用/关闭。
## 使用方式
### 1. 控制器调用
该视图文件由 <mcfile name="Config.php" path="src/app/shop/controller/Config.php"></mcfile> 控制器中的 <mcsymbol name="map" filename="Config.php" path="src/app/shop/controller/Config.php" startline="168" type="function"></mcsymbol> 方法调用和渲染。当用户访问对应路由时,控制器会通过以下代码渲染该视图:
```php
return $this->fetch('config/map');
```
### 2. 菜单配置
**老配置**
在 <mcfile name="menu_shop.php" path="src/config/menu_shop.php"></mcfile> 文件中,该页面被注册为店铺后台的一个菜单项,位于"店铺设置" > "其他设置" > "地图配置",对应的路由为 `shop/config/map`
**最新配置**
现在关于菜单的处理全部放到数据库中_menu 表中, 查看配置处理
``` sql
-- auto-generated definition
create table lucky_menu
(
id int(11) unsigned auto_increment comment '菜单ID'
primary key,
app_module varchar(255) default 'admin' not null comment '应用模块',
addon varchar(255) default '' not null comment '所属插件',
title varchar(50) default '' not null comment '菜单标题',
name varchar(50) default '' not null comment '菜单关键字',
parent varchar(255) default '' not null comment '上级菜单',
level int default 1 not null comment '深度等级',
url varchar(255) default '' not null comment '链接地址',
is_show tinyint default 0 not null comment '是否展示',
sort int default 0 not null comment '排序(同级有效)',
`desc` varchar(255) default '' not null comment '描述',
is_icon tinyint default 0 not null comment '是否是矢量菜单图',
picture varchar(255) default '' not null comment '图片(矢量图)',
picture_select varchar(255) default '' not null comment '图片(矢量图)(选中)',
is_control tinyint default 1 not null comment '是否控制权限'
)
comment '菜单表' charset = utf8
row_format = DYNAMIC;
```
### 3. 其他页面引用
该配置页面在以下几个页面中被引用,作为地图配置的入口点:
- <mcfile name="local.html" path="src/app/shop/view/local/local.html"></mcfile>:当地址定位功能无法使用时,提供配置入口
- <mcfile name="contact.html" path="src/app/shop/view/shop/contact.html"></mcfile>:提供地图配置的入口(目前被注释掉)
## 功能实现
1. **数据提交**:通过 AJAX 提交表单数据到 `shop/config/map` 路由
2. **数据处理**:控制器接收数据后,调用 `ConfigModel` 的方法验证和保存地图配置
3. **配置存储**:配置信息存储在系统配置中,包括腾讯地图 KEY 和手机端定位开关状态
## 关联功能
该地图配置主要用于支持项目中的定位功能,特别是在门店地图展示、地址选择等场景中使用。

38
docs/common/menu.md Normal file
View File

@@ -0,0 +1,38 @@
# 菜单配置
系统的菜单配置全部放到数据库中_menu 表中
``` sql
-- auto-generated definition
create table lucky_menu
(
id int(11) unsigned auto_increment comment '菜单ID'
primary key,
app_module varchar(255) default 'admin' not null comment '应用模块',
addon varchar(255) default '' not null comment '所属插件',
title varchar(50) default '' not null comment '菜单标题',
name varchar(50) default '' not null comment '菜单关键字',
parent varchar(255) default '' not null comment '上级菜单',
level int default 1 not null comment '深度等级',
url varchar(255) default '' not null comment '链接地址',
is_show tinyint default 0 not null comment '是否展示',
sort int default 0 not null comment '排序(同级有效)',
`desc` varchar(255) default '' not null comment '描述',
is_icon tinyint default 0 not null comment '是否是矢量菜单图',
picture varchar(255) default '' not null comment '图片(矢量图)',
picture_select varchar(255) default '' not null comment '图片(矢量图)(选中)',
is_control tinyint default 1 not null comment '是否控制权限'
)
comment '菜单表' charset = utf8
row_format = DYNAMIC;
```
以 AI 配置菜单为例
```
INSERT INTO shop_mallnew.lucky_menu (id, app_module, addon, title, name, parent, level, url, is_show, sort, `desc`, is_icon, picture, picture_select, is_control) VALUES (2481, 'shop', '', 'AI智能', 'CONFIG_AI_PLATFORM', 'CONFIG_BASE', 3, 'shop/config/ai', 1, 99, '', 0, '', '', 1);
```
| id | app\_module | addon | title | name | parent | level | url | is\_show | sort | desc | is\_icon | picture | picture\_select | is\_control |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 2481 | shop | | AI智能 | CONFIG\_AI\_PLATFORM | CONFIG\_BASE | 3 | shop/config/ai | 1 | 99 | | 0 | | | 1 |

7
docs/common/password.md Normal file
View File

@@ -0,0 +1,7 @@
# 密码关系
| 密码明文 | 密码密文|
| --- | --- |
| shjs8888 | 3acce189dc4fb79af8750eda8ea7073a |
| admin123456789 | 29e6803d217472f3c0b2cd7f13f84ec9 |

12
docs/dev.md Normal file
View File

@@ -0,0 +1,12 @@
# 开发指引
## View模板中的定义
```
<!-- 例如在html模板中引入route.js MERCHANT_JS是一个动态变量会被替换为实际的路径 -->
<script src="MERCHANT_JS/route.js"></script>
```
这个变量是在 src\app\event\init\InitConfig.php 中定义的,会在系统初始化时被替换为实际的路径。

View File

@@ -25,7 +25,7 @@
**开发账号** **开发账号**
- 网址[http://localhost/shop/login/login.html](http://localhost/shop/login/login.html) - 网址[http://localhost/shop/login/login.html](http://localhost/shop/login/login.html)
- 测试账号:防爆电器 - 测试账号:制氧设备
- 密码shjs8888 - 密码shjs8888
## 功能概述 ## 功能概述

View File

@@ -126,6 +126,9 @@ class Config extends BaseApi
$copyright = $config_model->getCopyright($this->site_id, 'shop')[ 'data' ][ 'value' ]; $copyright = $config_model->getCopyright($this->site_id, 'shop')[ 'data' ][ 'value' ];
$map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ]; $map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
// AI智能客服配置信息
$aiagent_config = $config_model->getAIAgentServicesConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
$website_model = new SiteModel(); $website_model = new SiteModel();
$site_info = $website_model->getSiteInfo([ [ 'site_id', '=', $this->site_id ] ], 'site_id,site_domain,site_name,logo,seo_title,seo_keywords,seo_description,site_tel,logo_square')[ 'data' ]; $site_info = $website_model->getSiteInfo([ [ 'site_id', '=', $this->site_id ] ], 'site_id,site_domain,site_name,logo,seo_title,seo_keywords,seo_description,site_tel,logo_square')[ 'data' ];
@@ -148,7 +151,8 @@ class Config extends BaseApi
'servicer' => $servicer_info, 'servicer' => $servicer_info,
'shop_info'=>$shop_info, 'shop_info'=>$shop_info,
'store_config' => $this->store_data[ 'config' ], 'store_config' => $this->store_data[ 'config' ],
'map_config' => $map_config 'map_config' => $map_config,
'aiagent_config' => $aiagent_config,
]; ];
if (!empty($this->store_data[ 'store_info' ])) { if (!empty($this->store_data[ 'store_info' ])) {
$res[ 'store_info' ] = $this->store_data[ 'store_info' ]; $res[ 'store_info' ] = $this->store_data[ 'store_info' ];

View File

@@ -286,6 +286,208 @@ class Config extends BaseModel
return $res; return $res;
} }
/**
* 获取支持的AI平台类型
* @return array
*/
public function getSupportAIPlatformTypes()
{
return [
['value' => 'dify', 'label' => 'Dify'],
['value' => 'ragflow', 'label' => 'Ragflow'],
];
}
/**
* 设置AI第三平台提供的配置信息
* @$data
* @param int $site_id
* @param string $app_module
* @return array
*/
public function setAIPlatformConfig($data, $site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->setConfig($data, 'AI第三平台提供的配置信息', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'AI_PLATFORM_CONFIG' ] ]);
return $res;
}
/**
* 获取AI第三平台提供的配置信息
* @param int $site_id
* @param string $app_module
* @return array
*/
public function getAIPlatformConfig($site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'AI_PLATFORM_CONFIG' ] ]);
if (empty($res[ 'data' ][ 'value' ])) {
$id = time();
$res[ 'data' ][ 'value' ] = [
'default' => [ 'id' => $id, 'name'=> 'dify-demo' ],
'list' => [
// Dify Demo 版本,
['id' => $id, 'name' => 'dify-demo', 'type' => 'dify', 'type_label' => 'Dify', 'desc' => 'Dify Demo 版本', 'enable' => 1, 'api_url' => 'https://api.dify.cn', 'api_key' => '', 'create_time' => time()],
]
];
return $res;
}
return $res;
}
/**
* 设置AI智能客服配置信息
* @param $data 配置信息
* @param int $site_id
* @param string $app_module
* @return array
*/
public function setAIAgentServicesConfig($data, $site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->setConfig($data, 'AI配置信息', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'AI_AGENT_SERVICES_CONFIG' ] ]);
return $res;
}
/**
* 获得AI智能客服配置信息
* @param int $site_id
* @param string $app_module
* @return array
*/
public function getAIAgentServicesConfig($site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'AI_AGENT_SERVICES_CONFIG' ] ]);
if (empty($res[ 'data' ][ 'value' ])) {
$res[ 'data' ][ 'value' ] = [
// 是否开启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',
],
],
]
];
}
return $res;
}
/** /**
* 设置获取H5域名配置 * 设置获取H5域名配置
* @param $data * @param $data

View File

@@ -0,0 +1,617 @@
<!-- 页面样式定义 -->
<style>
.layui-card {
margin: 20px 0;
border-radius: 4px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.layui-card-header {
background-color: #f2f2f2;
padding: 12px 20px;
font-weight: 500;
border-bottom: 1px solid #e6e6e6;
}
.layui-card-body {
padding: 20px;
}
.layui-form-item {
margin-bottom: 20px;
}
.layui-field-title {
margin-top: 25px;
margin-bottom: 20px;
}
.layui-field-title legend {
padding: 0 10px;
font-size: 16px;
font-weight: 500;
}
.word-aux {
color: #999;
font-size: 12px;
margin-top: 5px;
display: block;
}
.required {
color: #f00;
margin-right: 4px;
}
.form-wrap {
padding: 20px;
background: #fff;
min-height: calc(100vh - 40px);
}
.lang-tabs {
margin-bottom: 20px;
}
.lang-content {
display: none;
}
.lang-content.active {
display: block;
}
.layui-form-label {
padding: 9px 15px;
width: 110px;
}
.layui-input-block {
margin-left: 110px;
}
.all-shop-information {
width: 100%;
background: white;
padding: 15px;
box-sizing: border-box;
margin-top: 15px;
margin-bottom: 30px;
}
.all-shop-information .all-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.all-shop-information .all-top .title {
color: #333333;
margin-bottom: 0;
font-size: 17px;
padding-left: 10px;
border-left: 3px solid var(--base-color);
box-sizing: border-box;
}
select[name="selected_platform"] + .layui-form-select {
min-width: 400px;
max-width: fit-content;
}
/* 扁平化表格样式 */
.layui-table {
margin: 10px 0;
border-radius: 0;
box-shadow: none;
}
.layui-table th {
font-weight: 400;
background-color: #f5f7fa;
border-bottom: 1px solid #e6e8eb;
text-align: center;
}
.layui-table td {
vertical-align: top;
border-bottom: 1px solid #e6e8eb;
padding: 12px 15px;
}
.layui-table tbody tr:hover {
background-color: #f5f7fa;
}
/* 调整类型列宽度 */
.layui-table th:nth-child(2),
.layui-table td:nth-child(2) {
width: 120px;
}
/* 调整输入框样式 */
.layui-table-edit {
width: calc(100% - 4px);
border-radius: 2px;
border: 1px solid #dcdfe6;
transition: border-color 0.2s;
/* 确保输入框和选择框垂直居中对齐 */
line-height: 30px;
padding: 0 10px;
box-sizing: border-box;
margin: 4px;
margin-top: 12px;
height: 34px;
}
.layui-table-edit:focus {
border-color: #c0c4cc;
outline: none;
}
.layui-table td select.layui-select {
height: 30px;
line-height: 30px;
padding: 0 10px;
box-sizing: border-box;
}
/* 调整操作列宽度 */
.layui-table th:last-child,
.layui-table td:last-child {
width: 120px;
white-space: nowrap;
overflow: hidden;
}
/* 按钮图标样式 */
.btn-icon {
width: 28px;
height: 28px;
line-height: 28px;
padding: 0;
text-align: center;
margin: 0 2px;
font-size: 14px;
}
</style>
<div class="layui-form">
<!-- 根据功能分两个Tab进行配置一个是AI智能客服一个是AI平台 -->
<div class="layui-tab" lay-filter="mainTab">
<ul class="layui-tab-title">
<li class="layui-this" lay-id="ai_agent">AI智能客服</li>
<li lay-id="ai_platform">AI服务平台</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<!-- AI智能客服配置 -->
<div class="layui-form form-wrap card-common">
<!-- 基础设置 -->
<fieldset class="layui-elem-field layui-field-title">
<legend>基础设置</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">启用状态</label>
<div class="layui-input-block">
<input type="checkbox" name="enable" lay-skin="switch" lay-text="开启|关闭" {if
condition="isset($agent_info) && $agent_info.enable" }checked{/if}>
</div>
</div>
<!-- 语言切换 -->
<div class="layui-form-item">
<div class="layui-tab lang-tabs" lay-filter="langTab">
<ul class="layui-tab-title">
<li class="layui-this" lay-id="zh_CN">简体中文</li>
<li lay-id="en">English</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="layui-form-item">
<label class="layui-form-label">AI客服姓名</label>
<div class="layui-input-block">
<input type="text" name="ai_name[zh_CN]" placeholder="请输入AI客服姓名"
class="layui-input" value="{$agent_info.ai_name.zh_CN|default=''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">AI客服头像</label>
<div class="layui-input-block">
<input type="text" name="ai_avatar[zh_CN]" placeholder="请输入AI客服头像URL"
class="layui-input" value="{$agent_info.ai_avatar.zh_CN|default=''}">
<div class="word-aux">支持JPG、PNG、GIF格式建议尺寸100x100px</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">用户头像</label>
<div class="layui-input-block">
<input type="text" name="user_avatar[zh_CN]" placeholder="请输入用户头像URL"
class="layui-input" value="{$agent_info.user_avatar.zh_CN|default=''}">
<div class="word-aux">支持JPG、PNG、GIF格式建议尺寸100x100px</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">欢迎语</label>
<div class="layui-input-block">
<textarea name="welcome_messages[zh_CN]" placeholder="请输入欢迎语,每行一条"
class="layui-textarea" rows="4">{if isset($agent_info.welcome_messages.zh_CN)}{foreach $agent_info.welcome_messages.zh_CN as $msg}{$msg}
{/foreach}{else}您好,我是智能客服助手,有什么可以帮助您的吗?{/if}</textarea>
<!-- <div class="word-aux">每行一条欢迎语,系统会随机选择一条显示</div> -->
</div>
</div>
</div>
<div class="layui-tab-item">
<div class="layui-form-item">
<label class="layui-form-label">AI Name</label>
<div class="layui-input-block">
<input type="text" name="ai_name[en]" placeholder="Please enter AI name"
class="layui-input" value="{$agent_info.ai_name.en|default=''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">AI Avatar</label>
<div class="layui-input-block">
<input type="text" name="ai_avatar[en]"
placeholder="Please enter AI avatar URL" class="layui-input"
value="{$agent_info.ai_avatar.en|default=''}">
<div class="word-aux">Support JPG, PNG, GIF formats, recommended size:
100x100px</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">User Avatar</label>
<div class="layui-input-block">
<input type="text" name="user_avatar[en]"
placeholder="Please enter user avatar URL" class="layui-input"
value="{$agent_info.user_avatar.en|default=''}">
<div class="word-aux">Support JPG, PNG, GIF formats, recommended size:
100x100px</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Welcome Messages</label>
<div class="layui-input-block">
<textarea name="welcome_messages[en]"
placeholder="Please enter welcome messages, one per line"
class="layui-textarea" rows="4">{if isset($agent_info.welcome_messages.en)}{foreach $agent_info.welcome_messages.en as $msg}{$msg}
{/foreach}{else}Hello, I'm the AI customer service assistant. How can I help you?{/if}</textarea>
<!-- <div class="word-aux">One welcome message per line, the system will randomly select one to display</div> -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 显示设置 -->
<fieldset class="layui-elem-field layui-field-title">
<legend>显示设置</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">显示加载更多按钮</label>
<div class="layui-input-block">
<input type="checkbox" name="show_load_more_button" lay-skin="switch" lay-text="开启|关闭" {if
condition="isset($agent_info) && $agent_info.show_load_more_button"
}checked{else}checked{/if}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">最大消息数量</label>
<div class="layui-input-inline" style="width: 100px;">
<input type="number" name="max_messages" value="{$agent_info.max_messages|default='100'}"
class="layui-input" min="10" max="500">
</div>
<div class="layui-form-mid"></div>
<div class="word-aux" style="margin-left: 110px;">建议设置在10-500条之间</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">启用流式响应</label>
<div class="layui-input-block">
<input type="checkbox" name="stream_mode" lay-skin="switch" lay-text="开启|关闭" {if
condition="isset($agent_info) && $agent_info.stream_mode" }checked{else}checked{/if}>
</div>
</div>
</div>
</div>
<div class="layui-tab-item" lay-id="ai_platform">
<!-- AI平台配置 -->
<div class="layui-form form-wrap card-common">
<!-- 平台选择 -->
<fieldset class="layui-elem-field layui-field-title">
<legend>基本设置</legend>
</fieldset>
<div class="layui-form-item">
<label class="layui-form-label">默认平台</label>
<div class="layui-input-block">
<select name="selected_platform" lay-filter="platformSelect">
<option value="">请选择要默认使用的AI服务平台</option>
{if isset($enable_platform_list) && !empty($enable_platform_list)}
{foreach $enable_platform_list as $platform}
<option value="{$platform.id}">{$platform.name}</option>
{/foreach}
{/if}
</select>
</div>
</div>
<!-- 平台配置表格 -->
<fieldset class="layui-elem-field layui-field-title">
<legend>AI服务平台配置</legend>
</fieldset>
<div class="layui-form-item">
<table class="layui-table" lay-even lay-skin="line">
<thead>
<tr>
<th>名称</th>
<th>类型</th>
<th>API URL</th>
<th>API Key</th>
<th>操作</th>
</tr>
</thead>
<tbody id="platformTable">
{if isset($platform_list) && !empty($platform_list)}
{foreach $platform_list as $platform}
<tr data-id="{$platform.id}">
<td>
<input type="text" name="platform_name[{$platform.id}]" value="{$platform.name}"
class="layui-input layui-table-edit" placeholder="请输入AI服务平台名称">
</td>
<td>
<select name="platform_type[{$platform.id}]" class="layui-select layui-table-edit">
{foreach $support_ai_platform_types as $item}
<option value="{$item.value}" {if $platform.type == $item.value}selected{/if}>{$item.label}</option>
{/foreach}
</select>
</td>
<td>
<input type="text" name="platform_api_url[{$platform.id}]" value="{$platform.api_url}"
class="layui-input layui-table-edit" placeholder="请输入API URL">
</td>
<td>
<input type="text" name="platform_api_key[{$platform.id}]" value="{$platform.api_key}"
class="layui-input layui-table-edit" placeholder="请输入API Key">
</td>
<td class="layui-row">
<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs layui-btn-danger btn-icon delete-platform" data-id="{$platform.id}" title="删除">
<i class="layui-icon layui-icon-delete"></i>
</button>
<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs layui-btn-warm btn-icon toggle-platform" data-id="{$platform.id}" data-status="{if $platform.enable === 1}1{else}0{/if}" title="{if $platform.enable === 1}禁用{else}开启{/if}">
{if $platform.enable === 1}<i class="layui-icon layui-icon-radio"></i>{else}<i class="layui-icon layui-icon-circle"></i>{/if}
</button>
<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs btn-icon save-platform" data-id="{$platform.id}" title="保存">
<i class="layui-icon layui-icon-ok"></i>
</button>
</td>
</tr>
{/foreach}
{else}
<tr>
<td colspan="5" style="text-align: center;">暂无平台配置</td>
</tr>
{/if}
</tbody>
</table>
</div>
<!-- 添加新平台 -->
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-block">
<button class="layui-btn" id="addPlatform">添加平台</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 页面脚本 -->
<script>
layui.use(['form', 'layer', 'element'], function () {
var form = layui.form;
var layer = layui.layer;
var element = layui.element;
// 初始化表单
form.render();
// layui 2.5.5版本需要手动初始化Tab组件
element.render('tab');
// 主Tab切换处理
element.on('tab(mainTab)', function (data) { });
// 语言切换 - 使用layui原生的Tab切换不再需要自定义逻辑
element.on('tab(langTab)', function (data) { });
// 平台选择下拉框处理
form.on('select(platformSelect)', function(data) {
var platformId = data.value;
if (platformId) {
// 可以在这里添加根据平台ID高亮显示对应表格行的逻辑
$('#platformTable tr').removeClass('layui-bg-blue');
$('#platformTable tr[data-id="' + platformId + '"]').addClass('layui-bg-blue');
}
});
// 保存平台配置
$(document).on('click', '.save-platform', function() {
var platformId = $(this).data('id');
var name = $('input[name="platform_name[' + platformId + ']"]').val();
var type = $('select[name="platform_type[' + platformId + ']"]').val();
var apiUrl = $('input[name="platform_api_url[' + platformId + ']"]').val();
var apiKey = $('input[name="platform_api_key[' + platformId + ']"]').val();
if (!name) {
layer.msg('平台名称不能为空', {icon: 2});
return;
}
if (!type) {
layer.msg('请选择平台类型', {icon: 2});
return;
}
if (!apiUrl) {
layer.msg('API URL不能为空', {icon: 2});
return;
}
if (!apiKey) {
layer.msg('API Key不能为空', {icon: 2});
return;
}
// 这里应该是AJAX请求保存数据
// 模拟保存成功并获取新的平台ID
var newPlatformId = platformId.startsWith('temp_') ? 'new_' + new Date().getTime() : platformId;
// 更新行的data-id属性
$('#platformTable tr[data-id="' + platformId + '"]').attr('data-id', newPlatformId);
// 更新表单元素的name属性中的ID
$('#platformTable tr[data-id="' + newPlatformId + '"] input, #platformTable tr[data-id="' + newPlatformId + '"] select').each(function() {
var oldName = $(this).attr('name');
var newName = oldName.replace(platformId, newPlatformId);
$(this).attr('name', newName);
});
// 更新按钮的data-id属性
$('#platformTable tr[data-id="' + newPlatformId + '"] button').data('id', newPlatformId);
// 更新默认平台下拉框
var select = $('select[name="selected_platform"]');
// 检查是否已存在相同ID的选项
if (select.find('option[value="' + newPlatformId + '"]').length === 0) {
select.append('<option value="' + newPlatformId + '">' + name + '</option>');
form.render('select'); // 重新渲染select
}
// 显示保存成功提示
layer.msg('保存成功', {icon: 1});
});
// 删除平台
$(document).on('click', '.delete-platform', function() {
var platformId = $(this).data('id');
layer.confirm('确定要删除这个平台配置吗?', {
btn: ['确定', '取消']
}, function(index) {
// 删除行
$('#platformTable tr[data-id="' + platformId + '"]').remove();
// 从下拉框中移除对应的选项
$('select[name="selected_platform"] option[value="' + platformId + '"]').remove();
form.render('select');
// 检查表格是否为空,如果为空则显示提示
if ($('#platformTable tr').length === 0) {
$('#platformTable').append('<tr><td colspan="5" style="text-align: center;">暂无平台配置</td></tr>');
}
layer.close(index);
layer.msg('删除成功', {icon: 1});
});
});
// 禁用/开启平台
$(document).on('click', '.toggle-platform', function() {
var platformId = $(this).data('id');
var status = $(this).data('status');
var newStatus = status === 1 ? 0 : 1;
// 更新按钮状态
$(this).data('status', newStatus);
$(this).html(newStatus === 1 ? '<i class="layui-icon layui-icon-radio"></i>' : '<i class="layui-icon layui-icon-circle"></i>');
$(this).attr('title', newStatus === 1 ? '开启' : '禁用');
// 如果平台被禁用,从默认平台下拉框中移除
if (newStatus === 0) {
var option = $('select[name="selected_platform"] option[value="' + platformId + '"]');
if (option.length > 0) {
option.detach().data('disabled', true); // 保存选项但不显示
form.render('select');
}
}
// 如果平台被启用,将选项添加回下拉框
else {
var savedOption = $('select[name="selected_platform"] option[data-disabled="true"][value="' + platformId + '"]');
if (savedOption.length === 0) {
// 如果没有保存的选项,获取平台名称并创建新选项
var platformName = $('#platformTable tr[data-id="' + platformId + '"] input[name^="platform_name"]').val();
if (platformName) {
$('select[name="selected_platform"]').append('<option value="' + platformId + '">' + platformName + '</option>');
form.render('select');
}
} else {
savedOption.removeData('disabled').appendTo('select[name="selected_platform"]');
form.render('select');
}
}
layer.msg(newStatus === 1 ? '已开启' : '已禁用', {icon: 1});
});
// 添加新平台
$('#addPlatform').on('click', function() {
// 生成一个临时ID
var tempId = 'temp_' + new Date().getTime();
// 创建新行HTML
var newRow = '<tr data-id="' + tempId + '">' +
'<td>' +
'<input type="text" name="platform_name[' + tempId + ']" ' +
'class="layui-input layui-table-edit" placeholder="请输入AI服务平台名称">' +
'</td>' +
'<td>' +
'<select name="platform_type[' + tempId + ']" class="layui-select layui-table-edit">' +
'{foreach $support_ai_platform_types as $type}' +
'<option value="{$type.value}">{$type.label}</option>' +
'{/foreach}' +
'</select>' +
'</td>' +
'<td>' +
'<input type="text" name="platform_api_url[' + tempId + ']" ' +
'class="layui-input layui-table-edit" placeholder="请输入API URL">' +
'</td>' +
'<td>' +
'<input type="text" name="platform_api_key[' + tempId + ']" ' +
'class="layui-input layui-table-edit" placeholder="请输入API Key">' +
'</td>' +
'<td class="layui-row">' +
'<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs btn-icon delete-platform" data-id="' + tempId + '" title="删除">' +
'<i class="layui-icon layui-icon-delete"></i>' +
'</button>' +
'<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs btn-icon toggle-platform" data-id="' + tempId + '" data-status="0" title="开启">'+
'<i class="layui-icon layui-icon-circle"></i>' +
'</button>' +
'<button class="layui-col-xs4 layui-col-sm12 layui-col-md4 layui-btn layui-btn-xs btn-icon save-platform" data-id="' + tempId + '" title="保存">' +
'<i class="layui-icon layui-icon-ok"></i>' +
'</button>' +
'</td>' +
'</tr>'
// 检查是否有暂无平台配置的提示行
var emptyRow = $('#platformTable tr:has(td[colspan="5"])');
if (emptyRow.length > 0) {
emptyRow.replaceWith(newRow);
} else {
$('#platformTable').append(newRow);
}
// 重新渲染表单元素
form.render();
// 聚焦到新添加的行的第一个输入框
$('input[name="platform_name[' + tempId + ']"]').focus();
});
});
</script>

View File

@@ -2509,6 +2509,17 @@ return [
], ],
], ],
], ],
[
'name'=> 'CONFIG_AI_PLATFORM',
'title' => 'AI智能客服配置',
'url'=> 'shop/config/ai',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
'sort' => 1,
],
[ [
'name' => 'CONFIG_BASE_ORDER', 'name' => 'CONFIG_BASE_ORDER',
'title' => '交易设置', 'title' => '交易设置',