Compare commits
50
Commits
89d7761887
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4eab9ad89 | ||
|
|
2a6b14f698 | ||
|
|
9281c1dc35 | ||
|
|
d30a2531a7 | ||
|
|
b3a25ceb82 | ||
|
|
14c305f518 | ||
|
|
a7908e0677 | ||
|
|
bf21006d4e | ||
|
|
1f8d876cef | ||
|
|
e46a4100c7 | ||
|
|
f134b0e759 | ||
|
|
5dffe62adc | ||
|
|
98156991c1 | ||
|
|
7cdb591f69 | ||
|
|
c00229f2ee | ||
|
|
e27cc8f457 | ||
|
|
e09b4c639c | ||
|
|
bf0daf987b | ||
|
|
4cbc52c51b | ||
|
|
99fc99f8ad | ||
|
|
21480f43b1 | ||
|
|
050d1adc0b | ||
|
|
f80e1f71d4 | ||
|
|
bfa5292962 | ||
|
|
1e8b6fe77d | ||
|
|
67244496f1 | ||
|
|
c389fec971 | ||
|
|
25e3923ad3 | ||
|
|
63e9cb5c48 | ||
|
|
0bf9b77aed | ||
|
|
0ed654b5b8 | ||
|
|
badc502fbb | ||
|
|
776aacfa2e | ||
|
|
a32b1656b0 | ||
|
|
27819199a4 | ||
|
|
0b6a7d0efb | ||
|
|
399d61e2f2 | ||
|
|
36fe5e2ab9 | ||
|
|
516c043924 | ||
|
|
769d595e30 | ||
|
|
7826025d42 | ||
|
|
85e52cea87 | ||
|
|
581738da6e | ||
|
|
5e997747c5 | ||
|
|
59b3a10d77 | ||
|
|
9e6a6bd9fe | ||
|
|
878e2dbcac | ||
|
|
18dfebf0de | ||
|
|
743d8d9ddf | ||
|
|
aa2612bcb9 |
@@ -1,11 +0,0 @@
|
|||||||
APP_DEBUG = true
|
|
||||||
|
|
||||||
DB_TYPE = mysql
|
|
||||||
DB_HOST = 10.168.1.239
|
|
||||||
DB_NAME = official_website
|
|
||||||
DB_USER = official
|
|
||||||
DB_PASS = meitian@#!
|
|
||||||
DB_PORT = 3306
|
|
||||||
DB_CHARSET = utf8
|
|
||||||
|
|
||||||
DEFAULT_LANG = zh-cn
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
runtime
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
@@ -22,3 +23,9 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.example.env
|
||||||
|
|
||||||
|
public\storage
|
||||||
-100
@@ -1,100 +0,0 @@
|
|||||||
# Redis 配置说明
|
|
||||||
|
|
||||||
## 1. 安装 Redis 扩展
|
|
||||||
|
|
||||||
在项目根目录执行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require predis/predis
|
|
||||||
```
|
|
||||||
|
|
||||||
或者如果使用 phpredis 扩展(需要 PHP Redis 扩展):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 确保已安装 PHP Redis 扩展
|
|
||||||
# 然后直接使用,无需 composer 安装
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 配置环境变量
|
|
||||||
|
|
||||||
在项目根目录创建 `.env` 文件(如果不存在),添加以下配置:
|
|
||||||
|
|
||||||
```env
|
|
||||||
# Redis 配置
|
|
||||||
REDIS_HOST=127.0.0.1
|
|
||||||
REDIS_PORT=6379
|
|
||||||
REDIS_PASSWORD=
|
|
||||||
REDIS_DB=0
|
|
||||||
REDIS_PREFIX=
|
|
||||||
|
|
||||||
# 缓存配置
|
|
||||||
CACHE_DRIVER=redis
|
|
||||||
|
|
||||||
# Session 配置
|
|
||||||
SESSION_DRIVER=redis
|
|
||||||
SESSION_PREFIX=
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. 配置文件说明
|
|
||||||
|
|
||||||
### cache.php
|
|
||||||
- 默认缓存驱动已设置为 `redis`
|
|
||||||
- Redis 连接配置已添加
|
|
||||||
|
|
||||||
### session.php
|
|
||||||
- Session 驱动已设置为 `redis`
|
|
||||||
- 使用 Redis 存储 Session
|
|
||||||
|
|
||||||
## 4. 使用说明
|
|
||||||
|
|
||||||
### 缓存使用
|
|
||||||
```php
|
|
||||||
use think\facade\Cache;
|
|
||||||
|
|
||||||
// 设置缓存
|
|
||||||
Cache::set('key', 'value', 3600);
|
|
||||||
|
|
||||||
// 获取缓存
|
|
||||||
$value = Cache::get('key');
|
|
||||||
|
|
||||||
// 删除缓存
|
|
||||||
Cache::delete('key');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Session 使用
|
|
||||||
```php
|
|
||||||
use think\facade\Session;
|
|
||||||
|
|
||||||
// 设置 Session
|
|
||||||
Session::set('key', 'value');
|
|
||||||
|
|
||||||
// 获取 Session
|
|
||||||
$value = Session::get('key');
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. 验证 Redis 连接
|
|
||||||
|
|
||||||
确保 Redis 服务已启动:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Windows
|
|
||||||
redis-server
|
|
||||||
|
|
||||||
# Linux/Mac
|
|
||||||
sudo systemctl start redis
|
|
||||||
# 或
|
|
||||||
redis-server
|
|
||||||
```
|
|
||||||
|
|
||||||
测试连接:
|
|
||||||
```bash
|
|
||||||
redis-cli ping
|
|
||||||
# 应该返回 PONG
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. 注意事项
|
|
||||||
|
|
||||||
1. 如果 Redis 未安装或连接失败,可以临时将 `CACHE_DRIVER` 和 `SESSION_DRIVER` 改回 `file`
|
|
||||||
2. Redis 密码如果为空,可以不设置 `REDIS_PASSWORD`
|
|
||||||
3. `REDIS_PREFIX` 用于区分不同项目的缓存,建议设置
|
|
||||||
|
|
||||||
@@ -187,4 +187,15 @@ abstract class BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户的 tid
|
||||||
|
*
|
||||||
|
* @return int 租户ID
|
||||||
|
*/
|
||||||
|
protected function getTenantId(): int
|
||||||
|
{
|
||||||
|
$userInfo = $this->getAdminUserInfo();
|
||||||
|
return isset($userInfo['tid']) ? intval($userInfo['tid']) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,417 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\BabyHealth;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\AppsBabyhealthBabys;
|
||||||
|
use app\model\AppsBabyhealthUsers;
|
||||||
|
|
||||||
|
|
||||||
|
class BabysController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取宝贝信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getBabyList()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$babylist = AppsBabyhealthBabys::where('delete_time', null)
|
||||||
|
->field('id, name, nickname, sex, avatar, birth, father, mother, height, weight, status, create_time, update_time')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 查询每个宝贝的父母名称
|
||||||
|
foreach ($babylist as &$baby) {
|
||||||
|
$parentNames = $this->findParentNames(
|
||||||
|
(int)($baby['father'] ?? 0),
|
||||||
|
(int)($baby['mother'] ?? 0)
|
||||||
|
);
|
||||||
|
$baby['father'] = $parentNames['father_name'];
|
||||||
|
$baby['mother'] = $parentNames['mother_name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '获取宝贝信息', ['data' => $babylist]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $babylist
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '获取宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建宝贝信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function createBaby()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取请求参数
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 准备宝贝数据
|
||||||
|
$babyData = [
|
||||||
|
'name' => $data['name'],
|
||||||
|
'nickname' => $data['nickname'],
|
||||||
|
'sex' => $data['sex'],
|
||||||
|
'birth' => $data['birth'],
|
||||||
|
'height' => $data['height'],
|
||||||
|
'weight' => $data['weight'],
|
||||||
|
'avatar' => $data['avatar'],
|
||||||
|
'status' => $data['status'],
|
||||||
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 创建宝贝信息
|
||||||
|
$result = AppsBabyhealthBabys::insertGetId($babyData);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '创建宝贝信息', ['id' => $result]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => ['id' => $result]
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '创建宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '创建宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑宝贝信息
|
||||||
|
* @param int $id Baby ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editBaby(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取请求参数
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 检查宝贝信息是否存在
|
||||||
|
$baby = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '宝贝信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备更新数据
|
||||||
|
$updateData = [
|
||||||
|
'name' => $data['name'],
|
||||||
|
'nickname' => $data['nickname'],
|
||||||
|
'sex' => $data['sex'],
|
||||||
|
'birth' => $data['birth'],
|
||||||
|
'height' => $data['height'],
|
||||||
|
'weight' => $data['weight'],
|
||||||
|
'avatar' => $data['avatar'],
|
||||||
|
'status' => $data['status'],
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 执行更新
|
||||||
|
AppsBabyhealthBabys::where('id', $id)->update($updateData);
|
||||||
|
|
||||||
|
// 获取更新后的宝贝信息
|
||||||
|
$updatedBaby = AppsBabyhealthBabys::where('id', $id)->find();
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '更新宝贝信息', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $updatedBaby ? $updatedBaby->toArray() : []
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '更新宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '更新宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除宝贝信息
|
||||||
|
* @param int $id Baby ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteBaby(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 检查宝贝信息是否存在
|
||||||
|
$baby = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '宝贝信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逻辑删除宝贝信息
|
||||||
|
$result = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update([
|
||||||
|
'delete_time' => date('Y-m-d H:i:s'),
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '删除宝贝信息', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '删除宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预览宝贝信息
|
||||||
|
* @param int $id Baby ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getBabyDetail(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 查询宝贝信息
|
||||||
|
$baby = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '宝贝信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-宝贝管理', '获取宝贝信息', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $baby->toArray()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-宝贝管理', '获取宝贝信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定父母
|
||||||
|
* @param int $id Baby ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function bindParent(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取请求参数(支持POST)
|
||||||
|
$data = $this->request->post();
|
||||||
|
|
||||||
|
// 检查宝贝信息是否存在
|
||||||
|
$baby = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '宝贝信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备更新数据
|
||||||
|
$updateData = [
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 更新父亲ID
|
||||||
|
if (isset($data['father_id'])) {
|
||||||
|
$updateData['father_id'] = $data['father_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新母亲ID
|
||||||
|
if (isset($data['mother_id'])) {
|
||||||
|
$updateData['mother_id'] = $data['mother_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行更新
|
||||||
|
AppsBabyhealthBabys::where('id', $id)->update($updateData);
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '绑定父母', ['id' => $id, 'father_id' => $data['father_id'] ?? null, 'mother_id' => $data['mother_id'] ?? null]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '绑定成功'
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '绑定父母', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '绑定失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取父母名称
|
||||||
|
* @param int $id 宝贝ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getParents(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 查询宝贝的父母ID
|
||||||
|
$baby = AppsBabyhealthBabys::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->field('father, mother')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '宝贝信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取父母名称
|
||||||
|
$parentNames = $this->findParentNames(
|
||||||
|
(int)($baby['father'] ?? 0),
|
||||||
|
(int)($baby['mother'] ?? 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝管理', '获取父母信息', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'father_id' => $baby['father'] ?? null,
|
||||||
|
'mother_id' => $baby['mother'] ?? null,
|
||||||
|
'father' => $parentNames['father_name'],
|
||||||
|
'mother' => $parentNames['mother_name']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝管理', '获取父母信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找父母名称
|
||||||
|
* @param int $father 父亲ID
|
||||||
|
* @param int $mother 母亲ID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findParentNames(int $father = 0, int $mother = 0): array
|
||||||
|
{
|
||||||
|
$result = [
|
||||||
|
'father_name' => '',
|
||||||
|
'mother_name' => ''
|
||||||
|
];
|
||||||
|
|
||||||
|
// 查询父亲名称
|
||||||
|
if ($father > 0) {
|
||||||
|
$father = \app\model\AppsBabyhealthUsers::where('id', $father)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->field('name')
|
||||||
|
->find();
|
||||||
|
if ($father) {
|
||||||
|
$result['father_name'] = $father['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询母亲名称
|
||||||
|
if ($mother > 0) {
|
||||||
|
$mother = \app\model\AppsBabyhealthUsers::where('id', $mother)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->field('name')
|
||||||
|
->find();
|
||||||
|
if ($mother) {
|
||||||
|
$result['mother_name'] = $mother['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\BabyHealth;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\AppsBabyhealthBabys;
|
||||||
|
use app\model\AppsBabyhealthUsers;
|
||||||
|
|
||||||
|
class DashboradController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* dashborad总体输出
|
||||||
|
*/
|
||||||
|
public function getDashborad()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'userCounts' => $this->getUserCounts(),
|
||||||
|
'babyCounts' => $this->getBabyCounts()
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计宝贝数量
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getBabyCounts(): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 总数
|
||||||
|
$total = AppsBabyhealthBabys::where('delete_time', null)->count();
|
||||||
|
|
||||||
|
// 男宝宝数 (sex = 1)
|
||||||
|
$maleCount = AppsBabyhealthBabys::where('delete_time', null)->where('sex', 1)->count();
|
||||||
|
|
||||||
|
// 女宝宝数 (sex = 2)
|
||||||
|
$femaleCount = AppsBabyhealthBabys::where('delete_time', null)->where('sex', 2)->count();
|
||||||
|
|
||||||
|
// 未知性别 (sex = 0)
|
||||||
|
$unknownCount = AppsBabyhealthBabys::where('delete_time', null)->where('sex', 0)->count();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'total' => $total,
|
||||||
|
'male' => $maleCount,
|
||||||
|
'female' => $femaleCount,
|
||||||
|
'unknown' => $unknownCount
|
||||||
|
];
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 返回空数组而不是抛出异常,让外层处理
|
||||||
|
error_log('统计宝贝数量失败: ' . $e->getMessage());
|
||||||
|
return [
|
||||||
|
'total' => 0,
|
||||||
|
'male' => 0,
|
||||||
|
'female' => 0,
|
||||||
|
'unknown' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计用户数量
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getUserCounts(): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 总数
|
||||||
|
$total = AppsBabyhealthUsers::where('delete_time', null)->count();
|
||||||
|
|
||||||
|
// 父亲 (sex = 1)
|
||||||
|
$fatherCount = AppsBabyhealthUsers::where('delete_time', null)->where('sex', 1)->count();
|
||||||
|
|
||||||
|
// 母亲 (sex = 2)
|
||||||
|
$motherCount = AppsBabyhealthUsers::where('delete_time', null)->where('sex', 2)->count();
|
||||||
|
|
||||||
|
// 未知性别 (sex = 0)
|
||||||
|
$unknownCount = AppsBabyhealthUsers::where('delete_time', null)->where('sex', 0)->count();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'total' => $total,
|
||||||
|
'father' => $fatherCount,
|
||||||
|
'mother' => $motherCount,
|
||||||
|
'unknown' => $unknownCount
|
||||||
|
];
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 返回空数组而不是抛出异常,让外层处理
|
||||||
|
error_log('统计用户数量失败: ' . $e->getMessage());
|
||||||
|
return [
|
||||||
|
'total' => 0,
|
||||||
|
'father' => 0,
|
||||||
|
'mother' => 0,
|
||||||
|
'unknown' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\BabyHealth;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\AppsBabyhealthUsers;
|
||||||
|
|
||||||
|
class UserController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getUserList()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$babylist = AppsBabyhealthUsers::where('delete_time', null)
|
||||||
|
->field('id, account, phone, email, name, sex, avatar, birth, status, create_time, update_time')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-用户管理', '获取用户信息', ['data' => $babylist]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $babylist
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '获取用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建用户信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function createUser()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取请求参数
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
// 准备用户数据,密码进行 MD5 加密
|
||||||
|
$babyData = [
|
||||||
|
'account' => $data['account'],
|
||||||
|
'password' => !empty($data['password']) ? md5($data['password']) : '',
|
||||||
|
'name' => $data['name'],
|
||||||
|
'sex' => $data['sex'],
|
||||||
|
'birth' => $data['birth'],
|
||||||
|
'phone' => $data['phone'],
|
||||||
|
'email' => $data['email'],
|
||||||
|
'avatar' => $data['avatar'],
|
||||||
|
'status' => $data['status'],
|
||||||
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 创建用户信息
|
||||||
|
$result = AppsBabyhealthUsers::insertGetId($babyData);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-用户管理', '创建用户信息', ['id' => $result]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => ['id' => $result]
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '创建用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '创建用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑用户信息
|
||||||
|
* @param int $id User ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function updateUser(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取请求参数
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
// 检查用户信息是否存在
|
||||||
|
$baby = AppsBabyhealthUsers::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备更新数据
|
||||||
|
$updateData = [
|
||||||
|
'name' => $data['name'],
|
||||||
|
'sex' => $data['sex'],
|
||||||
|
'birth' => $data['birth'],
|
||||||
|
'phone' => $data['phone'],
|
||||||
|
'email' => $data['email'],
|
||||||
|
'avatar' => $data['avatar'],
|
||||||
|
'status' => $data['status'],
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 执行更新
|
||||||
|
AppsBabyhealthUsers::where('id', $id)->update($updateData);
|
||||||
|
|
||||||
|
// 获取更新后的用户信息
|
||||||
|
$updatedBaby = AppsBabyhealthUsers::where('id', $id)->find();
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-用户管理', '更新用户信息', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $updatedBaby ? $updatedBaby->toArray() : []
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '更新用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '更新用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户信息
|
||||||
|
* @param int $id User ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteUser(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 检查用户信息是否存在
|
||||||
|
$baby = AppsBabyhealthUsers::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逻辑删除用户信息
|
||||||
|
$result = AppsBabyhealthUsers::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update([
|
||||||
|
'delete_time' => date('Y-m-d H:i:s'),
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-用户管理', '删除用户信息', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '删除用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预览用户信息
|
||||||
|
* @param int $id User ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getUserDetail(int $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 查询用户信息
|
||||||
|
$baby = AppsBabyhealthUsers::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$baby) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户信息不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('宝贝监护-用户管理', '获取用户信息', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $baby->toArray()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('宝贝监护-用户管理', '获取用户信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-69
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\Cms\Analytics;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use app\model\Articles;
|
use app\model\Cms\Articles;
|
||||||
use app\model\ArticlesCategory;
|
use app\model\Cms\ArticlesCategory;
|
||||||
use app\model\AdminUser;
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
class AnalyticsController extends BaseController
|
class AnalyticsController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -23,80 +23,47 @@ class AnalyticsController extends BaseController
|
|||||||
public function getContentStats()
|
public function getContentStats()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$today = date('Y-m-d');
|
|
||||||
$yesterday = date('Y-m-d', strtotime('-1 day'));
|
$yesterday = date('Y-m-d', strtotime('-1 day'));
|
||||||
$monthStart = date('Y-m-01');
|
$monthStart = date('Y-m-01');
|
||||||
$yesterdayMonthStart = date('Y-m-01', strtotime('-1 day'));
|
|
||||||
$monthEnd = date('Y-m-t 23:59:59');
|
$monthEnd = date('Y-m-t 23:59:59');
|
||||||
|
|
||||||
// 总发布量
|
// 总发布量
|
||||||
$totalArticles = Articles::where('delete_time', null)
|
$totalArticles = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
// 昨日总发布量
|
// 昨日新增发布
|
||||||
$yesterdayTotalArticles = Articles::where('delete_time', null)
|
$yesterdayArticles = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->where('publish_date', '>=', $yesterday . ' 00:00:00')
|
->where('publish_date', '>=', $yesterday . ' 00:00:00')
|
||||||
->where('publish_date', '<=', $yesterday . ' 23:59:59')
|
->where('publish_date', '<=', $yesterday . ' 23:59:59')
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
// 本月新增
|
// 本月新增发布
|
||||||
$monthNewArticles = Articles::where('delete_time', null)
|
$monthNewArticles = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->where('publish_date', '>=', $monthStart . ' 00:00:00')
|
->where('publish_date', '>=', $monthStart . ' 00:00:00')
|
||||||
->where('publish_date', '<=', $monthEnd)
|
->where('publish_date', '<=', $monthEnd)
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
// 上月同期新增(用于对比)
|
|
||||||
$lastMonthStart = date('Y-m-01', strtotime('-1 month'));
|
|
||||||
$lastMonthEnd = date('Y-m-t 23:59:59', strtotime('-1 month'));
|
|
||||||
$lastMonthNewArticles = Articles::where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->where('publish_date', '>=', $lastMonthStart . ' 00:00:00')
|
|
||||||
->where('publish_date', '<=', $lastMonthEnd)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// 总点赞量
|
// 总点赞量
|
||||||
$totalLikes = Articles::where('delete_time', null)
|
$totalLikes = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->sum('likes');
|
->sum('likes');
|
||||||
|
|
||||||
// 昨日点赞量
|
|
||||||
$yesterdayLikes = Articles::where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->where('update_time', '>=', $yesterday . ' 00:00:00')
|
|
||||||
->where('update_time', '<=', $yesterday . ' 23:59:59')
|
|
||||||
->sum('likes');
|
|
||||||
|
|
||||||
// 总访问量
|
// 总访问量
|
||||||
$totalViews = Articles::where('delete_time', null)
|
$totalViews = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->sum('views');
|
->sum('views');
|
||||||
|
|
||||||
// 昨日访问量
|
|
||||||
$yesterdayViews = Articles::where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->where('update_time', '>=', $yesterday . ' 00:00:00')
|
|
||||||
->where('update_time', '<=', $yesterday . ' 23:59:59')
|
|
||||||
->sum('views');
|
|
||||||
|
|
||||||
// 计算增长率
|
|
||||||
$articleGrowth = $yesterdayTotalArticles > 0
|
|
||||||
? round(($totalArticles - $yesterdayTotalArticles) / $yesterdayTotalArticles * 100, 2)
|
|
||||||
: 0;
|
|
||||||
$monthGrowth = $lastMonthNewArticles > 0
|
|
||||||
? round(($monthNewArticles - $lastMonthNewArticles) / $lastMonthNewArticles * 100, 2)
|
|
||||||
: 0;
|
|
||||||
$likesGrowth = $yesterdayLikes > 0
|
|
||||||
? round(($totalLikes - $yesterdayLikes) / $yesterdayLikes * 100, 2)
|
|
||||||
: 0;
|
|
||||||
$viewsGrowth = $yesterdayViews > 0
|
|
||||||
? round(($totalViews - $yesterdayViews) / $yesterdayViews * 100, 2)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
// 热门内容TOP5
|
// 热门内容TOP5
|
||||||
$hotArticles = Articles::where('delete_time', null)
|
$hotArticles = Articles::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 2)
|
->where('status', 2)
|
||||||
->order('views', 'desc')
|
->order('views', 'desc')
|
||||||
->limit(5)
|
->limit(5)
|
||||||
@@ -107,28 +74,11 @@ class AnalyticsController extends BaseController
|
|||||||
->select();
|
->select();
|
||||||
|
|
||||||
$stats = [
|
$stats = [
|
||||||
'overview' => [
|
'total_articles' => $totalArticles,
|
||||||
'total_articles' => [
|
'yesterday_articles' => $yesterdayArticles,
|
||||||
'value' => $totalArticles,
|
'month_articles' => $monthNewArticles,
|
||||||
'yesterday' => $yesterdayTotalArticles,
|
'total_likes' => (int)$totalLikes,
|
||||||
'growth' => $articleGrowth
|
'total_views' => (int)$totalViews,
|
||||||
],
|
|
||||||
'month_new' => [
|
|
||||||
'value' => $monthNewArticles,
|
|
||||||
'last_month' => $lastMonthNewArticles,
|
|
||||||
'growth' => $monthGrowth
|
|
||||||
],
|
|
||||||
'total_likes' => [
|
|
||||||
'value' => (int)$totalLikes,
|
|
||||||
'yesterday' => (int)$yesterdayLikes,
|
|
||||||
'growth' => $likesGrowth
|
|
||||||
],
|
|
||||||
'total_views' => [
|
|
||||||
'value' => (int)$totalViews,
|
|
||||||
'yesterday' => (int)$yesterdayViews,
|
|
||||||
'growth' => $viewsGrowth
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'hot_articles' => $hotArticles->toArray()
|
'hot_articles' => $hotArticles->toArray()
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -156,7 +106,9 @@ class AnalyticsController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$stats = [
|
$stats = [
|
||||||
'total_users' => AdminUser::where('delete_time', null)->count(),
|
'total_users' => AdminUser::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->count(),
|
||||||
];
|
];
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('用户统计', '获取用户统计', ['data' => $stats]);
|
$this->logSuccess('用户统计', '获取用户统计', ['data' => $stats]);
|
||||||
+12
-10
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
declare (strict_types = 1);
|
declare (strict_types = 1);
|
||||||
|
|
||||||
namespace app\admin\controller\Article;
|
namespace app\admin\controller\Cms\Article;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -9,6 +9,7 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
|
use app\model\Cms\ArticlesCategory;
|
||||||
|
|
||||||
class ArticleCategoryController extends BaseController
|
class ArticleCategoryController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -24,8 +25,8 @@ class ArticleCategoryController extends BaseController
|
|||||||
$keyword = $keyword ?? '';
|
$keyword = $keyword ?? '';
|
||||||
|
|
||||||
// 获取文章分类列表
|
// 获取文章分类列表
|
||||||
$categories = Db::name('mete_articles_category')
|
$categories = ArticlesCategory::where('delete_time', null)
|
||||||
->where('delete_time', null)
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
->where('name', 'like', '%' . $keyword . '%')
|
->where('name', 'like', '%' . $keyword . '%')
|
||||||
->order('sort', 'desc')
|
->order('sort', 'desc')
|
||||||
@@ -55,8 +56,8 @@ class ArticleCategoryController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 获取文章分类列表
|
// 获取文章分类列表
|
||||||
$categories = Db::name('mete_articles_category')
|
$categories = ArticlesCategory::where('delete_time', null)
|
||||||
->where('delete_time', null)
|
->where('tid', $this->getTenantId())
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
->field('id,cid,name,image,sort')
|
->field('id,cid,name,image,sort')
|
||||||
->order('sort', 'desc')
|
->order('sort', 'desc')
|
||||||
@@ -93,10 +94,11 @@ class ArticleCategoryController extends BaseController
|
|||||||
$data['cid'] = isset($data['cid']) ? (int)$data['cid'] : 0;
|
$data['cid'] = isset($data['cid']) ? (int)$data['cid'] : 0;
|
||||||
$data['sort'] = isset($data['sort']) ? (int)$data['sort'] : 0;
|
$data['sort'] = isset($data['sort']) ? (int)$data['sort'] : 0;
|
||||||
$data['status']= isset($data['status']) ? (int)$data['status'] : 1;
|
$data['status']= isset($data['status']) ? (int)$data['status'] : 1;
|
||||||
|
$data['tid'] = $this->getTenantId();
|
||||||
$data['create_time'] = date('Y-m-d H:i:s');
|
$data['create_time'] = date('Y-m-d H:i:s');
|
||||||
$data['update_time'] = $data['create_time'];
|
$data['update_time'] = $data['create_time'];
|
||||||
|
|
||||||
$id = Db::name('mete_articles_category')->insertGetId($data);
|
$id = ArticlesCategory::insertGetId($data);
|
||||||
return json(['code'=>200,'msg'=>'success','data'=>['id'=>$id]]);
|
return json(['code'=>200,'msg'=>'success','data'=>['id'=>$id]]);
|
||||||
} catch (ValidateException $ve) {
|
} catch (ValidateException $ve) {
|
||||||
// 记录失败日志
|
// 记录失败日志
|
||||||
@@ -122,7 +124,7 @@ class ArticleCategoryController extends BaseController
|
|||||||
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
||||||
}
|
}
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
$affected = Db::name('mete_articles_category')->where('id',$id)->update($data);
|
$affected = ArticlesCategory::where('id',$id)->where('tid', $this->getTenantId())->update($data);
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
// 记录成功日志
|
// 记录成功日志
|
||||||
$this->logSuccess('文章分类管理', '更新文章分类', ['id' => $id]);
|
$this->logSuccess('文章分类管理', '更新文章分类', ['id' => $id]);
|
||||||
@@ -144,8 +146,8 @@ class ArticleCategoryController extends BaseController
|
|||||||
public function deleteCategory(int $id): Json
|
public function deleteCategory(int $id): Json
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$affected = Db::name('mete_articles_category')
|
$affected = ArticlesCategory::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -179,7 +181,7 @@ class ArticleCategoryController extends BaseController
|
|||||||
}
|
}
|
||||||
$data['status'] = isset($data['status']) ? (int)$data['status'] : 1;
|
$data['status'] = isset($data['status']) ? (int)$data['status'] : 1;
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
$affected = Db::name('mete_articles_category')->where('id',$id)->update($data);
|
$affected = ArticlesCategory::where('id',$id)->where('tid', $this->getTenantId())->update($data);
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
// 记录成功日志
|
// 记录成功日志
|
||||||
$this->logSuccess('文章分类管理', '更新分类状态', ['id' => $id]);
|
$this->logSuccess('文章分类管理', '更新分类状态', ['id' => $id]);
|
||||||
+56
-40
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
declare (strict_types = 1);
|
declare (strict_types = 1);
|
||||||
|
|
||||||
namespace app\admin\controller\Article;
|
namespace app\admin\controller\Cms\Article;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -10,6 +10,8 @@ use think\facade\Request;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
|
use app\model\Cms\Articles;
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
class ArticleController extends BaseController
|
class ArticleController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -21,18 +23,20 @@ class ArticleController extends BaseController
|
|||||||
* @param int $pageSize 每页条数(默认10)
|
* @param int $pageSize 每页条数(默认10)
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getArticlesList(string $keyword = '', string $cate = '', int $page = 1, int $pageSize = 10): Json
|
public function getArticlesList(string $author = '', string $keyword = '', string $cate = '', int $page = 1, int $pageSize = 10): Json
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 安全处理参数(防止非法参数)
|
// 安全处理参数(防止非法参数)
|
||||||
$page = max(1, $page); // 页码最小为1
|
$page = max(1, $page); // 页码最小为1
|
||||||
$pageSize = max(1, min(100, $pageSize)); // 每页条数限制1-100条
|
$pageSize = max(1, min(100, $pageSize)); // 每页条数限制1-100条
|
||||||
|
$author = trim($author);
|
||||||
$keyword = trim($keyword);
|
$keyword = trim($keyword);
|
||||||
$cate = trim($cate);
|
$cate = trim($cate);
|
||||||
|
|
||||||
// 输出参数值
|
// 输出参数值
|
||||||
trace('查询参数:', 'debug');
|
trace('查询参数:', 'debug');
|
||||||
trace([
|
trace([
|
||||||
|
'author' => $author,
|
||||||
'keyword' => $keyword,
|
'keyword' => $keyword,
|
||||||
'cate' => $cate,
|
'cate' => $cate,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
@@ -40,8 +44,9 @@ class ArticleController extends BaseController
|
|||||||
], 'debug');
|
], 'debug');
|
||||||
|
|
||||||
// 构建查询条件,合并表连接
|
// 构建查询条件,合并表连接
|
||||||
$query = Db::name('mete_articles')->alias('a')
|
$query = Articles::alias('a')
|
||||||
->where('a.delete_time', null)
|
->where('a.delete_time', null)
|
||||||
|
->where('a.tid', $this->getTenantId())
|
||||||
->leftJoin('mete_admin_user u', 'a.publisher = u.id')
|
->leftJoin('mete_admin_user u', 'a.publisher = u.id')
|
||||||
->leftJoin('mete_articles_category c', 'a.cate = c.id');
|
->leftJoin('mete_articles_category c', 'a.cate = c.id');
|
||||||
|
|
||||||
@@ -49,6 +54,11 @@ class ArticleController extends BaseController
|
|||||||
if ($keyword) {
|
if ($keyword) {
|
||||||
$query->where('a.title', 'like', '%' . $keyword . '%');
|
$query->where('a.title', 'like', '%' . $keyword . '%');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 作者筛选
|
||||||
|
if ($author) {
|
||||||
|
$query->where('a.publisher', 'like', '%' . $author . '%');
|
||||||
|
}
|
||||||
|
|
||||||
// 分类筛选
|
// 分类筛选
|
||||||
if ($cate) {
|
if ($cate) {
|
||||||
@@ -98,8 +108,7 @@ class ArticleController extends BaseController
|
|||||||
$newTitleLength = strlen($newTitleLower);
|
$newTitleLength = strlen($newTitleLower);
|
||||||
|
|
||||||
// 获取所有文章标题
|
// 获取所有文章标题
|
||||||
$allTitles = Db::name('mete_articles')
|
$allTitles = Articles::field('id, title')
|
||||||
->field('id, title')
|
|
||||||
->select();
|
->select();
|
||||||
|
|
||||||
$similarArticles = [];
|
$similarArticles = [];
|
||||||
@@ -180,10 +189,11 @@ class ArticleController extends BaseController
|
|||||||
'is_trans' => $data['is_trans'] ?? 0,
|
'is_trans' => $data['is_trans'] ?? 0,
|
||||||
'transurl' => $data['is_trans'] == 1 ? ($data['transurl'] ?? '') : '',
|
'transurl' => $data['is_trans'] == 1 ? ($data['transurl'] ?? '') : '',
|
||||||
'publisher' => $userId,
|
'publisher' => $userId,
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'create_time' => date('Y-m-d H:i:s'),
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
];
|
];
|
||||||
|
|
||||||
$id = Db::name('mete_articles')->insertGetId($insertData);
|
$id = Articles::insertGetId($insertData);
|
||||||
|
|
||||||
// 记录成功日志
|
// 记录成功日志
|
||||||
$this->logSuccess('文章管理', '创建文章', ['id' => $id]);
|
$this->logSuccess('文章管理', '创建文章', ['id' => $id]);
|
||||||
@@ -206,10 +216,17 @@ class ArticleController extends BaseController
|
|||||||
public function getArticle(int $id): Json
|
public function getArticle(int $id): Json
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$article = Db::name('mete_articles')
|
$article = Articles::alias('a')
|
||||||
->where('id', $id)
|
->where('a.id', $id)
|
||||||
->field('id,title,cate,image,desc,author,content,is_trans,transurl,views,likes,publisher,create_time,publish_date,update_time')
|
->where('a.tid', $this->getTenantId())
|
||||||
->find();
|
->leftJoin('mete_admin_user u', 'a.publisher = u.id')
|
||||||
|
->field('a.id,a.title,a.cate,a.image,a.desc,a.author,a.content,a.is_trans,a.transurl,a.views,a.likes,u.name as publisher_name,a.create_time,a.publish_date,a.update_time')
|
||||||
|
->find()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 将 publisher_name 赋值给 publisher
|
||||||
|
$article['publisher'] = $article['publisher_name'] ?? '';
|
||||||
|
unset($article['publisher_name']);
|
||||||
|
|
||||||
if (!$article) {
|
if (!$article) {
|
||||||
return json(['code' => 404, 'msg' => '文章不存在', 'data' => null]);
|
return json(['code' => 404, 'msg' => '文章不存在', 'data' => null]);
|
||||||
@@ -234,12 +251,17 @@ class ArticleController extends BaseController
|
|||||||
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
||||||
}
|
}
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
$affected = Db::name('mete_articles')->where('id',$id)->update($data);
|
$article = Articles::where('id', $id)->where('tid', $this->getTenantId())->find();
|
||||||
|
if (!$article) {
|
||||||
|
return json(['code'=>404,'msg'=>'文章不存在','data'=>null]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$affected = Articles::where('id',$id)->where('tid', $this->getTenantId())->update($data);
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
|
// 记录成功日志
|
||||||
|
$this->logSuccess('文章管理', '编辑文章', ['id' => $id]);
|
||||||
return json(['code'=>200,'msg'=>'success','data'=>null]);
|
return json(['code'=>200,'msg'=>'success','data'=>null]);
|
||||||
}
|
}
|
||||||
// 记录成功日志
|
|
||||||
$this->logSuccess('文章管理', '编辑文章', ['id' => $id]);
|
|
||||||
return json(['code'=>404,'msg'=>'not found','data'=>null]);
|
return json(['code'=>404,'msg'=>'not found','data'=>null]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// 记录失败日志
|
// 记录失败日志
|
||||||
@@ -256,24 +278,18 @@ class ArticleController extends BaseController
|
|||||||
public function deleteArticle(int $id): Json
|
public function deleteArticle(int $id): Json
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
// 记录成功日志
|
$this->logSuccess('文章管理', '删除文章', ['id' => $id]);
|
||||||
$this->logSuccess('文章管理', '删除文章', ['id' => $id]);
|
|
||||||
return json(['code' => 200, 'msg' => 'success', 'data' => null]);
|
return json(['code' => 200, 'msg' => 'success', 'data' => null]);
|
||||||
}
|
}
|
||||||
return json(['code' => 404, 'msg' => 'not found', 'data' => null]);
|
return json(['code' => 404, 'msg' => 'not found', 'data' => null]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// 记录失败日志
|
$this->logFail('文章管理', '删除文章', $e->getMessage());
|
||||||
$this->logFail('文章管理', '删除文章', $e->getMessage());
|
return json(['code' => 500, 'msg' => 'fail:' . $e->getMessage(), 'data' => null]);
|
||||||
return json([
|
|
||||||
'code' => 500,
|
|
||||||
'msg' => 'fail:' . $e->getMessage(),
|
|
||||||
'data' => $e->getTraceAsString()
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +306,7 @@ class ArticleController extends BaseController
|
|||||||
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
return json(['code'=>400,'msg'=>'无更新数据','data'=>null]);
|
||||||
}
|
}
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
$affected = Db::name('mete_articles')->where('id',$id)->update($data);
|
$affected = Articles::where('id',$id)->where('tid', $this->getTenantId())->update($data);
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
// 记录成功日志
|
// 记录成功日志
|
||||||
$this->logSuccess('文章管理', '更新文章分类状态', ['id' => $id]);
|
$this->logSuccess('文章管理', '更新文章分类状态', ['id' => $id]);
|
||||||
@@ -329,8 +345,8 @@ class ArticleController extends BaseController
|
|||||||
'publisher' => $user_id,
|
'publisher' => $user_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -366,8 +382,8 @@ class ArticleController extends BaseController
|
|||||||
'update_time' => $currentTime
|
'update_time' => $currentTime
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -400,8 +416,8 @@ class ArticleController extends BaseController
|
|||||||
'recommend' => 1, // 推荐状态
|
'recommend' => 1, // 推荐状态
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -434,8 +450,8 @@ class ArticleController extends BaseController
|
|||||||
'recommend' => 0, // 取消推荐状态
|
'recommend' => 0, // 取消推荐状态
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -464,8 +480,8 @@ class ArticleController extends BaseController
|
|||||||
'top' => 1, // 置顶状态
|
'top' => 1, // 置顶状态
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -494,8 +510,8 @@ class ArticleController extends BaseController
|
|||||||
'top' => 0, // 取消置顶状态
|
'top' => 0, // 取消置顶状态
|
||||||
];
|
];
|
||||||
|
|
||||||
$affected = Db::name('mete_articles')
|
$affected = Articles::where('id', $id)
|
||||||
->where('id', $id)
|
->where('tid', $this->getTenantId())
|
||||||
->update($data);
|
->update($data);
|
||||||
|
|
||||||
if ($affected) {
|
if ($affected) {
|
||||||
@@ -539,9 +555,9 @@ class ArticleController extends BaseController
|
|||||||
], 'debug');
|
], 'debug');
|
||||||
|
|
||||||
// 构建查询条件
|
// 构建查询条件
|
||||||
$query = Db::name('mete_articles')
|
$query = Articles::alias('a')
|
||||||
->alias('a')
|
->where('a.delete_time', null)
|
||||||
->where('a.delete_time', null);
|
->where('a.tid', $this->getTenantId());
|
||||||
|
|
||||||
// 关键词筛选(标题模糊匹配)
|
// 关键词筛选(标题模糊匹配)
|
||||||
if (!empty($keyword)) {
|
if (!empty($keyword)) {
|
||||||
+16
-7
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\Cms\Banner;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -10,7 +10,7 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use app\model\Banner;
|
use app\model\Cms\Banner;
|
||||||
|
|
||||||
class BannerController extends BaseController
|
class BannerController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,8 @@ class BannerController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$banners = Banner::where('delete_time', null)
|
$banners = Banner::where('delete_time', null)
|
||||||
->order('sort', 'asc')
|
->where('tid', $this->getTenantId())
|
||||||
|
->order('sort desc, id desc')
|
||||||
->field('id, title, desc, url, image, sort, create_time, update_time')
|
->field('id, title, desc, url, image, sort, create_time, update_time')
|
||||||
->select()
|
->select()
|
||||||
->toArray();
|
->toArray();
|
||||||
@@ -66,6 +67,7 @@ class BannerController extends BaseController
|
|||||||
// 准备Banner数据
|
// 准备Banner数据
|
||||||
$bannerData = [
|
$bannerData = [
|
||||||
'title' => $data['title'],
|
'title' => $data['title'],
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'desc' => $data['desc'] ?? '',
|
'desc' => $data['desc'] ?? '',
|
||||||
'url' => $data['url'] ?? '',
|
'url' => $data['url'] ?? '',
|
||||||
'image' => $data['image'] ?? '',
|
'image' => $data['image'] ?? '',
|
||||||
@@ -127,8 +129,9 @@ class BannerController extends BaseController
|
|||||||
'sort|排序号' => 'integer',
|
'sort|排序号' => 'integer',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 检查Banner是否存在
|
// 检查Banner是否存在(验证tid)
|
||||||
$banner = Banner::where('id', $id)
|
$banner = Banner::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -150,10 +153,14 @@ class BannerController extends BaseController
|
|||||||
];
|
];
|
||||||
|
|
||||||
// 执行更新
|
// 执行更新
|
||||||
Banner::where('id', $id)->update($updateData);
|
Banner::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update($updateData);
|
||||||
|
|
||||||
// 获取更新后的Banner信息
|
// 获取更新后的Banner信息
|
||||||
$updatedBanner = Banner::where('id', $id)->find();
|
$updatedBanner = Banner::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('Banner管理', '更新Banner', ['id' => $id]);
|
$this->logSuccess('Banner管理', '更新Banner', ['id' => $id]);
|
||||||
@@ -187,8 +194,9 @@ class BannerController extends BaseController
|
|||||||
public function deleteBanner(int $id)
|
public function deleteBanner(int $id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 检查Banner是否存在
|
// 检查Banner是否存在(验证tid)
|
||||||
$banner = Banner::where('id', $id)
|
$banner = Banner::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -201,6 +209,7 @@ class BannerController extends BaseController
|
|||||||
|
|
||||||
// 逻辑删除Banner
|
// 逻辑删除Banner
|
||||||
$result = Banner::where('id', $id)
|
$result = Banner::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->update([
|
->update([
|
||||||
'delete_time' => time(),
|
'delete_time' => time(),
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Demand;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Request;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
|
||||||
|
use app\model\Cms\Demand;
|
||||||
|
use app\model\Cms\DemandCategory;
|
||||||
|
|
||||||
|
|
||||||
|
class DemandController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取需求列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getDemandList(): Json
|
||||||
|
{
|
||||||
|
// 查询分类
|
||||||
|
$demandList = Demand::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->order('id', 'desc')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
if (!$demandList) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $demandList,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加需求
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function addDemand(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = Request::only(['title', 'desc', 'applicant', 'status']);
|
||||||
|
|
||||||
|
// 验证数据
|
||||||
|
if (empty($data['title']) || empty($data['desc'])) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '标题和描述不能为空',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建需求
|
||||||
|
$demand = Demand::create([
|
||||||
|
'title' => $data['title'],
|
||||||
|
'desc' => $data['desc'],
|
||||||
|
'applicant' => $data['applicant'] ?? '',
|
||||||
|
'status' => $data['status'] ?? 'pending',
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => $demand,
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '添加失败:' . $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑需求
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editDemand(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$id = Request::param('id');
|
||||||
|
$data = Request::only(['title', 'desc', 'applicant', 'status']);
|
||||||
|
|
||||||
|
// 验证数据
|
||||||
|
if (empty($id)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '需求ID不能为空',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['title']) || empty($data['desc'])) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '标题和描述不能为空',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找需求(验证tid)
|
||||||
|
$demand = Demand::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if (!$demand) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '需求不存在',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新需求
|
||||||
|
$demand->save([
|
||||||
|
'title' => $data['title'],
|
||||||
|
'desc' => $data['desc'],
|
||||||
|
'applicant' => $data['applicant'] ?? '',
|
||||||
|
'status' => $data['status'] ?? 'pending',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功',
|
||||||
|
'data' => $demand,
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '编辑失败:' . $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除需求
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteDemand(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$id = Request::param('id');
|
||||||
|
|
||||||
|
// 验证数据
|
||||||
|
if (empty($id)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '需求ID不能为空',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找需求(验证tid)
|
||||||
|
$demand = Demand::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if (!$demand) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '需求不存在',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 软删除
|
||||||
|
$demand->delete();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功',
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Domain;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\Request;
|
||||||
|
use app\model\System\SystemDomainPool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主域名池管理控制器
|
||||||
|
*/
|
||||||
|
class DomainPoolController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取域名池列表
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$page = $request->param('page', 1, 'int');
|
||||||
|
$pageSize = $request->param('pageSize', 10, 'int');
|
||||||
|
$mainDomain = $request->param('main_domain', '');
|
||||||
|
$status = $request->param('status', '');
|
||||||
|
|
||||||
|
$where = [['delete_time', '=', null]];
|
||||||
|
|
||||||
|
if ($mainDomain) {
|
||||||
|
$where[] = ['main_domain', 'like', "%$mainDomain%"];
|
||||||
|
}
|
||||||
|
if ($status !== '' && $status !== null) {
|
||||||
|
$where[] = ['status', '=', $status];
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = SystemDomainPool::where($where)
|
||||||
|
->page($page, $pageSize)
|
||||||
|
->order('id', 'desc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$total = SystemDomainPool::where($where)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取启用状态的主域名列表(供租户选择)
|
||||||
|
*/
|
||||||
|
public function getEnabledDomains()
|
||||||
|
{
|
||||||
|
$list = SystemDomainPool::where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建主域名
|
||||||
|
*/
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$mainDomain = $request->param('main_domain', '');
|
||||||
|
|
||||||
|
if (empty($mainDomain)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '主域名不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查域名是否已存在
|
||||||
|
$exists = SystemDomainPool::where('main_domain', $mainDomain)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($exists) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该域名已存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
$id = SystemDomainPool::insertGetId([
|
||||||
|
'main_domain' => $mainDomain,
|
||||||
|
'status' => 1,
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => ['id' => $id]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑主域名
|
||||||
|
*/
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->param('id', 0, 'int');
|
||||||
|
$mainDomain = $request->param('main_domain', '');
|
||||||
|
$status = $request->param('status', null);
|
||||||
|
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($mainDomain)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '主域名不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查域名是否与其他记录重复
|
||||||
|
$exists = SystemDomainPool::where('main_domain', $mainDomain)
|
||||||
|
->where('id', '<>', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($exists) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该域名已存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'main_domain' => $mainDomain,
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($status !== null) {
|
||||||
|
$data['status'] = $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemDomainPool::where('id', $id)->update($data);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除主域名(软删除)
|
||||||
|
*/
|
||||||
|
public function delete($id)
|
||||||
|
{
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemDomainPool::where('id', $id)
|
||||||
|
->update([
|
||||||
|
'delete_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换主域名状态
|
||||||
|
*/
|
||||||
|
public function toggleStatus(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->param('id', 0, 'int');
|
||||||
|
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$domain = SystemDomainPool::where('id', $id)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$domain) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '域名不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newStatus = $domain['status'] == 1 ? 0 : 1;
|
||||||
|
|
||||||
|
SystemDomainPool::where('id', $id)
|
||||||
|
->update([
|
||||||
|
'status' => $newStatus,
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '状态更新成功',
|
||||||
|
'data' => ['status' => $newStatus]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Domain;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\Request;
|
||||||
|
use think\facade\Session;
|
||||||
|
use app\model\Tenant\TenantDomain;
|
||||||
|
use app\model\Tenant\Tenant;
|
||||||
|
use app\model\System\SystemDomainPool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户域名绑定控制器
|
||||||
|
*/
|
||||||
|
class TenantDomainController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取租户域名列表(管理员查看所有)
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$page = $request->param('page', 1, 'int');
|
||||||
|
$pageSize = $request->param('pageSize', 10, 'int');
|
||||||
|
$tenantId = $request->param('tid', 0, 'int');
|
||||||
|
$status = $request->param('status', '');
|
||||||
|
$subDomain = $request->param('sub_domain', '');
|
||||||
|
|
||||||
|
$where = [['delete_time', '=', null]];
|
||||||
|
|
||||||
|
if ($tenantId > 0) {
|
||||||
|
$where[] = ['tid', '=', $tenantId];
|
||||||
|
}
|
||||||
|
if ($status !== '' && $status !== null) {
|
||||||
|
$where[] = ['status', '=', $status];
|
||||||
|
}
|
||||||
|
if ($subDomain) {
|
||||||
|
$where[] = ['sub_domain', 'like', "%$subDomain%"];
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = TenantDomain::where($where)
|
||||||
|
->page($page, $pageSize)
|
||||||
|
->order('id', 'desc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$total = TenantDomain::where($where)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
// 获取租户名称
|
||||||
|
$tenantIds = array_column($list, 'tid');
|
||||||
|
$tenants = [];
|
||||||
|
if ($tenantIds) {
|
||||||
|
$tenantList = Tenant::whereIn('id', $tenantIds)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
$tenants = array_column($tenantList, null, 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 附加租户名称
|
||||||
|
foreach ($list as &$item) {
|
||||||
|
$item['tenant_name'] = $tenants[$item['tid']]['tenant_name'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前租户的域名列表(租户端)
|
||||||
|
*/
|
||||||
|
public function myDomains(Request $request)
|
||||||
|
{
|
||||||
|
$tid = $request->param('tid', 0, 'int');
|
||||||
|
|
||||||
|
if ($tid <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '租户ID不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = TenantDomain::where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->order('id', 'desc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户申请二级域名
|
||||||
|
*/
|
||||||
|
public function apply(Request $request)
|
||||||
|
{
|
||||||
|
$tid = $request->param('tid', 0, 'int');
|
||||||
|
$subDomain = $request->param('sub_domain', '');
|
||||||
|
$mainDomain = $request->param('main_domain', '');
|
||||||
|
|
||||||
|
if ($tid <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '租户ID不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查该租户是否已有域名数据
|
||||||
|
$hasDomain = TenantDomain::where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($hasDomain) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该租户已有域名,请删除后再次申请'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($subDomain)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '二级域名前缀不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($mainDomain)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '请选择主域名'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证域名格式(只能包含字母、数字、连字符)
|
||||||
|
if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/', $subDomain)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '二级域名前缀格式不正确'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查主域名是否存在且启用
|
||||||
|
$mainDomainInfo = SystemDomainPool::where('main_domain', $mainDomain)
|
||||||
|
->where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$mainDomainInfo) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '主域名不存在或已禁用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查二级域名是否已被使用
|
||||||
|
$exists = TenantDomain::where('sub_domain', $subDomain)
|
||||||
|
->where('main_domain', $mainDomain)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($exists) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该二级域名已被使用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fullDomain = $subDomain . '.' . $mainDomain;
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$id = TenantDomain::insertGetId([
|
||||||
|
'tid' => $tid,
|
||||||
|
'sub_domain' => $subDomain,
|
||||||
|
'main_domain' => $mainDomain,
|
||||||
|
'full_domain' => $fullDomain,
|
||||||
|
'status' => 0, // 审核中
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '申请提交成功,等待审核',
|
||||||
|
'data' => ['id' => $id]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核租户域名(通过/拒绝)
|
||||||
|
*/
|
||||||
|
public function audit(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->param('id', 0, 'int');
|
||||||
|
$action = $request->param('action', ''); // 'approve' 或 'reject'
|
||||||
|
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$domain = TenantDomain::where('id', $id)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$domain) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '域名不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($domain['status'] != 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该域名已审核过了'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newStatus = $action === 'approve' ? 1 : 2; // 1-已生效 2-已拒绝
|
||||||
|
|
||||||
|
TenantDomain::where('id', $id)
|
||||||
|
->update([
|
||||||
|
'status' => $newStatus,
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
$msg = $action === 'approve' ? '审核通过' : '已拒绝';
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => $msg
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用/启用租户域名
|
||||||
|
*/
|
||||||
|
public function toggleStatus(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->param('id', 0, 'int');
|
||||||
|
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$domain = TenantDomain::where('id', $id)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$domain) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '域名不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有已生效的域名才能被禁用
|
||||||
|
if ($domain['status'] != 1) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '只有已生效的域名才能被禁用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换为禁用状态
|
||||||
|
TenantDomain::where('id', $id)
|
||||||
|
->update([
|
||||||
|
'status' => 2,
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '已禁用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除租户域名(软删除)
|
||||||
|
*/
|
||||||
|
public function delete($id)
|
||||||
|
{
|
||||||
|
if ($id <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TenantDomain::where('id', $id)
|
||||||
|
->update([
|
||||||
|
'delete_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Friendlink;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\response\Json;
|
||||||
|
use app\model\Cms\Friendlink;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 友情链接管理控制器
|
||||||
|
*/
|
||||||
|
class FriendlinkController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取友情链接列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getList(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$page = (int)$this->request->param('page', 1);
|
||||||
|
$limit = (int)$this->request->param('limit', 10);
|
||||||
|
$keyword = $this->request->param('keyword', '');
|
||||||
|
$status = $this->request->param('status', '');
|
||||||
|
|
||||||
|
$query = Friendlink::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
|
// 关键词搜索
|
||||||
|
if (!empty($keyword)) {
|
||||||
|
$query->where('link_name', 'like', '%' . $keyword . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态筛选
|
||||||
|
if ($status !== '') {
|
||||||
|
$query->where('status', (int)$status);
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = $query->count();
|
||||||
|
$list = $query->order('sort', 'asc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->page($page, $limit)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有友情链接(用于下拉选择)
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getAll(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$list = Friendlink::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('status', 1)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->field('id,link_name')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加友情链接
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function add(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
// 验证参数
|
||||||
|
$this->validate($data, [
|
||||||
|
'link_name|链接名称' => 'require|max:100',
|
||||||
|
'link_url|链接地址' => 'require|url|max:255',
|
||||||
|
'sort|排序' => 'integer',
|
||||||
|
'status|状态' => 'in:0,1'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$friendlink = new Friendlink();
|
||||||
|
$friendlink->tid = $this->getTenantId();
|
||||||
|
$friendlink->link_name = $data['link_name'];
|
||||||
|
$friendlink->link_url = $data['link_url'];
|
||||||
|
$friendlink->link_logo = $data['link_logo'] ?? '';
|
||||||
|
$friendlink->description = $data['description'] ?? '';
|
||||||
|
$friendlink->sort = $data['sort'] ?? 0;
|
||||||
|
$friendlink->status = $data['status'] ?? 1;
|
||||||
|
$friendlink->create_time = date('Y-m-d H:i:s');
|
||||||
|
$friendlink->save();
|
||||||
|
|
||||||
|
$this->logSuccess('友情链接', '添加链接', ['id' => $friendlink->id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => $friendlink->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('友情链接', '添加链接', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '添加失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新友情链接
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function update(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$friendlink = Friendlink::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$friendlink) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '链接不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证参数
|
||||||
|
if (isset($data['link_name'])) {
|
||||||
|
$this->validate($data, [
|
||||||
|
'link_name|链接名称' => 'require|max:100'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (isset($data['link_url'])) {
|
||||||
|
$this->validate($data, [
|
||||||
|
'link_url|链接地址' => 'require|url|max:255'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['link_name'])) $friendlink->link_name = $data['link_name'];
|
||||||
|
if (isset($data['link_url'])) $friendlink->link_url = $data['link_url'];
|
||||||
|
if (isset($data['link_logo'])) $friendlink->link_logo = $data['link_logo'];
|
||||||
|
if (isset($data['description'])) $friendlink->description = $data['description'];
|
||||||
|
if (isset($data['sort'])) $friendlink->sort = $data['sort'];
|
||||||
|
if (isset($data['status'])) $friendlink->status = $data['status'];
|
||||||
|
$friendlink->update_time = date('Y-m-d H:i:s');
|
||||||
|
$friendlink->save();
|
||||||
|
|
||||||
|
$this->logSuccess('友情链接', '更新链接', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $friendlink->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('友情链接', '更新链接', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除友情链接
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function delete(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$friendlink = Friendlink::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$friendlink) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '链接不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$friendlink->delete();
|
||||||
|
|
||||||
|
$this->logSuccess('友情链接', '删除链接', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('友情链接', '删除链接', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除友情链接
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function batchDelete(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$ids = $this->request->param('ids', []);
|
||||||
|
|
||||||
|
if (empty($ids)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '请选择要删除的链接'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Friendlink::whereIn('id', $ids)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
|
$this->logSuccess('友情链接', '批量删除链接', ['ids' => $ids]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '批量删除成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('友情链接', '批量删除链接', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '批量删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\Cms\FrontMenu;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -10,11 +10,11 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use app\model\FrontMenu;
|
use app\model\Cms\FrontMenu;
|
||||||
|
|
||||||
class FrontMenuController extends BaseController
|
class FrontMenuController extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 获取前端导航接口
|
* 获取前端导航接口
|
||||||
* @return \think\response\Json
|
* @return \think\response\Json
|
||||||
*/
|
*/
|
||||||
@@ -23,6 +23,7 @@ class FrontMenuController extends BaseController
|
|||||||
try {
|
try {
|
||||||
// 获取所有未删除的菜单
|
// 获取所有未删除的菜单
|
||||||
$frontMenus = FrontMenu::where('delete_time', null)
|
$frontMenus = FrontMenu::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->field('id,pid,title,type,image,path,component_path,sort,desc')
|
->field('id,pid,title,type,image,path,component_path,sort,desc')
|
||||||
->order('sort', 'desc')
|
->order('sort', 'desc')
|
||||||
->select()
|
->select()
|
||||||
@@ -69,6 +70,7 @@ class FrontMenuController extends BaseController
|
|||||||
// 准备菜单数据
|
// 准备菜单数据
|
||||||
$menuData = [
|
$menuData = [
|
||||||
'pid' => $data['pid'] ?? 0,
|
'pid' => $data['pid'] ?? 0,
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'title' => $data['title'],
|
'title' => $data['title'],
|
||||||
'type' => $data['type'],
|
'type' => $data['type'],
|
||||||
'sort' => $data['sort'] ?? 0,
|
'sort' => $data['sort'] ?? 0,
|
||||||
@@ -130,6 +132,7 @@ class FrontMenuController extends BaseController
|
|||||||
// 准备更新数据
|
// 准备更新数据
|
||||||
$updateData = [
|
$updateData = [
|
||||||
'title' => $data['title'],
|
'title' => $data['title'],
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'pid' => $data['pid'] ?? null,
|
'pid' => $data['pid'] ?? null,
|
||||||
'type' => $data['type'],
|
'type' => $data['type'],
|
||||||
'path' => $data['path'] ?? null,
|
'path' => $data['path'] ?? null,
|
||||||
@@ -163,7 +166,7 @@ class FrontMenuController extends BaseController
|
|||||||
} catch (DbException $e) {
|
} catch (DbException $e) {
|
||||||
// 记录失败日志
|
// 记录失败日志
|
||||||
$this->logFail('前端导航管理', '更新前端导航', $e->getMessage());
|
$this->logFail('前端导航管理', '更新前端导航', $e->getMessage());
|
||||||
return json([
|
return json([
|
||||||
'code' => 500,
|
'code' => 500,
|
||||||
'msg' => 'fail:' . $e->getMessage(),
|
'msg' => 'fail:' . $e->getMessage(),
|
||||||
'data' => $e->getTraceAsString()
|
'data' => $e->getTraceAsString()
|
||||||
@@ -176,7 +179,8 @@ class FrontMenuController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 检查是否有子前端导航
|
// 检查是否有子前端导航
|
||||||
$hasChildren = FrontMenu::where('pid', $id)
|
$hasChildren = FrontMenu::where('pid', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('pid', $id)
|
->where('pid', $id)
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->count() > 0;
|
->count() > 0;
|
||||||
@@ -192,6 +196,7 @@ $hasChildren = FrontMenu::where('pid', $id)
|
|||||||
$result = FrontMenu::where('id', $id)
|
$result = FrontMenu::where('id', $id)
|
||||||
->where('id', $id)
|
->where('id', $id)
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->update([
|
->update([
|
||||||
'delete_time' => date('Y-m-d H:i:s'),
|
'delete_time' => date('Y-m-d H:i:s'),
|
||||||
'update_time' => date('Y-m-d H:i:s')
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
+11
-4
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\Cms\OnePage;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -10,7 +10,7 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use app\model\OnePage;
|
use app\model\Cms\OnePage;
|
||||||
|
|
||||||
class OnePageController extends BaseController
|
class OnePageController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -22,6 +22,7 @@ class OnePageController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$onePages = OnePage::where('delete_time', null)
|
$onePages = OnePage::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->order('sort', 'asc')
|
->order('sort', 'asc')
|
||||||
->field('id, title, content, path, sort, status, create_time, update_time')
|
->field('id, title, content, path, sort, status, create_time, update_time')
|
||||||
->select()
|
->select()
|
||||||
@@ -69,6 +70,7 @@ class OnePageController extends BaseController
|
|||||||
|
|
||||||
// 检查路由是否已存在
|
// 检查路由是否已存在
|
||||||
$exists = OnePage::where('path', $data['path'])
|
$exists = OnePage::where('path', $data['path'])
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
@@ -85,6 +87,7 @@ class OnePageController extends BaseController
|
|||||||
'path' => $data['path'],
|
'path' => $data['path'],
|
||||||
'sort' => $data['sort'] ?? 0,
|
'sort' => $data['sort'] ?? 0,
|
||||||
'status' => $data['status'] ?? 1,
|
'status' => $data['status'] ?? 1,
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'create_time' => date('Y-m-d H:i:s'),
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -150,8 +153,9 @@ class OnePageController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查单页是否存在
|
// 检查单页是否存在(验证tid)
|
||||||
$onePage = OnePage::where('id', $id)
|
$onePage = OnePage::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -165,6 +169,7 @@ class OnePageController extends BaseController
|
|||||||
// 检查路由是否被其他单页使用
|
// 检查路由是否被其他单页使用
|
||||||
$exists = OnePage::where('path', $data['path'])
|
$exists = OnePage::where('path', $data['path'])
|
||||||
->where('id', '<>', $id)
|
->where('id', '<>', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
@@ -222,8 +227,9 @@ class OnePageController extends BaseController
|
|||||||
public function deleteOnePage(int $id)
|
public function deleteOnePage(int $id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 检查单页是否存在
|
// 检查单页是否存在(验证tid)
|
||||||
$onePage = OnePage::where('id', $id)
|
$onePage = OnePage::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -236,6 +242,7 @@ class OnePageController extends BaseController
|
|||||||
|
|
||||||
// 逻辑删除单页
|
// 逻辑删除单页
|
||||||
$result = OnePage::where('id', $id)
|
$result = OnePage::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->update([
|
->update([
|
||||||
'delete_time' => date('Y-m-d H:i:s'),
|
'delete_time' => date('Y-m-d H:i:s'),
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Products;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\response\Json;
|
||||||
|
use app\model\Cms\Products;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色产品管理控制器
|
||||||
|
*/
|
||||||
|
class ProductsController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取特色产品列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function productsList(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$page = (int)$this->request->param('page', 1);
|
||||||
|
$limit = (int)$this->request->param('limit', 10);
|
||||||
|
$keyword = $this->request->param('keyword', '');
|
||||||
|
|
||||||
|
$query = Products::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
|
// 关键词搜索
|
||||||
|
if (!empty($keyword)) {
|
||||||
|
$query->where('title', 'like', '%' . $keyword . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = $query->count();
|
||||||
|
$list = $query->order('sort', 'asc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->page($page, $limit)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加特色产品
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function addProducts(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$product = new Products();
|
||||||
|
$product->tid = $this->getTenantId();
|
||||||
|
$product->title = $data['title'];
|
||||||
|
$product->url = $data['url'];
|
||||||
|
$product->thumb = $data['thumb'] ?? '';
|
||||||
|
$product->desc = $data['desc'] ?? '';
|
||||||
|
$product->content = $data['content'] ?? '';
|
||||||
|
$product->sort = $data['sort'] ?? 0;
|
||||||
|
$product->create_time = date('Y-m-d H:i:s');
|
||||||
|
$product->save();
|
||||||
|
|
||||||
|
$this->logSuccess('特色产品', '添加产品', ['id' => $product->id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => $product->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色产品', '添加产品', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '添加失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新特色产品
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editProducts(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$product = Products::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$product) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '产品不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['title'])) $product->title = $data['title'];
|
||||||
|
if (isset($data['url'])) $product->url = $data['url'];
|
||||||
|
if (isset($data['thumb'])) $product->thumb = $data['thumb'];
|
||||||
|
if (isset($data['desc'])) $product->desc = $data['desc'];
|
||||||
|
if (isset($data['sort'])) $product->sort = $data['sort'];
|
||||||
|
$product->update_time = date('Y-m-d H:i:s');
|
||||||
|
$product->save();
|
||||||
|
|
||||||
|
$this->logSuccess('特色产品', '更新产品', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $product->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色产品', '更新产品', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除特色产品
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteProducts(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$product = Products::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$product) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '产品不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$product->delete();
|
||||||
|
|
||||||
|
$this->logSuccess('特色产品', '删除产品', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色产品', '删除产品', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Products;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use app\model\Cms\ProductsTypes;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\response\Json;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品分类管理控制器
|
||||||
|
*/
|
||||||
|
class ProductsTypesController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取产品分类列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function productsTypesList(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$page = (int)$this->request->param('page', 1);
|
||||||
|
$limit = (int)$this->request->param('limit', 10);
|
||||||
|
$keyword = (string)$this->request->param('keyword', '');
|
||||||
|
|
||||||
|
$query = ProductsTypes::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
|
if ($keyword !== '') {
|
||||||
|
$query->where('title', 'like', '%' . $keyword . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = $query->count();
|
||||||
|
|
||||||
|
$list = $query->order('sort', 'asc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->page($page, $limit)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => [
|
||||||
|
'list' => [],
|
||||||
|
'total' => 0
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加产品分类
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function addProductsTypes(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$title = (string)($data['title'] ?? '');
|
||||||
|
if ($title === '') {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '分类名称不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = new ProductsTypes();
|
||||||
|
$type->tid = $this->getTenantId();
|
||||||
|
$type->pid = isset($data['pid']) ? (int)$data['pid'] : 0;
|
||||||
|
$type->title = $title;
|
||||||
|
$type->desc = (string)($data['desc'] ?? '');
|
||||||
|
$type->sort = isset($data['sort']) ? (int)$data['sort'] : 0;
|
||||||
|
$type->create_time = date('Y-m-d H:i:s');
|
||||||
|
$type->update_time = date('Y-m-d H:i:s');
|
||||||
|
$type->save();
|
||||||
|
|
||||||
|
$this->logSuccess('产品分类管理', '添加分类', ['id' => $type->id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => $type->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('产品分类管理', '添加分类', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '添加失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新产品分类
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editProductsTypes(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$type = ProductsTypes::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$type) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '分类不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['title'])) $type->title = (string)$data['title'];
|
||||||
|
if (isset($data['pid'])) $type->pid = (int)$data['pid'];
|
||||||
|
if (isset($data['desc'])) $type->desc = (string)$data['desc'];
|
||||||
|
if (isset($data['sort'])) $type->sort = (int)$data['sort'];
|
||||||
|
|
||||||
|
if ((string)$type->title === '') {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '分类名称不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$type->update_time = date('Y-m-d H:i:s');
|
||||||
|
$type->save();
|
||||||
|
|
||||||
|
$this->logSuccess('产品分类管理', '更新分类', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $type->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('产品分类管理', '更新分类', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除产品分类(软删除)
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteProductsTypes(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$type = ProductsTypes::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$type) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '分类不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$type->delete();
|
||||||
|
|
||||||
|
$this->logSuccess('产品分类管理', '删除分类', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('产品分类管理', '删除分类', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Services;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\response\Json;
|
||||||
|
use app\model\Cms\Services;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色服务管理控制器
|
||||||
|
*/
|
||||||
|
class ServicesController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取特色服务列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function servicesList(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$page = (int)$this->request->param('page', 1);
|
||||||
|
$limit = (int)$this->request->param('limit', 10);
|
||||||
|
$keyword = $this->request->param('keyword', '');
|
||||||
|
|
||||||
|
$query = Services::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
|
// 关键词搜索
|
||||||
|
if (!empty($keyword)) {
|
||||||
|
$query->where('name', 'like', '%' . $keyword . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = $query->count();
|
||||||
|
$list = $query->order('sort', 'asc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->page($page, $limit)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => $total
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加特色服务
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function addServices(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$service = new Services();
|
||||||
|
$service->tid = $this->getTenantId();
|
||||||
|
$service->title = $data['title'];
|
||||||
|
$service->url = $data['url'];
|
||||||
|
$service->thumb = $data['thumb'] ?? '';
|
||||||
|
$service->desc = $data['desc'] ?? '';
|
||||||
|
$service->sort = $data['sort'] ?? 0;
|
||||||
|
$service->create_time = date('Y-m-d H:i:s');
|
||||||
|
$service->save();
|
||||||
|
|
||||||
|
$this->logSuccess('特色服务', '添加服务', ['id' => $service->id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => $service->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色服务', '添加服务', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '添加失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新特色服务
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editServices(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
$service = Services::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$service) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '服务不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['title'])) $service->title = $data['title'];
|
||||||
|
if (isset($data['url'])) $service->url = $data['url'];
|
||||||
|
if (isset($data['thumb'])) $service->thumb = $data['thumb'];
|
||||||
|
if (isset($data['desc'])) $service->desc = $data['desc'];
|
||||||
|
if (isset($data['sort'])) $service->sort = $data['sort'];
|
||||||
|
$service->update_time = date('Y-m-d H:i:s');
|
||||||
|
$service->save();
|
||||||
|
|
||||||
|
$this->logSuccess('特色服务', '更新服务', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $service->toArray()
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色服务', '更新服务', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除特色服务
|
||||||
|
* @param int $id
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteServices(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$service = Services::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$service) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '服务不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$service->delete();
|
||||||
|
|
||||||
|
$this->logSuccess('特色服务', '删除服务', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('特色服务', '删除服务', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Cms\Theme;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use app\service\ThemeService;
|
||||||
|
use think\facade\Request;
|
||||||
|
use app\model\Cms\TemplateSiteConfig;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板管理控制器
|
||||||
|
*/
|
||||||
|
class ThemeController extends BaseController
|
||||||
|
{
|
||||||
|
private ThemeService $themeService;
|
||||||
|
|
||||||
|
public function __construct(\think\App $app)
|
||||||
|
{
|
||||||
|
parent::__construct($app);
|
||||||
|
$this->themeService = new ThemeService();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模板列表(后台管理)
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
$themes = $this->themeService->getThemeList();
|
||||||
|
$currentTheme = $this->themeService->getCurrentTheme($tid);
|
||||||
|
|
||||||
|
$theme_useing = TemplateSiteConfig::where('tid', $tid)
|
||||||
|
->where('key', 'current_theme')
|
||||||
|
->value('value');
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'list' => $themes,
|
||||||
|
'currentTheme' => $currentTheme
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换模板
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function switch()
|
||||||
|
{
|
||||||
|
$tid = Request::post('tid', 0, 'int');
|
||||||
|
$themeKey = Request::post('theme_key', '');
|
||||||
|
|
||||||
|
if (empty($tid) || $tid == 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '未获取到租户ID,请先选择租户'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($themeKey)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '模板标识不能为空'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->themeService->switchTheme($tid, $themeKey);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '切换成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '切换失败,模板不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模板字段数据
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
$tid = Request::get('tid', 0, 'int');
|
||||||
|
$themeKey = Request::get('theme_key', '');
|
||||||
|
|
||||||
|
$themeData = $this->themeService->getThemeData($tid, $themeKey ?: null);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => $themeData
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存模板字段数据
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function saveData()
|
||||||
|
{
|
||||||
|
$tid = Request::post('tid', 0, 'int');
|
||||||
|
$themeKey = Request::post('theme_key', '');
|
||||||
|
$fieldKey = Request::post('field_key', '');
|
||||||
|
$fieldValue = Request::post('field_value', '');
|
||||||
|
|
||||||
|
if (empty($themeKey) || empty($fieldKey)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '参数不完整'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->themeService->saveThemeField($tid, $themeKey, $fieldKey, $fieldValue);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '保存成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '保存失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Erp;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\Erp\Employee;
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
|
class EmployeeController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取员工列表
|
||||||
|
*/
|
||||||
|
public function getEmployee()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = Employee::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取员工详情
|
||||||
|
*/
|
||||||
|
public function getEmployeeDetail($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$detail = Employee::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->find()
|
||||||
|
->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $detail
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建员工
|
||||||
|
*/
|
||||||
|
public function createEmployee()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->request->post();
|
||||||
|
$data['tid'] = $tid;
|
||||||
|
|
||||||
|
$employee = Employee::create($data);
|
||||||
|
if ($employee) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => $employee
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑员工
|
||||||
|
*/
|
||||||
|
public function editEmployee($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->request->post();
|
||||||
|
unset($data['tid']); // 不允许修改租户ID
|
||||||
|
|
||||||
|
$employee = Employee::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->update($data);
|
||||||
|
if ($employee !== false) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功',
|
||||||
|
'data' => $employee
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '编辑失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除员工
|
||||||
|
*/
|
||||||
|
public function deleteEmployee($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$employee = Employee::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
if ($employee) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Erp;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\Erp\Organization;
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
|
class OrganizationController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取组织机构列表
|
||||||
|
*/
|
||||||
|
public function getOrganization()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = Organization::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取组织机构详情
|
||||||
|
*/
|
||||||
|
public function getOrganizationDetail($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$detail = Organization::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->find()
|
||||||
|
->toArray();
|
||||||
|
$detail['leader_name'] = AdminUser::where('id', $detail['leader_id'])->value('name');
|
||||||
|
$detail['parent_name'] = Organization::where('id', $detail['parent_id'])->value('org_name');
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $detail
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建组织机构
|
||||||
|
*/
|
||||||
|
public function createOrganization()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->request->post();
|
||||||
|
$data['tid'] = $tid;
|
||||||
|
|
||||||
|
$organization = Organization::create($data);
|
||||||
|
if ($organization) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => $organization
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑组织机构
|
||||||
|
*/
|
||||||
|
public function editOrganization($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->request->post();
|
||||||
|
unset($data['tid']); // 不允许修改租户ID
|
||||||
|
|
||||||
|
$organization = Organization::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->update($data);
|
||||||
|
if ($organization !== false) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功',
|
||||||
|
'data' => $organization
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '编辑失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除组织机构
|
||||||
|
*/
|
||||||
|
public function deleteOrganization($id)
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$organization = Organization::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
if ($organization) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取企业单位
|
||||||
|
*/
|
||||||
|
public function getCompanys()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$where = [['delete_time', '=', null], ['is_company', '=', 1], ['tid', '=', $tid]];
|
||||||
|
|
||||||
|
$list = Organization::where($where)->select()->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取部门
|
||||||
|
*/
|
||||||
|
public function getDepartments()
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if (!$tid) {
|
||||||
|
return json(['code' => 403, 'msg' => '无法获取租户信息']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentId = input('parent_id/d', 0);
|
||||||
|
|
||||||
|
$where = [['delete_time', '=', null], ['is_company', '=', 0], ['tid', '=', $tid]];
|
||||||
|
|
||||||
|
if ($parentId > 0) {
|
||||||
|
$where[] = ['parent_id', '=', $parentId];
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = Organization::where($where)->select()->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $list
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ declare (strict_types = 1);
|
|||||||
namespace app\admin\controller;
|
namespace app\admin\controller;
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
|
|
||||||
|
|
||||||
class Index extends BaseController
|
class Index extends BaseController
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
|
|||||||
@@ -9,11 +9,19 @@ use think\exception\ValidateException;
|
|||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\facade\Cache;
|
use think\facade\Cache;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use app\model\AdminUser;
|
|
||||||
use app\service\JwtService;
|
use app\service\JwtService;
|
||||||
|
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
use app\model\System\AdminUserGroup;
|
||||||
|
use app\model\System\SystemSiteSettings;
|
||||||
|
use app\model\Tenant\Tenant;
|
||||||
|
use app\model\System\OperationLog;
|
||||||
|
|
||||||
class LoginController extends BaseController
|
class LoginController extends BaseController
|
||||||
{
|
{
|
||||||
|
private const SMS_CODE_TTL_SECONDS = 300; // 5分钟
|
||||||
|
private const SMS_CODE_RESEND_SECONDS = 60; // 60秒可重发
|
||||||
|
|
||||||
private function generateToken($userInfo): string
|
private function generateToken($userInfo): string
|
||||||
{
|
{
|
||||||
return JwtService::generateToken($userInfo);
|
return JwtService::generateToken($userInfo);
|
||||||
@@ -24,67 +32,176 @@ class LoginController extends BaseController
|
|||||||
return JwtService::verifyToken($token);
|
return JwtService::verifyToken($token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getSiteSettingValue(string $label): string
|
||||||
* 登录接口
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function login(): Json
|
|
||||||
{
|
{
|
||||||
$data = $this->request->param();
|
$row = SystemSiteSettings::where('label', $label)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->order('id', 'asc')
|
||||||
|
->find();
|
||||||
|
return $row ? (string)$row['value'] : '';
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($data['email'])) {
|
private function smsCodeCacheKey(string $scene, string $tenantName, string $account, string $phone): string
|
||||||
$data['account'] = $data['email'];
|
{
|
||||||
} elseif (isset($data['phone'])) {
|
return 'sms_code:' . md5($scene . '|' . $tenantName . '|' . $account . '|' . $phone);
|
||||||
$data['account'] = $data['phone'];
|
}
|
||||||
|
|
||||||
|
private function smsCodeThrottleKey(string $scene, string $tenantName, string $account, string $phone): string
|
||||||
|
{
|
||||||
|
return 'sms_code_throttle:' . md5($scene . '|' . $tenantName . '|' . $account . '|' . $phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function postJson(string $url, array $payload, array $headers): array
|
||||||
|
{
|
||||||
|
$body = json_encode($payload, JSON_UNESCAPED_UNICODE);
|
||||||
|
if ($body === false) {
|
||||||
|
return ['ok' => false, 'error' => 'json_encode failed'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$context = stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' => implode("\r\n", $headers),
|
||||||
|
'content' => $body,
|
||||||
|
'timeout' => 10,
|
||||||
|
'ignore_errors' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$respBody = @file_get_contents($url, false, $context);
|
||||||
|
$status = 0;
|
||||||
|
if (!empty($http_response_header) && is_array($http_response_header)) {
|
||||||
|
foreach ($http_response_header as $line) {
|
||||||
|
if (preg_match('#^HTTP/\\S+\\s+(\\d+)#', $line, $m)) {
|
||||||
|
$status = (int)$m[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($respBody === false) {
|
||||||
|
$last = error_get_last();
|
||||||
|
return ['ok' => false, 'status' => $status, 'error' => (string)($last['message'] ?? 'http request failed')];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = json_decode((string)$respBody, true);
|
||||||
|
if (!is_array($decoded)) {
|
||||||
|
$decoded = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ok' => $status >= 200 && $status < 300,
|
||||||
|
'status' => $status,
|
||||||
|
'body' => (string)$respBody,
|
||||||
|
'json' => $decoded,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendSmsCodeInternal(string $scene, string $tenantName, string $account, string $phone): Json
|
||||||
|
{
|
||||||
|
$throttleKey = $this->smsCodeThrottleKey($scene, $tenantName, $account, $phone);
|
||||||
|
if (Cache::has($throttleKey)) {
|
||||||
|
return json(['code' => 429, 'msg' => '验证码发送过于频繁,请稍后再试']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$backendUrl = $this->getSiteSettingValue('backendUrl');
|
||||||
|
$apiKey = $this->getSiteSettingValue('apiKey');
|
||||||
|
if ($backendUrl === '' || $apiKey === '') {
|
||||||
|
return json(['code' => 500, 'msg' => '短信网关配置缺失,请联系管理员']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = (string)random_int(100000, 999999);
|
||||||
|
$sceneTextMap = [
|
||||||
|
'register' => '注册',
|
||||||
|
'reset' => '找回密码',
|
||||||
|
'login' => '登录',
|
||||||
|
];
|
||||||
|
$sceneText = $sceneTextMap[$scene] ?? '验证';
|
||||||
|
$content = "【云泽网】{$sceneText}验证码:{$code},5分钟内有效。";
|
||||||
|
|
||||||
|
$enqueueUrl = rtrim($backendUrl, '/') . '/api/v1/business/outbound-tasks';
|
||||||
|
$resp = $this->postJson($enqueueUrl, [
|
||||||
|
'phone' => $phone,
|
||||||
|
'content' => $content,
|
||||||
|
], [
|
||||||
|
'X-Api-Key: ' . $apiKey,
|
||||||
|
'Content-Type: application/json; charset=utf-8',
|
||||||
|
'Accept: application/json',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (empty($resp['ok'])) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '验证码短信发送失败',
|
||||||
|
'detail' => [
|
||||||
|
'http_status' => $resp['status'] ?? null,
|
||||||
|
'body_preview' => isset($resp['body']) ? substr((string)$resp['body'], 0, 200) : '',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$codeKey = $this->smsCodeCacheKey($scene, $tenantName, $account, $phone);
|
||||||
|
Cache::set($codeKey, $code, self::SMS_CODE_TTL_SECONDS);
|
||||||
|
Cache::set($throttleKey, 1, self::SMS_CODE_RESEND_SECONDS);
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '验证码已发送']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildLoginSuccessResponse($user, $tenant): Json
|
||||||
|
{
|
||||||
|
$tid = (int)$tenant->id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->validate($data, [
|
$loginCount = isset($user['login_count']) && $user['login_count'] !== null ? (int)$user['login_count'] : 0;
|
||||||
'account|账号' => 'require|length:3,32',
|
AdminUser::where('id', $user['id'])->update([
|
||||||
'password|密码' => 'require|length:6,32'
|
'login_count' => $loginCount + 1,
|
||||||
]);
|
'last_login_ip' => $this->request->ip(),
|
||||||
} catch (ValidateException $e) {
|
'last_login_time' => date('Y-m-d H:i:s')
|
||||||
$this->logFail('登录管理', '登录', $e->getMessage());
|
|
||||||
return json([
|
|
||||||
'code' => 400,
|
|
||||||
'msg' => $e->getError()
|
|
||||||
]);
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('更新登录信息失败: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = AdminUser::where('account', $data['account'])
|
|
||||||
->where('status', 1)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
return json([
|
|
||||||
'code' => 401,
|
|
||||||
'msg' => '账号不存在或已禁用'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (md5($data['password']) !== $user['password']) {
|
|
||||||
return json([
|
|
||||||
'code' => 401,
|
|
||||||
'msg' => '密码错误'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
AdminUser::where('id', $user['id'])->update([
|
|
||||||
'login_count' => $user['login_count'] + 1,
|
|
||||||
'last_login_ip' => $this->request->ip()
|
|
||||||
]);
|
|
||||||
|
|
||||||
$userInfo = [
|
$userInfo = [
|
||||||
'id' => $user['id'],
|
'id' => $user['id'],
|
||||||
'account' => $user['account'],
|
'account' => $user['account'],
|
||||||
'name' => $user['name'],
|
'name' => $user['name'],
|
||||||
'group_id' => $user['group_id']
|
'group_id' => $user['group_id'],
|
||||||
|
'tid' => $tid,
|
||||||
|
'tenant' => $tenant
|
||||||
];
|
];
|
||||||
|
|
||||||
$token = $this->generateToken($userInfo);
|
if ($user['group_id']) {
|
||||||
|
$userGroup = AdminUserGroup::where('id', $user['group_id'])->find();
|
||||||
|
if ($userGroup && $userGroup->rights) {
|
||||||
|
$userInfo['rights'] = json_decode($userGroup->rights, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$token = $this->generateToken($userInfo);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('登录管理', '登录', 'Token生成失败: ' . $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '登录失败,请稍后重试']);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$cacheKey = 'admin_user_' . $user['id'] . '_' . $tid;
|
||||||
|
\think\facade\Cache::set($cacheKey, $userInfo, 86400 * 7);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('用户缓存写入失败: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->logSuccess('登录管理', '登录', [
|
||||||
|
'id' => $user['id'],
|
||||||
|
'tid' => $tid,
|
||||||
|
'tenant' => $tenant
|
||||||
|
], $userInfo);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('登录日志记录失败: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
$this->logSuccess('登录管理', '登录', ['id' => $user['id']], $userInfo);
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '登录成功',
|
'msg' => '登录成功',
|
||||||
@@ -95,6 +212,249 @@ class LoginController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录接口
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function login(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
// 1. 先验证租户名称是否传入(新增:必须传租户名称)
|
||||||
|
try {
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128', // 匹配租户表tenant字段长度
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'password|密码' => 'require|length:6,32'
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
$this->logFail('登录管理', '登录', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 处理账号兼容(邮箱/手机号转account)
|
||||||
|
if (isset($data['email'])) {
|
||||||
|
$data['account'] = $data['email'];
|
||||||
|
} elseif (isset($data['phone'])) {
|
||||||
|
$data['account'] = $data['phone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查询租户ID(新增:只查正常状态的租户 status=1)
|
||||||
|
$tenant = Tenant::where('tenant_name', $data['tenant_name'])
|
||||||
|
->where('status', 1) // 过滤停用/删除的租户
|
||||||
|
->field(['id', 'tenant_name']) // 只查需要的字段,提升性能
|
||||||
|
->find(); // ThinkPHP 使用 find()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 4. 验证租户是否存在
|
||||||
|
|
||||||
|
if (!$tenant) {
|
||||||
|
$this->logFail('登录管理', '登录', '租户不存在或已禁用,租户名称:' . $data['tenant_name']);
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '租户不存在或已禁用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$tid = $tenant->id;
|
||||||
|
$tenant_name = $tenant->tenant_name;
|
||||||
|
|
||||||
|
// 5. 查询用户(新增:关联租户ID,确保用户属于该租户)
|
||||||
|
$user = AdminUser::where('account', $data['account'])
|
||||||
|
->where('tid', $tid) // 核心:验证用户所属租户
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 6. 验证用户是否存在
|
||||||
|
if (!$user) {
|
||||||
|
$this->logFail('登录管理', '登录', '账号不存在/已禁用,或不属于当前租户,账号:' . $data['account'] . ',租户:' . $tenant_name);
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '账号不存在或已禁用,或不属于当前租户'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 验证密码
|
||||||
|
if (md5($data['password']) !== $user['password']) {
|
||||||
|
$this->logFail('登录管理', '登录', '密码错误,账号:' . $data['account'] . ',租户:' . $tenant_name);
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '密码错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 更新登录次数和IP
|
||||||
|
try {
|
||||||
|
$loginCount = isset($user['login_count']) && $user['login_count'] !== null ? (int)$user['login_count'] : 0;
|
||||||
|
AdminUser::where('id', $user['id'])->update([
|
||||||
|
'login_count' => $loginCount + 1,
|
||||||
|
'last_login_ip' => $this->request->ip(),
|
||||||
|
'last_login_time' => date('Y-m-d H:i:s') // 新增:记录最后登录时间,更实用
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('更新登录信息失败: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 组装用户信息(新增:加入租户ID和租户名称和角色权限)
|
||||||
|
$userInfo = [
|
||||||
|
'id' => $user['id'],
|
||||||
|
'account' => $user['account'],
|
||||||
|
'name' => $user['name'],
|
||||||
|
'group_id' => $user['group_id'],
|
||||||
|
'tid' => $tid, // 新增:租户ID
|
||||||
|
'tenant' => $tenant // 新增:租户名称
|
||||||
|
];
|
||||||
|
|
||||||
|
// 获取角色权限
|
||||||
|
if ($user['group_id']) {
|
||||||
|
$userGroup = AdminUserGroup::where('id', $user['group_id'])->find();
|
||||||
|
if ($userGroup && $userGroup->rights) {
|
||||||
|
$userInfo['rights'] = json_decode($userGroup->rights, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 生成Token(Token中已包含租户信息,后续可通过Token解析获取)
|
||||||
|
try {
|
||||||
|
$token = $this->generateToken($userInfo);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('登录管理', '登录', 'Token生成失败: ' . $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '登录失败,请稍后重试'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 11. 写入用户数据缓存(核心:缓存包含租户信息,示例用Redis,可根据你的缓存工具调整)
|
||||||
|
try {
|
||||||
|
$cacheKey = 'admin_user_' . $user['id'] . '_' . $tid; // 缓存键加入租户ID,避免多租户冲突
|
||||||
|
$cacheExpire = 86400 * 7; // 缓存7天,可根据需求调整
|
||||||
|
// 写入缓存(这里假设你使用thinkphp的Cache类,若用其他工具可替换)
|
||||||
|
\think\facade\Cache::set($cacheKey, $userInfo, $cacheExpire);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('用户缓存写入失败: ' . $e->getMessage());
|
||||||
|
// 缓存写入失败不影响登录,但记录日志
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12. 记录登录成功日志
|
||||||
|
try {
|
||||||
|
$this->logSuccess('登录管理', '登录', [
|
||||||
|
'id' => $user['id'],
|
||||||
|
'tid' => $tid,
|
||||||
|
'tenant' => $tenant
|
||||||
|
], $userInfo);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
error_log('登录日志记录失败: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13. 返回登录结果(包含租户信息)
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '登录成功',
|
||||||
|
'data' => [
|
||||||
|
'token' => $token,
|
||||||
|
'user' => $userInfo // 前端可直接获取租户ID和名称
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$errorMsg = $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine();
|
||||||
|
error_log('登录失败: ' . $errorMsg);
|
||||||
|
try {
|
||||||
|
$this->logFail('登录管理', '登录', $errorMsg);
|
||||||
|
} catch (\Exception $logError) {
|
||||||
|
error_log('记录登录失败日志也失败: ' . $logError->getMessage());
|
||||||
|
}
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '登录失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送手机号登录验证码
|
||||||
|
*/
|
||||||
|
public function sendLoginCode(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant = Tenant::where('tenant_name', (string)$data['tenant_name'])
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 400, 'msg' => '租户不存在或已禁用']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = AdminUser::where('tid', (int)$tenant['id'])
|
||||||
|
->where('phone', (string)$data['phone'])
|
||||||
|
->where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if (!$user) {
|
||||||
|
return json(['code' => 404, 'msg' => '手机号未绑定可用账号']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendSmsCodeInternal('login', (string)$data['tenant_name'], (string)$data['phone'], (string)$data['phone']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '发送失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号验证码登录
|
||||||
|
*/
|
||||||
|
public function loginBySms(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
'sms_code|短信验证码' => 'require|length:4,8',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$codeKey = $this->smsCodeCacheKey('login', (string)$data['tenant_name'], (string)$data['phone'], (string)$data['phone']);
|
||||||
|
$cachedCode = (string)Cache::get($codeKey, '');
|
||||||
|
if ($cachedCode === '' || $cachedCode !== (string)$data['sms_code']) {
|
||||||
|
return json(['code' => 400, 'msg' => '短信验证码错误或已过期']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tenant = Tenant::where('tenant_name', (string)$data['tenant_name'])
|
||||||
|
->where('status', 1)
|
||||||
|
->field(['id', 'tenant_name'])
|
||||||
|
->find();
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 401, 'msg' => '租户不存在或已禁用']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = AdminUser::where('tid', (int)$tenant['id'])
|
||||||
|
->where('phone', (string)$data['phone'])
|
||||||
|
->where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if (!$user) {
|
||||||
|
return json(['code' => 401, 'msg' => '手机号未绑定可用账号']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache::delete($codeKey);
|
||||||
|
return $this->buildLoginSuccessResponse($user, $tenant);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '登录失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出登录
|
* 退出登录
|
||||||
* @return Json
|
* @return Json
|
||||||
@@ -103,7 +463,7 @@ class LoginController extends BaseController
|
|||||||
{
|
{
|
||||||
$authHeader = $this->request->header('Authorization', '');
|
$authHeader = $this->request->header('Authorization', '');
|
||||||
$userInfo = null;
|
$userInfo = null;
|
||||||
|
|
||||||
if (preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
|
if (preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
|
||||||
$tokenData = $this->verifyToken($matches[1]);
|
$tokenData = $this->verifyToken($matches[1]);
|
||||||
if ($tokenData && isset($tokenData['user'])) {
|
if ($tokenData && isset($tokenData['user'])) {
|
||||||
@@ -114,7 +474,7 @@ class LoginController extends BaseController
|
|||||||
if ($userInfo && isset($userInfo['id'])) {
|
if ($userInfo && isset($userInfo['id'])) {
|
||||||
$this->logSuccess('登录管理', '退出登录', ['result' => 'success'], $userInfo);
|
$this->logSuccess('登录管理', '退出登录', ['result' => 'success'], $userInfo);
|
||||||
} else {
|
} else {
|
||||||
\app\model\OperationLog::create([
|
OperationLog::create([
|
||||||
'user_id' => 0,
|
'user_id' => 0,
|
||||||
'user_account' => '',
|
'user_account' => '',
|
||||||
'user_name' => '未知用户',
|
'user_name' => '未知用户',
|
||||||
@@ -145,7 +505,7 @@ class LoginController extends BaseController
|
|||||||
public function userInfo(): Json
|
public function userInfo(): Json
|
||||||
{
|
{
|
||||||
$authHeader = $this->request->header('Authorization', '');
|
$authHeader = $this->request->header('Authorization', '');
|
||||||
|
|
||||||
if (!preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
|
if (!preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 401,
|
'code' => 401,
|
||||||
@@ -154,7 +514,7 @@ class LoginController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tokenData = $this->verifyToken($matches[1]);
|
$tokenData = $this->verifyToken($matches[1]);
|
||||||
|
|
||||||
if (!$tokenData || !isset($tokenData['user'])) {
|
if (!$tokenData || !isset($tokenData['user'])) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 401,
|
'code' => 401,
|
||||||
@@ -183,9 +543,286 @@ class LoginController extends BaseController
|
|||||||
'data' => $userData->toArray()
|
'data' => $userData->toArray()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAdminUserFromToken(): array
|
public function getAdminUserFromToken(): array
|
||||||
{
|
{
|
||||||
return JwtService::getUserFromHeader($this->request->header('Authorization', ''));
|
return JwtService::getUserFromHeader($this->request->header('Authorization', ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function loginInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
$loginInfo = SystemSiteSettings::select();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $loginInfo
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册账号(按租户维度)
|
||||||
|
*/
|
||||||
|
public function sendRegisterCode(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
]);
|
||||||
|
return $this->sendSmsCodeInternal('register', (string)$data['tenant_name'], (string)$data['account'], (string)$data['phone']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '发送失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'name|姓名' => 'require|length:2,32',
|
||||||
|
'password|密码' => 'require|length:6,32',
|
||||||
|
'confirm_password|确认密码' => 'require',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
'sms_code|短信验证码' => 'require|length:4,8',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ((string)$data['password'] !== (string)$data['confirm_password']) {
|
||||||
|
return json(['code' => 400, 'msg' => '两次输入的密码不一致']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$codeKey = $this->smsCodeCacheKey('register', (string)$data['tenant_name'], (string)$data['account'], (string)$data['phone']);
|
||||||
|
$cachedCode = (string)Cache::get($codeKey, '');
|
||||||
|
if ($cachedCode === '' || $cachedCode !== (string)$data['sms_code']) {
|
||||||
|
return json(['code' => 400, 'msg' => '短信验证码错误或已过期']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tenant = Tenant::where('tenant_name', (string)$data['tenant_name'])
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 400, 'msg' => '租户不存在或已禁用']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$exists = AdminUser::where('tid', (int)$tenant['id'])
|
||||||
|
->where('account', (string)$data['account'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if ($exists) {
|
||||||
|
return json(['code' => 400, 'msg' => '账号已存在']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
$user = new AdminUser();
|
||||||
|
$user->save([
|
||||||
|
'tid' => (int)$tenant['id'],
|
||||||
|
'account' => (string)$data['account'],
|
||||||
|
'name' => (string)$data['name'],
|
||||||
|
'phone' => (string)$data['phone'],
|
||||||
|
'email' => (string)($data['email'] ?? ''),
|
||||||
|
'password' => md5((string)$data['password']),
|
||||||
|
'status' => 1,
|
||||||
|
'group_id' => 0,
|
||||||
|
'login_count' => 0,
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Cache::delete($codeKey);
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '注册成功']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '注册失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忘记密码:通过租户 + 账号 + 手机号重置密码
|
||||||
|
*/
|
||||||
|
public function sendResetCode(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant = Tenant::where('tenant_name', (string)$data['tenant_name'])
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 400, 'msg' => '租户不存在或已禁用']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = AdminUser::where('tid', (int)$tenant['id'])
|
||||||
|
->where('account', (string)$data['account'])
|
||||||
|
->where('phone', (string)$data['phone'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if (!$user) {
|
||||||
|
return json(['code' => 404, 'msg' => '账号不存在或手机号不匹配']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendSmsCodeInternal('reset', (string)$data['tenant_name'], (string)$data['account'], (string)$data['phone']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '发送失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetPassword(): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->post();
|
||||||
|
$this->validate($data, [
|
||||||
|
'tenant_name|租户名称' => 'require|length:1,128',
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'phone|手机号' => 'require|mobile',
|
||||||
|
'new_password|新密码' => 'require|length:6,32',
|
||||||
|
'confirm_password|确认密码' => 'require',
|
||||||
|
'sms_code|短信验证码' => 'require|length:4,8',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ((string)$data['new_password'] !== (string)$data['confirm_password']) {
|
||||||
|
return json(['code' => 400, 'msg' => '两次输入的密码不一致']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$codeKey = $this->smsCodeCacheKey('reset', (string)$data['tenant_name'], (string)$data['account'], (string)$data['phone']);
|
||||||
|
$cachedCode = (string)Cache::get($codeKey, '');
|
||||||
|
if ($cachedCode === '' || $cachedCode !== (string)$data['sms_code']) {
|
||||||
|
return json(['code' => 400, 'msg' => '短信验证码错误或已过期']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tenant = Tenant::where('tenant_name', (string)$data['tenant_name'])
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 400, 'msg' => '租户不存在或已禁用']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = AdminUser::where('tid', (int)$tenant['id'])
|
||||||
|
->where('account', (string)$data['account'])
|
||||||
|
->where('phone', (string)$data['phone'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if (!$user) {
|
||||||
|
return json(['code' => 404, 'msg' => '账号不存在或手机号不匹配']);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminUser::where('id', (int)$user['id'])->update([
|
||||||
|
'password' => md5((string)$data['new_password']),
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Cache::delete($codeKey);
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '密码重置成功']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '重置失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取极验3.0的id和key
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getGeetest3Infos()
|
||||||
|
{
|
||||||
|
// 定义你需要的 label 列表
|
||||||
|
$targetLabels = [
|
||||||
|
'geetest3ID',
|
||||||
|
'geetest3KEY'
|
||||||
|
];
|
||||||
|
|
||||||
|
$legalInfos = SystemSiteSettings::where('delete_time', null)
|
||||||
|
->whereIn('label', $targetLabels) // 仅筛选指定的 label
|
||||||
|
->field('label, value')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看极验3.0的id和key', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $legalInfos->toArray()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取极验4.0的id和key
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getGeetest4Infos()
|
||||||
|
{
|
||||||
|
// 定义你需要的 label 列表
|
||||||
|
$targetLabels = [
|
||||||
|
'geetest4ID',
|
||||||
|
'geetest4KEY'
|
||||||
|
];
|
||||||
|
|
||||||
|
$legalInfos = SystemSiteSettings::where('delete_time', null)
|
||||||
|
->whereIn('label', $targetLabels) // 仅筛选指定的 label
|
||||||
|
->field('label, value')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 转换为前端需要的格式
|
||||||
|
$data = [];
|
||||||
|
foreach ($legalInfos as $item) {
|
||||||
|
if ($item['label'] === 'geetest4ID') {
|
||||||
|
$data['captcha_id'] = $item['value'];
|
||||||
|
}
|
||||||
|
if ($item['label'] === 'geetest4KEY') {
|
||||||
|
$data['captcha_key'] = $item['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看极验4.0的id和key', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $data
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否开启验证
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getOpenVerify()
|
||||||
|
{
|
||||||
|
// 定义你需要的 label 列表
|
||||||
|
$targetLabels = [
|
||||||
|
'openVerify',
|
||||||
|
'verifyModel'
|
||||||
|
];
|
||||||
|
|
||||||
|
$legalInfos = SystemSiteSettings::where('delete_time', null)
|
||||||
|
->whereIn('label', $targetLabels) // 仅筛选指定的 label
|
||||||
|
->field('label, value')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $legalInfos->toArray()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use think\facade\Session;
|
|||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use app\model\SystemMenu;
|
use app\model\SystemMenu;
|
||||||
use app\model\AdminUser;
|
use app\model\System\AdminUser;
|
||||||
use app\model\AdminUserGroup;
|
use app\model\System\AdminUserGroup;
|
||||||
|
|
||||||
class MenuController extends BaseController
|
class MenuController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -69,6 +69,10 @@ class MenuController extends BaseController
|
|||||||
$userGroup = AdminUserGroup::where('id', $user['group_id'])
|
$userGroup = AdminUserGroup::where('id', $user['group_id'])
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
|
// 调试日志
|
||||||
|
error_log('getMenus - user group_id: ' . $user['group_id']);
|
||||||
|
error_log('getMenus - userGroup: ' . json_encode($userGroup));
|
||||||
|
|
||||||
// var_dump($userGroup);
|
// var_dump($userGroup);
|
||||||
|
|
||||||
if (!$userGroup) {
|
if (!$userGroup) {
|
||||||
@@ -81,8 +85,9 @@ class MenuController extends BaseController
|
|||||||
|
|
||||||
// 解析权限数组
|
// 解析权限数组
|
||||||
$menuIds = [];
|
$menuIds = [];
|
||||||
if (!empty($userGroup['rights'])) {
|
if ($userGroup->rights) {
|
||||||
$menuIds = is_array($userGroup['rights']) ? $userGroup['rights'] : json_decode($userGroup['rights'], true);
|
$decoded = json_decode($userGroup->rights, true);
|
||||||
|
$menuIds = is_array($decoded) ? $decoded : [];
|
||||||
}
|
}
|
||||||
// var_dump($menuIds);
|
// var_dump($menuIds);
|
||||||
|
|
||||||
@@ -95,11 +100,14 @@ class MenuController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取有权限的菜单及其所有父级菜单
|
||||||
|
$allMenuIds = $this->getMenuIdsWithParents($menuIds);
|
||||||
|
|
||||||
// 获取有权限的菜单
|
// 获取有权限的菜单
|
||||||
$menus = SystemMenu::where('delete_time', null)
|
$menus = SystemMenu::where('delete_time', null)
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
->whereIn('id', $menuIds)
|
->whereIn('id', $allMenuIds)
|
||||||
->field('id,pid,title,path,component_path,icon,sort')
|
->field('id,pid,title,path,component_path,icon,sort,is_visible')
|
||||||
->order('sort', 'asc')
|
->order('sort', 'asc')
|
||||||
->select();
|
->select();
|
||||||
|
|
||||||
@@ -253,6 +261,7 @@ class MenuController extends BaseController
|
|||||||
'title|菜单名称' => 'require|max:50',
|
'title|菜单名称' => 'require|max:50',
|
||||||
'type|菜单类型' => 'require|in:1,2,3',
|
'type|菜单类型' => 'require|in:1,2,3',
|
||||||
'status|菜单状态' => 'require|in:0,1',
|
'status|菜单状态' => 'require|in:0,1',
|
||||||
|
'is_visible|是否显示' => 'require|in:0,1',
|
||||||
'sort|排序号' => 'integer',
|
'sort|排序号' => 'integer',
|
||||||
'path|路由路径' => 'max:200',
|
'path|路由路径' => 'max:200',
|
||||||
'icon|菜单图标' => 'max:100',
|
'icon|菜单图标' => 'max:100',
|
||||||
@@ -266,6 +275,7 @@ class MenuController extends BaseController
|
|||||||
'title' => $data['title'],
|
'title' => $data['title'],
|
||||||
'type' => $data['type'],
|
'type' => $data['type'],
|
||||||
'status' => $data['status'] ?? 1,
|
'status' => $data['status'] ?? 1,
|
||||||
|
'is_visible' => $data['is_visible'] ?? 1,
|
||||||
'sort' => $data['sort'] ?? 0,
|
'sort' => $data['sort'] ?? 0,
|
||||||
'path' => $data['path'] ?? '',
|
'path' => $data['path'] ?? '',
|
||||||
'component_path' => $data['component_path'] ?? '',
|
'component_path' => $data['component_path'] ?? '',
|
||||||
@@ -280,6 +290,9 @@ class MenuController extends BaseController
|
|||||||
$result = SystemMenu::insertGetId($menuData);
|
$result = SystemMenu::insertGetId($menuData);
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
// 更新角色菜单权限
|
||||||
|
$this->updateRoleMenuPermissions((int)$result, 'create');
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('菜单管理', '创建菜单', ['id' => $result]);
|
$this->logSuccess('菜单管理', '创建菜单', ['id' => $result]);
|
||||||
return json([
|
return json([
|
||||||
@@ -318,6 +331,7 @@ class MenuController extends BaseController
|
|||||||
'pid|上级菜单ID' => 'integer',
|
'pid|上级菜单ID' => 'integer',
|
||||||
'type|菜单类型' => 'require|in:1,2,3',
|
'type|菜单类型' => 'require|in:1,2,3',
|
||||||
'status|菜单状态' => 'require|in:0,1',
|
'status|菜单状态' => 'require|in:0,1',
|
||||||
|
'is_visible|是否显示' => 'require|in:0,1',
|
||||||
'sort|排序号' => 'integer',
|
'sort|排序号' => 'integer',
|
||||||
'path|路由路径' => 'max:200',
|
'path|路由路径' => 'max:200',
|
||||||
'icon|菜单图标' => 'max:100',
|
'icon|菜单图标' => 'max:100',
|
||||||
@@ -335,6 +349,7 @@ class MenuController extends BaseController
|
|||||||
'icon' => $data['icon'] ?? null,
|
'icon' => $data['icon'] ?? null,
|
||||||
'sort' => $data['sort'] ?? 0,
|
'sort' => $data['sort'] ?? 0,
|
||||||
'status' => $data['status'],
|
'status' => $data['status'],
|
||||||
|
'is_visible' => $data['is_visible'],
|
||||||
'permission' => $data['permission'] ?? null,
|
'permission' => $data['permission'] ?? null,
|
||||||
'remark' => $data['remark'] ?? null,
|
'remark' => $data['remark'] ?? null,
|
||||||
'update_time' => date('Y-m-d H:i:s')
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
@@ -343,6 +358,9 @@ class MenuController extends BaseController
|
|||||||
// 执行更新
|
// 执行更新
|
||||||
SystemMenu::where('id', $id)->update($updateData);
|
SystemMenu::where('id', $id)->update($updateData);
|
||||||
|
|
||||||
|
// 更新角色菜单权限
|
||||||
|
$this->updateRoleMenuPermissions($id, 'update');
|
||||||
|
|
||||||
// 获取更新后的菜单信息
|
// 获取更新后的菜单信息
|
||||||
$menu = SystemMenu::where('id', $id)->find();
|
$menu = SystemMenu::where('id', $id)->find();
|
||||||
|
|
||||||
@@ -405,6 +423,9 @@ class MenuController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新角色菜单权限(从所有角色中移除该菜单)
|
||||||
|
$this->updateRoleMenuPermissions($id, 'delete');
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('菜单管理', '删除菜单', ['id' => $id]);
|
$this->logSuccess('菜单管理', '删除菜单', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
@@ -421,6 +442,95 @@ class MenuController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新角色菜单权限
|
||||||
|
* @param int $menuId 菜单ID
|
||||||
|
* @param string $action 操作类型: create, update, delete
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateRoleMenuPermissions(int $menuId, string $action = 'update'): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取所有角色
|
||||||
|
$roles = AdminUserGroup::where('delete_time', null)->select();
|
||||||
|
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
// 解析权限数据,如果rights为空,初始化为空数组
|
||||||
|
$rights = empty($role->rights) ? [] : json_decode($role->rights, true);
|
||||||
|
if (!is_array($rights)) {
|
||||||
|
$rights = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated = false;
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'create':
|
||||||
|
case 'update':
|
||||||
|
// 创建或更新菜单时,自动添加到所有角色的权限中
|
||||||
|
if (!in_array($menuId, $rights)) {
|
||||||
|
$rights[] = $menuId;
|
||||||
|
$updated = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// 删除菜单时,从所有角色的权限中移除该菜单ID
|
||||||
|
if (in_array($menuId, $rights)) {
|
||||||
|
$rights = array_diff($rights, [$menuId]);
|
||||||
|
$rights = array_values($rights); // 重新索引数组
|
||||||
|
$updated = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果权限有变化,更新角色
|
||||||
|
if ($updated) {
|
||||||
|
$role->rights = !empty($rights) ? json_encode($rights) : null;
|
||||||
|
$role->update_time = date('Y-m-d H:i:s');
|
||||||
|
$role->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 记录错误日志但不中断主流程
|
||||||
|
$this->logFail('菜单管理', '更新角色菜单权限', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单ID及其所有父级菜单ID
|
||||||
|
* @param array $menuIds 菜单ID数组
|
||||||
|
* @return array 包含所有父级菜单的ID数组
|
||||||
|
*/
|
||||||
|
private function getMenuIdsWithParents(array $menuIds): array
|
||||||
|
{
|
||||||
|
if (empty($menuIds)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$allIds = $menuIds;
|
||||||
|
$toCheck = $menuIds;
|
||||||
|
|
||||||
|
while (!empty($toCheck)) {
|
||||||
|
// 查询这些菜单的父级
|
||||||
|
$parents = SystemMenu::whereIn('id', $toCheck)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->column('pid');
|
||||||
|
|
||||||
|
// 过滤掉已经存在的和为0的父ID
|
||||||
|
$newParents = [];
|
||||||
|
foreach ($parents as $pid) {
|
||||||
|
if ($pid > 0 && !in_array($pid, $allIds)) {
|
||||||
|
$newParents[] = $pid;
|
||||||
|
$allIds[] = $pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$toCheck = $newParents;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $allIds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建菜单树形结构
|
* 构建菜单树形结构
|
||||||
* @param array $menus 菜单列表
|
* @param array $menus 菜单列表
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
|
||||||
|
use app\model\SystemModuleCenter;
|
||||||
|
use app\model\SystemModuleCategory;
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
|
class ModuleCenterController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取模块中心分类
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getModuleCategory()
|
||||||
|
{
|
||||||
|
$cates = SystemModuleCategory::where('delete_time', null)->field('id, title, status')->select()->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $cates,
|
||||||
|
'total' => count($cates)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模块中心列表
|
||||||
|
* @param int $cid 分类ID,0表示全部
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getModuleList(int $cid = 0)
|
||||||
|
{
|
||||||
|
$query = SystemModuleCenter::where('delete_time', null)
|
||||||
|
->field('id, title, desc, thumb, cid, downloads, author, status, version, create_time');
|
||||||
|
|
||||||
|
// 如果cid不为0,则按分类筛选
|
||||||
|
if ($cid > 0) {
|
||||||
|
$query->where('cid', $cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = $query->select()->toArray();
|
||||||
|
|
||||||
|
// 遍历列表,将cid替换为分类标题
|
||||||
|
foreach ($list as &$item) {
|
||||||
|
if ($item['cid']) {
|
||||||
|
$category = SystemModuleCategory::where('id', $item['cid'])->field('title')->find();
|
||||||
|
$item['cid'] = $category ? $category['title'] : '';
|
||||||
|
}
|
||||||
|
if ($item['author']) {
|
||||||
|
$author = AdminUser::where('id', $item['author'])->field('name')->find();
|
||||||
|
$item['author'] = $author ? $author['name'] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $list,
|
||||||
|
'total' => count($list)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑分类(添加/编辑)
|
||||||
|
* @param int $id 分类ID,为空时新增,有值时编辑
|
||||||
|
*/
|
||||||
|
public function editCategory(int $id = 0)
|
||||||
|
{
|
||||||
|
$data = request()->param();
|
||||||
|
|
||||||
|
// 过滤只保留数据库表需要的字段
|
||||||
|
$allowedFields = ['id', 'title', 'status'];
|
||||||
|
$saveData = [];
|
||||||
|
foreach ($allowedFields as $field) {
|
||||||
|
if (isset($data[$field])) {
|
||||||
|
$saveData[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id > 0) {
|
||||||
|
// 编辑模式
|
||||||
|
$saveData['update_time'] = date('Y-m-d H:i:s');
|
||||||
|
SystemModuleCategory::where('id', $id)->update($saveData);
|
||||||
|
$this->logSuccess('模块市场', '编辑模块分类', ['id' => $id, 'data' => $saveData]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功'
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// 新增模式
|
||||||
|
$saveData['create_time'] = date('Y-m-d H:i:s');
|
||||||
|
$cateId = SystemModuleCategory::insertGetId($saveData);
|
||||||
|
$this->logSuccess('模块市场', '添加模块分类', ['data' => $saveData]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑模块(添加/编辑)
|
||||||
|
* @param int $id 为空时新增,有值时编辑
|
||||||
|
*/
|
||||||
|
public function editModules(int $id = 0)
|
||||||
|
{
|
||||||
|
$data = request()->param();
|
||||||
|
|
||||||
|
// 过滤只保留数据库表需要的字段
|
||||||
|
$allowedFields = ['id', 'title', 'desc', 'thumb', 'cid', 'version', 'tatus'];
|
||||||
|
$saveData = [];
|
||||||
|
foreach ($allowedFields as $field) {
|
||||||
|
if (isset($data[$field])) {
|
||||||
|
$saveData[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id > 0) {
|
||||||
|
// 编辑模式
|
||||||
|
$saveData['update_time'] = date('Y-m-d H:i:s');
|
||||||
|
SystemModuleCenter::where('id', $id)->update($saveData);
|
||||||
|
$this->logSuccess('模块市场', '编辑模块', ['id' => $id, 'data' => $saveData]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功'
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// 新增模式
|
||||||
|
$saveData['create_time'] = date('Y-m-d H:i:s');
|
||||||
|
$moduleId = SystemModuleCenter::insertGetId($saveData);
|
||||||
|
$this->logSuccess('模块市场', '添加模块', ['data' => $saveData]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,9 @@ namespace app\admin\controller;
|
|||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use app\model\AdminModules;
|
use app\model\AdminModules;
|
||||||
|
use app\model\System\AdminUserGroup;
|
||||||
|
use app\model\SystemMenu;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
|
|
||||||
class ModulesController extends BaseController
|
class ModulesController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -43,13 +46,77 @@ class ModulesController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取租户模块列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getTenantList()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userInfo = $this->getAdminUserInfo();
|
||||||
|
$groupId = $userInfo['group_id'] ?? null;
|
||||||
|
$menuIds = [];
|
||||||
|
|
||||||
|
if ($groupId) {
|
||||||
|
$userGroup = AdminUserGroup::where('id', $groupId)->find();
|
||||||
|
if ($userGroup && $userGroup->rights) {
|
||||||
|
$rights = $userGroup->rights;
|
||||||
|
$decoded = json_decode($rights, true);
|
||||||
|
$menuIds = is_array($decoded) ? $decoded : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($menuIds)) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => [],
|
||||||
|
'total' => 0
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据子菜单ID查询所有父级模块ID
|
||||||
|
$moduleIds = $this->getModuleIdsByMenuIds($menuIds);
|
||||||
|
|
||||||
|
$modules = AdminModules::where('delete_time', null)
|
||||||
|
->whereIn('id', $moduleIds)
|
||||||
|
->where('status', 1)
|
||||||
|
->where('is_show', 1)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->order('id', 'asc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$this->logSuccess('模块管理', '获取模块列表', ['count' => count($modules)]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $modules,
|
||||||
|
'total' => count($modules)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('模块管理', '获取模块列表', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模块详情
|
* 获取模块详情
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getDetail(int $id)
|
public function getDetail($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$id = (int) $id;
|
||||||
$module = AdminModules::where('id', $id)
|
$module = AdminModules::where('id', $id)
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
@@ -92,6 +159,7 @@ class ModulesController extends BaseController
|
|||||||
'description' => input('post.description', '', 'trim'),
|
'description' => input('post.description', '', 'trim'),
|
||||||
'icon' => input('post.icon', '', 'trim'),
|
'icon' => input('post.icon', '', 'trim'),
|
||||||
'path' => input('post.path', '', 'trim'),
|
'path' => input('post.path', '', 'trim'),
|
||||||
|
'type' => input('post.type', '', 'trim'),
|
||||||
'sort' => (int)input('post.sort', 0),
|
'sort' => (int)input('post.sort', 0),
|
||||||
'status' => (int)input('post.status', 1),
|
'status' => (int)input('post.status', 1),
|
||||||
'is_show' => (int)input('post.is_show', 1),
|
'is_show' => (int)input('post.is_show', 1),
|
||||||
@@ -161,6 +229,7 @@ class ModulesController extends BaseController
|
|||||||
'description' => input('post.description', '', 'trim'),
|
'description' => input('post.description', '', 'trim'),
|
||||||
'icon' => input('post.icon', '', 'trim'),
|
'icon' => input('post.icon', '', 'trim'),
|
||||||
'path' => input('post.path', '', 'trim'),
|
'path' => input('post.path', '', 'trim'),
|
||||||
|
'type' => input('post.type', '', 'trim'),
|
||||||
'sort' => (int)input('post.sort', 0),
|
'sort' => (int)input('post.sort', 0),
|
||||||
'status' => (int)input('post.status', 1),
|
'status' => (int)input('post.status', 1),
|
||||||
'is_show' => (int)input('post.is_show', 1),
|
'is_show' => (int)input('post.is_show', 1),
|
||||||
@@ -323,6 +392,64 @@ class ModulesController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据菜单ID列表获取对应的模块ID列表(包括父级模块)
|
||||||
|
* @param array $menuIds 菜单ID列表(子菜单)
|
||||||
|
* @return array 模块ID列表
|
||||||
|
*/
|
||||||
|
private function getModuleIdsByMenuIds(array $menuIds): array
|
||||||
|
{
|
||||||
|
if (empty($menuIds)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取所有子菜单及其父级菜单ID
|
||||||
|
$allMenuIds = $this->getMenuIdsWithParents($menuIds);
|
||||||
|
|
||||||
|
// 2. 获取所有匹配的模块(mid在allMenuIds中)
|
||||||
|
$moduleIds = AdminModules::where('delete_time', null)
|
||||||
|
->whereIn('mid', $allMenuIds)
|
||||||
|
->column('id');
|
||||||
|
|
||||||
|
// 去重并返回
|
||||||
|
return array_unique($moduleIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单ID及其所有父级菜单ID
|
||||||
|
* @param array $menuIds 菜单ID数组
|
||||||
|
* @return array 包含所有父级菜单的ID数组
|
||||||
|
*/
|
||||||
|
private function getMenuIdsWithParents(array $menuIds): array
|
||||||
|
{
|
||||||
|
if (empty($menuIds)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$allIds = $menuIds;
|
||||||
|
$toCheck = $menuIds;
|
||||||
|
|
||||||
|
while (!empty($toCheck)) {
|
||||||
|
// 查询这些菜单的父级
|
||||||
|
$parents = SystemMenu::whereIn('id', $toCheck)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->column('pid');
|
||||||
|
|
||||||
|
// 过滤掉已经存在的和为0的父ID
|
||||||
|
$newParents = [];
|
||||||
|
foreach ($parents as $pid) {
|
||||||
|
if ($pid > 0 && !in_array($pid, $allIds)) {
|
||||||
|
$newParents[] = $pid;
|
||||||
|
$allIds[] = $pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$toCheck = $newParents;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $allIds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模块选择列表
|
* 获取模块选择列表
|
||||||
* @return Json
|
* @return Json
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ namespace app\admin\controller\OperationLog;
|
|||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\facade\Request;
|
use think\facade\Request;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use app\model\OperationLog;
|
use app\model\System\OperationLog;
|
||||||
use app\model\AdminUser;
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
class OperationLogController extends BaseController
|
class OperationLogController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -28,7 +28,8 @@ class OperationLogController extends BaseController
|
|||||||
$startTime = Request::param('startTime/s', '');
|
$startTime = Request::param('startTime/s', '');
|
||||||
$endTime = Request::param('endTime/s', '');
|
$endTime = Request::param('endTime/s', '');
|
||||||
|
|
||||||
$query = OperationLog::where('delete_time', null);
|
$query = OperationLog::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
// 关键词搜索(用户姓名、URL)
|
// 关键词搜索(用户姓名、URL)
|
||||||
if ($keyword) {
|
if ($keyword) {
|
||||||
@@ -129,6 +130,7 @@ class OperationLogController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$log = OperationLog::where('id', $id)
|
$log = OperationLog::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -164,6 +166,7 @@ class OperationLogController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$log = OperationLog::where('id', $id)
|
$log = OperationLog::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
@@ -206,6 +209,7 @@ class OperationLogController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
OperationLog::whereIn('id', $ids)
|
OperationLog::whereIn('id', $ids)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->delete();
|
->delete();
|
||||||
|
|
||||||
@@ -230,11 +234,13 @@ class OperationLogController extends BaseController
|
|||||||
try {
|
try {
|
||||||
// 获取模块列表
|
// 获取模块列表
|
||||||
$modules = OperationLog::where('delete_time', null)
|
$modules = OperationLog::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->group('module')
|
->group('module')
|
||||||
->column('module');
|
->column('module');
|
||||||
|
|
||||||
// 获取动作列表
|
// 获取动作列表
|
||||||
$actions = OperationLog::where('delete_time', null)
|
$actions = OperationLog::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->group('action')
|
->group('action')
|
||||||
->column('action');
|
->column('action');
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace app\admin\controller\OperationLog;
|
namespace app\admin\controller\OperationLog;
|
||||||
|
|
||||||
use app\model\OperationLog;
|
use app\model\System\OperationLog;
|
||||||
use think\facade\Request;
|
use think\facade\Request;
|
||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ class OperationLogHelper
|
|||||||
$userId = $userInfo['id'] ?? 0;
|
$userId = $userInfo['id'] ?? 0;
|
||||||
$userAccount = $userInfo['account'] ?? '';
|
$userAccount = $userInfo['account'] ?? '';
|
||||||
$userName = $userInfo['name'] ?? '';
|
$userName = $userInfo['name'] ?? '';
|
||||||
|
$tid = $userInfo['tid'] ?? ($userInfo['tid'] ?? 0);
|
||||||
|
|
||||||
// 获取请求信息
|
// 获取请求信息
|
||||||
$method = Request::method();
|
$method = Request::method();
|
||||||
@@ -52,6 +53,7 @@ class OperationLogHelper
|
|||||||
'user_id' => $userId,
|
'user_id' => $userId,
|
||||||
'user_account' => $userAccount,
|
'user_account' => $userAccount,
|
||||||
'user_name' => $userName,
|
'user_name' => $userName,
|
||||||
|
'tid' => $tid,
|
||||||
'module' => $module,
|
'module' => $module,
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
'method' => $method,
|
'method' => $method,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace app\admin\controller\OperationLog;
|
namespace app\admin\controller\OperationLog;
|
||||||
|
|
||||||
use think\facade\Request;
|
use think\facade\Request;
|
||||||
use app\model\OperationLog;
|
use app\model\System\OperationLog;
|
||||||
use app\service\JwtService;
|
use app\service\JwtService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +33,7 @@ class OperationLogger
|
|||||||
$userId = $userInfo['id'] ?? 0;
|
$userId = $userInfo['id'] ?? 0;
|
||||||
$userAccount = $userInfo['account'] ?? '';
|
$userAccount = $userInfo['account'] ?? '';
|
||||||
$userName = $userInfo['name'] ?? '';
|
$userName = $userInfo['name'] ?? '';
|
||||||
|
$tid = $userInfo['tid'] ?? ($userInfo['tid'] ?? 0);
|
||||||
|
|
||||||
if (empty($requestData)) {
|
if (empty($requestData)) {
|
||||||
$requestData = Request::param();
|
$requestData = Request::param();
|
||||||
@@ -49,6 +50,7 @@ class OperationLogger
|
|||||||
'user_id' => $userId,
|
'user_id' => $userId,
|
||||||
'user_account' => $userAccount,
|
'user_account' => $userAccount,
|
||||||
'user_name' => $userName,
|
'user_name' => $userName,
|
||||||
|
'tid' => $tid,
|
||||||
'module' => $module,
|
'module' => $module,
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
'method' => $method,
|
'method' => $method,
|
||||||
|
|||||||
@@ -8,24 +8,59 @@ use app\admin\BaseController;
|
|||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use app\model\SystemSiteSettings;
|
use app\model\System\SystemSiteSetting;
|
||||||
|
use app\model\System\SystemSiteSettings;
|
||||||
|
use app\model\Tenant\Tenant;
|
||||||
|
|
||||||
class SiteSettingsController extends BaseController
|
class SiteSettingsController extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 获取所有站点设置列表
|
* 获取指定站点设置列表
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getNormalInfos()
|
public function getNormalInfos()
|
||||||
{
|
{
|
||||||
$siteSettings = SystemSiteSettings::where('delete_time', null)
|
// 获取当前租户ID
|
||||||
->field('id, label, value, sort')
|
$tid = $this->request->param('tid', 0, 'int');
|
||||||
->order('id', 'asc')
|
|
||||||
->select();
|
// 查询站点设置
|
||||||
|
$siteSetting = SystemSiteSetting::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 如果没有数据,返回空值结构
|
||||||
|
if (!$siteSetting) {
|
||||||
|
$data = [
|
||||||
|
'sitename' => '',
|
||||||
|
'logo' => '',
|
||||||
|
'logow' => '',
|
||||||
|
'ico' => '',
|
||||||
|
'companyintroduction' => '',
|
||||||
|
'description' => '',
|
||||||
|
'copyright' => '',
|
||||||
|
'companyname' => '',
|
||||||
|
'icp' => ''
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$data = [
|
||||||
|
'sitename' => $siteSetting->sitename ?? '',
|
||||||
|
'logo' => $siteSetting->logo ?? '',
|
||||||
|
'logow' => $siteSetting->logow ?? '',
|
||||||
|
'ico' => $siteSetting->ico ?? '',
|
||||||
|
'companyintroduction' => $siteSetting->companyintroduction ?? '',
|
||||||
|
'description' => $siteSetting->description ?? '',
|
||||||
|
'copyright' => $siteSetting->copyright ?? '',
|
||||||
|
'companyname' => $siteSetting->companyname ?? '',
|
||||||
|
'icp' => $siteSetting->icp ?? ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看基本信息配置', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '获取成功',
|
'msg' => '获取成功',
|
||||||
'data' => $siteSettings->toArray()
|
'data' => $data
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,65 +71,137 @@ class SiteSettingsController extends BaseController
|
|||||||
public function saveNormalInfos()
|
public function saveNormalInfos()
|
||||||
{
|
{
|
||||||
$params = $this->request->param();
|
$params = $this->request->param();
|
||||||
|
$rawData = isset($params['data']) ? json_decode($params['data'], true) : $params;
|
||||||
|
$tid = $params['tid'] ?? 0;
|
||||||
|
|
||||||
if (!isset($params['data']) || empty($params['data'])) {
|
// 查找或创建记录
|
||||||
return json(['code' => 400, 'msg' => '数据不能为空', 'data' => null]);
|
$siteSetting = SystemSiteSetting::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$siteSetting) {
|
||||||
|
$siteSetting = new SystemSiteSetting();
|
||||||
|
$siteSetting->tid = $tid;
|
||||||
|
$siteSetting->create_time = date('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = json_decode($params['data'], true);
|
// 更新字段
|
||||||
if (!is_array($data)) {
|
if (isset($rawData['sitename'])) {
|
||||||
return json(['code' => 400, 'msg' => '数据格式错误', 'data' => null]);
|
$siteSetting->sitename = (string)$rawData['sitename'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['companyintroduction'])) {
|
||||||
|
$siteSetting->companyintroduction = (string)$rawData['companyintroduction'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['logo'])) {
|
||||||
|
$siteSetting->logo = (string)$rawData['logo'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['logow'])) {
|
||||||
|
$siteSetting->logow = (string)$rawData['logow'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['ico'])) {
|
||||||
|
$siteSetting->ico = (string)$rawData['ico'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['description'])) {
|
||||||
|
$siteSetting->description = (string)$rawData['description'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['copyright'])) {
|
||||||
|
$siteSetting->copyright = (string)$rawData['copyright'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['companyname'])) {
|
||||||
|
$siteSetting->companyname = (string)$rawData['companyname'];
|
||||||
|
}
|
||||||
|
if (isset($rawData['icp'])) {
|
||||||
|
$siteSetting->icp = (string)$rawData['icp'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $item) {
|
$siteSetting->update_time = date('Y-m-d H:i:s');
|
||||||
if (!isset($item['label']) || !isset($item['value'])) {
|
$siteSetting->save();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$label = $item['label'];
|
$this->logSuccess('站点设置管理', '保存基本信息', ['tid' => $tid], $this->getAdminUserInfo());
|
||||||
$value = $item['value'] ?? '';
|
|
||||||
|
|
||||||
$setting = SystemSiteSettings::where('label', $label)->find();
|
return json(['code' => 200, 'msg' => '基本信息保存成功']);
|
||||||
if ($setting) {
|
}
|
||||||
$setting->value = $value;
|
|
||||||
$setting->save();
|
/**
|
||||||
} else {
|
* 获取登录验证数据
|
||||||
SystemSiteSettings::create([
|
* @return Json
|
||||||
'label' => $label,
|
*/
|
||||||
'value' => $value,
|
public function getVerifyInfos()
|
||||||
'create_time' => date('Y-m-d H:i:s')
|
{
|
||||||
]);
|
// 定义你需要的 label 列表
|
||||||
}
|
$targetLabels = [
|
||||||
}
|
'openVerify',
|
||||||
|
'verifyModel',
|
||||||
|
'geetest3ID',
|
||||||
|
'geetest3KEY',
|
||||||
|
'geetest4ID',
|
||||||
|
'geetest4KEY'
|
||||||
|
];
|
||||||
|
|
||||||
|
$legalInfos = SystemSiteSettings::where('delete_time', null)
|
||||||
|
->whereIn('label', $targetLabels) // 仅筛选指定的 label
|
||||||
|
->field('label, value')
|
||||||
|
->select();
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看登录验证数据', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
$allSettings = SystemSiteSettings::column('value', 'label');
|
|
||||||
$allSettings['type'] = 'normal';
|
|
||||||
|
|
||||||
$labels = array_column($data, 'label');
|
|
||||||
$userInfo = $this->getAdminUserInfo();
|
|
||||||
$this->logSuccess('站点设置管理', '保存基本信息', ['labels' => $labels], $userInfo);
|
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '保存成功',
|
'msg' => '获取成功',
|
||||||
'data' => $allSettings
|
'data' => $legalInfos->toArray()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有站点设置列表
|
* 保存登录验证数据
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function saveVerifyInfos()
|
||||||
|
{
|
||||||
|
$params = $this->request->param();
|
||||||
|
$allowedLabels = ['openVerify', 'verifyModel', 'geetest3ID', 'geetest3KEY', 'geetest4ID', 'geetest4KEY'];
|
||||||
|
|
||||||
|
foreach ($allowedLabels as $label) {
|
||||||
|
if (isset($params[$label])) {
|
||||||
|
$val = $params[$label];
|
||||||
|
if (is_bool($val)) {
|
||||||
|
$val = $val ? '1' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemSiteSettings::where('label', $label)->update([
|
||||||
|
'value' => (string)$val
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '保存登录验证配置', $params, $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '保存成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取法律声明和隐私条款
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getLegalInfos()
|
public function getLegalInfos()
|
||||||
{
|
{
|
||||||
$siteSettings = SystemSiteSettings::where('delete_time', null)
|
// 定义你需要的 label 列表
|
||||||
->field('id, label, value, sort')
|
$targetLabels = [
|
||||||
->order('id', 'asc')
|
'legalNotice',
|
||||||
|
'privacyTerms'
|
||||||
|
];
|
||||||
|
|
||||||
|
$legalInfos = SystemSiteSettings::where('delete_time', null)
|
||||||
|
->whereIn('label', $targetLabels) // 仅筛选指定的 label
|
||||||
|
->field('label, value')
|
||||||
->select();
|
->select();
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看法律声明和隐私条款', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '获取成功',
|
'msg' => '获取成功',
|
||||||
'data' => $siteSettings->toArray()
|
'data' => $legalInfos->toArray()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,58 +212,175 @@ class SiteSettingsController extends BaseController
|
|||||||
public function saveLegalInfos()
|
public function saveLegalInfos()
|
||||||
{
|
{
|
||||||
$params = $this->request->param();
|
$params = $this->request->param();
|
||||||
|
$rawData = isset($params['data']) ? json_decode($params['data'], true) : $params;
|
||||||
|
$allowedLabels = ['legalNotice', 'privacyTerms'];
|
||||||
|
|
||||||
if (!isset($params['data']) || empty($params['data'])) {
|
foreach ($allowedLabels as $label) {
|
||||||
return json(['code' => 400, 'msg' => '数据不能为空', 'data' => null]);
|
if (isset($rawData[$label])) {
|
||||||
}
|
SystemSiteSettings::update(
|
||||||
|
['value' => (string)$rawData[$label]],
|
||||||
$data = json_decode($params['data'], true);
|
['label' => $label]
|
||||||
if (!is_array($data)) {
|
);
|
||||||
return json(['code' => 400, 'msg' => '数据格式错误', 'data' => null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if (!isset($item['label']) || !isset($item['value'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$label = $item['label'];
|
|
||||||
$value = $item['value'] ?? '';
|
|
||||||
|
|
||||||
$setting = SystemSiteSettings::where('label', $label)->find();
|
|
||||||
if ($setting) {
|
|
||||||
$setting->value = $value;
|
|
||||||
$setting->save();
|
|
||||||
} else {
|
|
||||||
SystemSiteSettings::create([
|
|
||||||
'label' => $label,
|
|
||||||
'value' => $value,
|
|
||||||
'create_time' => date('Y-m-d H:i:s')
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '保存法律声明和隐私条款', ['labels' => $allowedLabels], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '法律声明和隐私条款保存成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取企业信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getCompanyInfos()
|
||||||
|
{
|
||||||
|
// 获取当前租户ID
|
||||||
|
$tid = $this->request->param('tid', 0, 'int');
|
||||||
|
|
||||||
|
// 查询租户信息
|
||||||
|
$tenant = Tenant::where('delete_time', null)
|
||||||
|
->where('id', $tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 如果没有数据,返回空值结构
|
||||||
|
if (!$tenant) {
|
||||||
|
$data = [
|
||||||
|
'contact_phone' => '',
|
||||||
|
'contact_email' => '',
|
||||||
|
'address' => '',
|
||||||
|
'worktime' => ''
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$data = [
|
||||||
|
'contact_phone' => $tenant->contact_phone ?? '',
|
||||||
|
'contact_email' => $tenant->contact_email ?? '',
|
||||||
|
'address' => $tenant->address ?? '',
|
||||||
|
'worktime' => $tenant->worktime ?? ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看企业信息', [], $this->getAdminUserInfo());
|
||||||
|
|
||||||
$allSettings = SystemSiteSettings::column('value', 'label');
|
|
||||||
$allSettings['type'] = 'legal_notice';
|
|
||||||
|
|
||||||
$labels = array_column($data, 'label');
|
|
||||||
|
|
||||||
$userId = Session::get('user_id', 0);
|
|
||||||
$userFromSession = Session::get('user', []);
|
|
||||||
$userFromCache = Cache::get('userInfo_' . $userId, []);
|
|
||||||
$account = Session::get('account', '');
|
|
||||||
$name = Session::get('name', '');
|
|
||||||
|
|
||||||
\think\facade\Log::record('SiteSettings Debug - user_id: ' . $userId . ', userFromSession: ' . json_encode($userFromSession) . ', userFromCache: ' . json_encode($userFromCache) . ', account: ' . $account . ', name: ' . $name);
|
|
||||||
|
|
||||||
$this->logSuccess('站点设置管理', '保存法律声明和隐私条款', ['labels' => $labels]);
|
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '保存成功',
|
'msg' => '获取成功',
|
||||||
'data' => $allSettings
|
'data' => $data
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存企业信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function saveCompanyInfos()
|
||||||
|
{
|
||||||
|
$params = $this->request->param();
|
||||||
|
$tid = $params['tid'] ?? 0;
|
||||||
|
|
||||||
|
// 查找租户记录
|
||||||
|
$tenant = Tenant::where('delete_time', null)
|
||||||
|
->where('id', $tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$tenant) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '租户不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新字段
|
||||||
|
if (isset($params['contact_phone'])) {
|
||||||
|
$tenant->contact_phone = (string)$params['contact_phone'];
|
||||||
|
}
|
||||||
|
if (isset($params['contact_email'])) {
|
||||||
|
$tenant->contact_email = (string)$params['contact_email'];
|
||||||
|
}
|
||||||
|
if (isset($params['address'])) {
|
||||||
|
$tenant->address = (string)$params['address'];
|
||||||
|
}
|
||||||
|
if (isset($params['worktime'])) {
|
||||||
|
$tenant->worktime = (string)$params['worktime'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tenant->save();
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '保存企业信息', ['tid' => $tid], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '企业信息保存成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取企业SEO
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getCompanySeo()
|
||||||
|
{
|
||||||
|
// 获取当前租户ID
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
// 直接根据 ID 查询租户记录
|
||||||
|
$tenant = Tenant::where('delete_time', null)
|
||||||
|
->where('id', $tid)
|
||||||
|
->field('seoTitle, seoKeywords, seoDescription')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 如果没有数据,返回默认空值
|
||||||
|
if (!$tenant) {
|
||||||
|
$data = [
|
||||||
|
'seoTitle' => '',
|
||||||
|
'seoKeywords' => '',
|
||||||
|
'seoDescription' => ''
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// 直接读取模型对象的属性
|
||||||
|
$data = [
|
||||||
|
'seoTitle' => $tenant->seoTitle ?? '',
|
||||||
|
'seoKeywords' => $tenant->seoKeywords ?? '',
|
||||||
|
'seoDescription' => $tenant->seoDescription ?? ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '查看企业SEO', ['tid' => $tid], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $data
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存企业SEO
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function saveCompanySeo()
|
||||||
|
{
|
||||||
|
$params = $this->request->param();
|
||||||
|
|
||||||
|
$id = $this->getTenantId();
|
||||||
|
|
||||||
|
$tenant = Tenant::where('delete_time', null)
|
||||||
|
->where('id', $id)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$tenant) {
|
||||||
|
return json(['code' => 404, 'msg' => '租户不存在']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建更新数据
|
||||||
|
$updateData = [];
|
||||||
|
if (isset($params['seoTitle'])) $updateData['seoTitle'] = (string)$params['seoTitle'];
|
||||||
|
if (isset($params['seoKeywords'])) $updateData['seoKeywords'] = (string)$params['seoKeywords'];
|
||||||
|
if (isset($params['seoDescription'])) $updateData['seoDescription'] = (string)$params['seoDescription'];
|
||||||
|
|
||||||
|
if (!empty($updateData)) {
|
||||||
|
$tenant->save($updateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logSuccess('站点设置管理', '保存企业SEO', ['tid' => $id], $this->getAdminUserInfo());
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '企业SEO保存成功']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\System;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use app\model\System\SystemEmail;
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\Exception as MailException;
|
||||||
|
|
||||||
|
class EmailController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取邮箱信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getEmailInfo()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$email = SystemEmail::order('id', 'asc')
|
||||||
|
->field('id, from_address, from_name, host, port, password, encryption, timeout, create_time, update_time')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('邮箱管理', '获取邮箱信息', ['data' => $email]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $email
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('邮箱管理', '获取邮箱信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑邮箱信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editEmailInfo()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取原始请求参数(驼峰命名)
|
||||||
|
$raw = $this->request->post();
|
||||||
|
|
||||||
|
// 手动映射为下划线命名,便于与数据库字段、验证规则对应
|
||||||
|
$data = [
|
||||||
|
'from_address' => $raw['fromAddress'] ?? '',
|
||||||
|
'from_name' => $raw['fromName'] ?? '',
|
||||||
|
'host' => $raw['host'] ?? '',
|
||||||
|
'port' => $raw['port'] ?? '',
|
||||||
|
'password' => $raw['password'] ?? '',
|
||||||
|
'encryption' => $raw['encryption'] ?? '',
|
||||||
|
'timeout' => $raw['timeout'] ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 验证参数
|
||||||
|
$this->validate($data, [
|
||||||
|
'from_address|发件人邮箱' => 'require|max:255',
|
||||||
|
'from_name|发件人名称' => 'require|max:255',
|
||||||
|
'host|SMTP主机' => 'require|max:255',
|
||||||
|
'port|SMTP端口' => 'require|integer',
|
||||||
|
'password|密码' => 'require|max:255',
|
||||||
|
'encryption|加密方式' => 'require|max:255',
|
||||||
|
'timeout|超时时间' => 'require|integer',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 先查一条配置(本表设计为单条配置)
|
||||||
|
$email = SystemEmail::order('id', 'asc')->find();
|
||||||
|
|
||||||
|
// 公共字段
|
||||||
|
$saveData = [
|
||||||
|
'from_address' => $data['from_address'],
|
||||||
|
'from_name' => $data['from_name'],
|
||||||
|
'host' => $data['host'],
|
||||||
|
'port' => $data['port'],
|
||||||
|
'password' => $data['password'],
|
||||||
|
'encryption' => $data['encryption'],
|
||||||
|
'timeout' => $data['timeout'],
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($email) {
|
||||||
|
// 已有一条记录,按主键更新
|
||||||
|
$saveData['update_time'] = date('Y-m-d H:i:s');
|
||||||
|
SystemEmail::update($saveData, ['id' => $email['id']]);
|
||||||
|
} else {
|
||||||
|
// 没有记录,插入新记录
|
||||||
|
$saveData['create_time'] = date('Y-m-d H:i:s');
|
||||||
|
$saveData['update_time'] = $saveData['create_time'];
|
||||||
|
$model = new SystemEmail();
|
||||||
|
$model->save($saveData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取最新的邮箱信息
|
||||||
|
$updatedEmail = SystemEmail::order('id', 'asc')->find();
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('邮箱管理', '更新邮箱信息', ['data' => $updatedEmail]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $updatedEmail
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('邮箱管理', '更新邮箱信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('邮箱管理', '更新邮箱信息', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 发送测试邮件
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function sendTestEmail()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 获取前端传来的表单数据(驼峰命名)
|
||||||
|
$raw = $this->request->post();
|
||||||
|
|
||||||
|
// 映射为下划线命名,便于验证和使用
|
||||||
|
$data = [
|
||||||
|
'from_address' => $raw['fromAddress'] ?? '',
|
||||||
|
'from_name' => $raw['fromName'] ?? '',
|
||||||
|
'host' => $raw['host'] ?? '',
|
||||||
|
'port' => $raw['port'] ?? '',
|
||||||
|
'password' => $raw['password'] ?? '',
|
||||||
|
'encryption' => $raw['encryption'] ?? '',
|
||||||
|
'timeout' => $raw['timeout'] ?? 30,
|
||||||
|
'test_email' => $raw['testEmail'] ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 参数验证
|
||||||
|
$this->validate($data, [
|
||||||
|
'from_address|发件人邮箱' => 'require|email|max:255',
|
||||||
|
'from_name|发件人名称' => 'max:255',
|
||||||
|
'host|SMTP主机' => 'require|max:255',
|
||||||
|
'port|SMTP端口' => 'require|integer',
|
||||||
|
'password|密码' => 'require|max:255',
|
||||||
|
'encryption|加密方式' => 'require|max:10',
|
||||||
|
'timeout|超时时间' => 'integer',
|
||||||
|
'test_email|测试收件邮箱' => 'require|email|max:255',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 使用 PHPMailer 发送测试邮件
|
||||||
|
$mail = new PHPMailer(true);
|
||||||
|
|
||||||
|
// 服务器设置
|
||||||
|
$mail->CharSet = 'UTF-8';
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->Host = $data['host'];
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
// 发件人邮箱即为登录用户名
|
||||||
|
$mail->Username = $data['from_address'];
|
||||||
|
$mail->Password = $data['password'];
|
||||||
|
$mail->Port = (int)$data['port'];
|
||||||
|
|
||||||
|
// 加密方式
|
||||||
|
if (in_array(strtolower((string)$data['encryption']), ['ssl', 'tls'], true)) {
|
||||||
|
$mail->SMTPSecure = strtolower((string)$data['encryption']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超时时间(秒)
|
||||||
|
if (!empty($data['timeout'])) {
|
||||||
|
$mail->Timeout = (int)$data['timeout'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收发件配置
|
||||||
|
$fromName = $data['from_name'] ?: $data['from_address'];
|
||||||
|
$mail->setFrom($data['from_address'], $fromName);
|
||||||
|
$mail->addAddress($data['test_email']);
|
||||||
|
|
||||||
|
// 内容
|
||||||
|
$mail->isHTML(false);
|
||||||
|
$mail->Subject = '测试邮件 - 网站邮箱配置';
|
||||||
|
$mail->Body = '这是一封测试邮件,用于验证网站邮箱配置是否正确。发送时间:' . date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
// 发送
|
||||||
|
$mail->send();
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('邮箱管理', '发送测试邮件', [
|
||||||
|
'to' => $data['test_email'],
|
||||||
|
'host' => $data['host'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '测试邮件发送成功',
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
$this->logFail('邮箱管理', '发送测试邮件', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
} catch (MailException $e) {
|
||||||
|
$this->logFail('邮箱管理', '发送测试邮件', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '发送失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('邮箱管理', '发送测试邮件', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '发送失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+221
-14
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\System;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\facade\Filesystem;
|
use think\facade\Filesystem;
|
||||||
@@ -8,8 +8,8 @@ use think\facade\Request;
|
|||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\Response;
|
use think\Response;
|
||||||
|
|
||||||
use app\model\FilesCategory;
|
use app\model\System\FilesCategory;
|
||||||
use app\model\Files;
|
use app\model\System\Files;
|
||||||
|
|
||||||
class FileController extends BaseController
|
class FileController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,8 @@ class FileController extends BaseController
|
|||||||
$cate = Request::param('cate/d', 0);
|
$cate = Request::param('cate/d', 0);
|
||||||
$keyword = Request::param('keyword/s', '');
|
$keyword = Request::param('keyword/s', '');
|
||||||
|
|
||||||
$query = Files::where('delete_time', null);
|
$query = Files::where('delete_time', null)
|
||||||
|
->where('tid', $this->getTenantId());
|
||||||
|
|
||||||
if ($cate) {
|
if ($cate) {
|
||||||
$query->where('cate', $cate);
|
$query->where('cate', $cate);
|
||||||
@@ -75,11 +76,20 @@ class FileController extends BaseController
|
|||||||
public function getUserCate()
|
public function getUserCate()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$cate = FilesCategory::where('delete_time', null)->field('id,name')->select();
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
// 只根据 tid 筛选分类
|
||||||
|
$cate = FilesCategory::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->field('id,name')
|
||||||
|
->select();
|
||||||
|
|
||||||
// 获取每个分类下的文件数量
|
// 获取每个分类下的文件数量
|
||||||
foreach ($cate as &$c) {
|
foreach ($cate as &$c) {
|
||||||
$c['total'] = Files::where('cate', $c['id'])->where('delete_time', null)->count();
|
$c['total'] = Files::where('cate', $c['id'])
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
@@ -101,6 +111,7 @@ class FileController extends BaseController
|
|||||||
try {
|
try {
|
||||||
$data = Request::param();
|
$data = Request::param();
|
||||||
$data['create_time'] = date('Y-m-d H:i:s');
|
$data['create_time'] = date('Y-m-d H:i:s');
|
||||||
|
$data['tid'] = $this->getTenantId();
|
||||||
$id = FilesCategory::insertGetId($data);
|
$id = FilesCategory::insertGetId($data);
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
@@ -129,7 +140,9 @@ class FileController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$data = Request::param();
|
$data = Request::param();
|
||||||
$result = FilesCategory::where('id', $id)->update(['name' => $data['name']]);
|
$result = FilesCategory::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['name' => $data['name']]);
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('文件管理', '重命名文件分组', ['id' => $id]);
|
$this->logSuccess('文件管理', '重命名文件分组', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
@@ -150,7 +163,21 @@ class FileController extends BaseController
|
|||||||
public function deleteFileCate($id)
|
public function deleteFileCate($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = FilesCategory::where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]);
|
// 检查分组里是否有关联文件
|
||||||
|
$fileCount = Files::where('cate', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->count();
|
||||||
|
if ($fileCount > 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '该分组下还有 ' . $fileCount . ' 个文件,请先删除分组内文件!'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = FilesCategory::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('文件管理', '删除文件分组', ['id' => $id]);
|
$this->logSuccess('文件管理', '删除文件分组', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
@@ -175,12 +202,16 @@ class FileController extends BaseController
|
|||||||
$pageSize = Request::param('pageSize/d', 10);
|
$pageSize = Request::param('pageSize/d', 10);
|
||||||
$keyword = Request::param('keyword/s', '');
|
$keyword = Request::param('keyword/s', '');
|
||||||
|
|
||||||
$query = Files::where('cate', $id)->where('delete_time', null);
|
$query = Files::where('cate', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null);
|
||||||
|
|
||||||
if ($keyword) {
|
if ($keyword) {
|
||||||
$query->whereLike('name', "%{$keyword}%");
|
$query->whereLike('name', "%{$keyword}%");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取总条数
|
||||||
|
$total = $query->count();
|
||||||
$list = $query->page($page, $pageSize)
|
$list = $query->page($page, $pageSize)
|
||||||
->order('create_time', 'desc')
|
->order('create_time', 'desc')
|
||||||
->select();
|
->select();
|
||||||
@@ -196,6 +227,7 @@ class FileController extends BaseController
|
|||||||
'msg' => 'success',
|
'msg' => 'success',
|
||||||
'data' => [
|
'data' => [
|
||||||
'list' => $list,
|
'list' => $list,
|
||||||
|
'total' => $total,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
'pageSize' => $pageSize,
|
'pageSize' => $pageSize,
|
||||||
'categoryId' => $id
|
'categoryId' => $id
|
||||||
@@ -209,6 +241,7 @@ class FileController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 文件上传
|
||||||
public function uploadFile()
|
public function uploadFile()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -229,7 +262,10 @@ class FileController extends BaseController
|
|||||||
$fileMd5 = md5_file($file->getRealPath());
|
$fileMd5 = md5_file($file->getRealPath());
|
||||||
|
|
||||||
// 检查是否已存在相同文件
|
// 检查是否已存在相同文件
|
||||||
$existFile = Files::where('md5', $fileMd5)->where('delete_time', null)->find();
|
$existFile = Files::where('md5', $fileMd5)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
if ($existFile) {
|
if ($existFile) {
|
||||||
return json([
|
return json([
|
||||||
@@ -271,6 +307,7 @@ class FileController extends BaseController
|
|||||||
'src' => $fileUrl,
|
'src' => $fileUrl,
|
||||||
'md5' => $fileMd5,
|
'md5' => $fileMd5,
|
||||||
'uploader' => $userId,
|
'uploader' => $userId,
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'create_time' => date('Y-m-d H:i:s'),
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -308,7 +345,10 @@ class FileController extends BaseController
|
|||||||
|
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
$result = Files::where('id', $id)->where('delete_time', null)->update($data);
|
$result = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update($data);
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
@@ -328,7 +368,17 @@ class FileController extends BaseController
|
|||||||
public function deleteFile($id)
|
public function deleteFile($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = Files::where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]);
|
// 先获取文件信息
|
||||||
|
$file = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if (!$file) {
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
@@ -344,11 +394,49 @@ class FileController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//永久删除文件
|
||||||
|
public function deleteFilePermanently($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// 先获取文件信息
|
||||||
|
$file = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if (!$file) {
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除服务器上的文件
|
||||||
|
if ($file['src']) {
|
||||||
|
$this->deleteFileFromServer($file['src']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('文件管理', '永久删除文件', ['id' => $id]);
|
||||||
|
return json(['code' => 200, 'msg' => '永久删除成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('文件管理', '永久删除文件', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '永久删除失败: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 下载文件
|
// 下载文件
|
||||||
public function download($id)
|
public function download($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$file = Files::where('id', $id)->where('delete_time', null)->find();
|
$file = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
if (!$file) {
|
if (!$file) {
|
||||||
return json(['code' => 404, 'msg' => '文件不存在']);
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
@@ -373,7 +461,9 @@ class FileController extends BaseController
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$cate = Request::param('cate/d', 0);
|
$cate = Request::param('cate/d', 0);
|
||||||
$result = Files::where('id', $id)->update(['cate' => $cate]);
|
$result = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['cate' => $cate]);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('文件管理', '移动文件', ['id' => $id]);
|
$this->logSuccess('文件管理', '移动文件', ['id' => $id]);
|
||||||
@@ -387,4 +477,121 @@ class FileController extends BaseController
|
|||||||
return json(['code' => 500, 'msg' => '移动失败: ' . $e->getMessage()]);
|
return json(['code' => 500, 'msg' => '移动失败: ' . $e->getMessage()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//删除服务器上文件
|
||||||
|
private function deleteFileFromServer($fileUrl)
|
||||||
|
{
|
||||||
|
// 去掉开头的 /storage/,得到相对路径
|
||||||
|
$relativePath = ltrim($fileUrl, '/');
|
||||||
|
if (strpos($relativePath, 'storage/') === 0) {
|
||||||
|
$relativePath = substr($relativePath, 8); // 去掉 'storage/' 部分
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取实际服务器路径
|
||||||
|
$fullPath = root_path() . 'public/storage/' . $relativePath;
|
||||||
|
|
||||||
|
if (file_exists($fullPath)) {
|
||||||
|
unlink($fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量删除文件
|
||||||
|
public function batchDeleteFiles()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$ids = Request::param('ids/a', []);
|
||||||
|
|
||||||
|
if (empty($ids)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请选择要删除的文件']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$file = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if ($file && $file['src']) {
|
||||||
|
$this->deleteFileFromServer($file['src']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Files::where('id', 'in', $ids)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->logSuccess('文件管理', '批量删除文件', ['ids' => $ids]);
|
||||||
|
return json(['code' => 200, 'msg' => '批量删除成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('文件管理', '批量删除文件', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '批量删除失败: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量彻底删除文件
|
||||||
|
public function batchDeleteFilesPermanently()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$ids = Request::param('ids/a', []);
|
||||||
|
|
||||||
|
if (empty($ids)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请选择要彻底删除的文件']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$file = Files::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->find();
|
||||||
|
if ($file && $file['src']) {
|
||||||
|
$this->deleteFileFromServer($file['src']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Files::where('id', 'in', $ids)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->force(true)
|
||||||
|
->update(['delete_time' => date('Y-m-d H:i:s')])
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->logSuccess('文件管理', '批量彻底删除文件', ['ids' => $ids]);
|
||||||
|
return json(['code' => 200, 'msg' => '批量彻底删除成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('文件管理', '批量彻底删除文件', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '批量彻底删除失败: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量移动文件
|
||||||
|
public function batchMoveFiles()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$ids = Request::param('ids/a', []);
|
||||||
|
$cate = Request::param('cate/d', 0);
|
||||||
|
|
||||||
|
if (empty($ids)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请选择要移动的文件']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Files::where('id', 'in', $ids)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
|
->update(['cate' => $cate]);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->logSuccess('文件管理', '批量移动文件', ['ids' => $ids, 'cate' => $cate]);
|
||||||
|
return json(['code' => 200, 'msg' => '批量移动成功']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(['code' => 404, 'msg' => '文件不存在']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logFail('文件管理', '批量移动文件', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '批量移动失败: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+34
-12
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\admin\controller;
|
namespace app\admin\controller\System;
|
||||||
|
|
||||||
use app\admin\BaseController;
|
use app\admin\BaseController;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
@@ -10,8 +10,8 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
|
|
||||||
use app\model\AdminUser;
|
use app\model\System\AdminUser;
|
||||||
use app\model\AdminUserGroup;
|
use app\model\System\AdminUserGroup;
|
||||||
|
|
||||||
class RoleController extends BaseController
|
class RoleController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,11 @@ class RoleController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function getAllRoles()
|
public function getAllRoles()
|
||||||
{
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
$roles = AdminUserGroup::where('delete_time', null)
|
$roles = AdminUserGroup::where('delete_time', null)
|
||||||
|
->where(function ($query) use ($tid) {
|
||||||
|
$query->where('tid', $tid)->whereOr('tid', 0);
|
||||||
|
})
|
||||||
->order('id', 'asc')
|
->order('id', 'asc')
|
||||||
->select();
|
->select();
|
||||||
return json([
|
return json([
|
||||||
@@ -39,6 +43,9 @@ class RoleController extends BaseController
|
|||||||
public function getRoleById(int $id)
|
public function getRoleById(int $id)
|
||||||
{
|
{
|
||||||
$role = AdminUserGroup::where('id', $id)
|
$role = AdminUserGroup::where('id', $id)
|
||||||
|
->where(function ($query) {
|
||||||
|
$query->where('tid', $this->getTenantId())->whereOr('tid', 0);
|
||||||
|
})
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if (!$role) {
|
if (!$role) {
|
||||||
@@ -73,6 +80,7 @@ class RoleController extends BaseController
|
|||||||
|
|
||||||
// 检查角色名称是否已存在
|
// 检查角色名称是否已存在
|
||||||
$exists = AdminUserGroup::where('name', $data['name'])
|
$exists = AdminUserGroup::where('name', $data['name'])
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
@@ -85,6 +93,7 @@ class RoleController extends BaseController
|
|||||||
// 准备数据
|
// 准备数据
|
||||||
$roleData = [
|
$roleData = [
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
'status' => $data['status'] ?? 1,
|
'status' => $data['status'] ?? 1,
|
||||||
'rights' => !empty($data['rights']) ? json_encode($data['rights']) : null,
|
'rights' => !empty($data['rights']) ? json_encode($data['rights']) : null,
|
||||||
'create_time' => date('Y-m-d H:i:s'),
|
'create_time' => date('Y-m-d H:i:s'),
|
||||||
@@ -136,8 +145,11 @@ class RoleController extends BaseController
|
|||||||
'rights|权限' => 'array'
|
'rights|权限' => 'array'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 查找角色
|
// 查找角色(验证tid,tid为0的系统角色也可编辑)
|
||||||
$role = AdminUserGroup::where('id', $id)
|
$role = AdminUserGroup::where('id', $id)
|
||||||
|
->where(function ($query) {
|
||||||
|
$query->where('tid', $this->getTenantId())->whereOr('tid', 0);
|
||||||
|
})
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if (!$role) {
|
if (!$role) {
|
||||||
@@ -147,9 +159,12 @@ class RoleController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查角色名称是否已被其他角色使用
|
// 检查角色名称是否已被其他角色使用(tid为0或当前用户tid的角色)
|
||||||
$exists = AdminUserGroup::where('name', $data['name'])
|
$exists = AdminUserGroup::where('name', $data['name'])
|
||||||
->where('id', '<>', $id)
|
->where('id', '<>', $id)
|
||||||
|
->where(function ($query) {
|
||||||
|
$query->where('tid', $this->getTenantId())->whereOr('tid', 0);
|
||||||
|
})
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
@@ -160,18 +175,23 @@ class RoleController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新数据
|
// 更新数据
|
||||||
$role->name = $data['name'];
|
$updateData = [
|
||||||
$role->status = $data['status'] ?? 1;
|
'name' => $data['name'],
|
||||||
$role->rights = !empty($data['rights']) ? json_encode($data['rights']) : null;
|
'status' => $data['status'] ?? 1,
|
||||||
$role->update_time = date('Y-m-d H:i:s');
|
'rights' => !empty($data['rights']) ? json_encode($data['rights']) : null,
|
||||||
$role->save();
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
];
|
||||||
|
AdminUserGroup::where('id', $id)->update($updateData);
|
||||||
|
|
||||||
|
// 重新查询获取最新数据
|
||||||
|
$updatedRole = AdminUserGroup::where('id', $id)->find();
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('角色管理', '更新角色', ['id' => $id]);
|
$this->logSuccess('角色管理', '更新角色', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '更新成功',
|
'msg' => '更新成功',
|
||||||
'data' => $role->toArray()
|
'data' => $updatedRole->toArray()
|
||||||
]);
|
]);
|
||||||
} catch (ValidateException $e) {
|
} catch (ValidateException $e) {
|
||||||
// 记录失败日志
|
// 记录失败日志
|
||||||
@@ -206,8 +226,9 @@ class RoleController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找角色
|
// 查找角色(验证tid)
|
||||||
$role = AdminUserGroup::where('id', $id)
|
$role = AdminUserGroup::where('id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
if (!$role) {
|
if (!$role) {
|
||||||
@@ -219,6 +240,7 @@ class RoleController extends BaseController
|
|||||||
|
|
||||||
// 检查是否有用户正在使用该角色
|
// 检查是否有用户正在使用该角色
|
||||||
$userCount = AdminUser::where('group_id', $id)
|
$userCount = AdminUser::where('group_id', $id)
|
||||||
|
->where('tid', $this->getTenantId())
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->count();
|
->count();
|
||||||
if ($userCount > 0) {
|
if ($userCount > 0) {
|
||||||
@@ -0,0 +1,676 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\System;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use app\model\System\SystemSiteSettings;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Log;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Request;
|
||||||
|
|
||||||
|
class SmsController extends BaseController
|
||||||
|
{
|
||||||
|
private function getSiteSettingValue(string $label): string
|
||||||
|
{
|
||||||
|
$row = SystemSiteSettings::where('label', $label)->order('id', 'asc')->find();
|
||||||
|
if (!$row) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return (string)$row['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function upsertSiteSetting(string $label, string $value): void
|
||||||
|
{
|
||||||
|
$row = SystemSiteSettings::where('label', $label)->order('id', 'asc')->find();
|
||||||
|
if ($row) {
|
||||||
|
SystemSiteSettings::update(['value' => $value], ['id' => $row['id']]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$model = new SystemSiteSettings();
|
||||||
|
$model->label = $label;
|
||||||
|
$model->value = $value;
|
||||||
|
$model->sort = 0;
|
||||||
|
$model->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取短信网关配置
|
||||||
|
*/
|
||||||
|
public function getSmsInfo()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$backendUrl = $this->getSiteSettingValue('backendUrl');
|
||||||
|
$apiKey = $this->getSiteSettingValue('apiKey');
|
||||||
|
|
||||||
|
// 前端约定返回 data[0],字段名兼容 backend_url/api_key 与 backendUrl/apiKey
|
||||||
|
$data = [[
|
||||||
|
'backend_url' => $backendUrl,
|
||||||
|
'api_key' => $apiKey,
|
||||||
|
'backendUrl' => $backendUrl,
|
||||||
|
'apiKey' => $apiKey,
|
||||||
|
]];
|
||||||
|
|
||||||
|
$this->logSuccess('短信管理', '获取短信网关配置', ['data' => $data]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
$this->logFail('短信管理', '获取短信网关配置', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取失败:' . $e->getMessage(),
|
||||||
|
'data' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑短信网关配置(本表设计为单条配置)
|
||||||
|
*/
|
||||||
|
public function editSmsInfo()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$raw = $this->request->post();
|
||||||
|
$data = [
|
||||||
|
'backend_url' => $raw['backendUrl'] ?? $raw['backend_url'] ?? '',
|
||||||
|
'api_key' => $raw['apiKey'] ?? $raw['api_key'] ?? '',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->validate($data, [
|
||||||
|
'backend_url|短信网关地址' => 'require|max:255',
|
||||||
|
'api_key|短信网关 API KEY' => 'require|max:255',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->upsertSiteSetting('backendUrl', (string)$data['backend_url']);
|
||||||
|
$this->upsertSiteSetting('apiKey', (string)$data['api_key']);
|
||||||
|
|
||||||
|
$updated = [[
|
||||||
|
'backend_url' => $this->getSiteSettingValue('backendUrl'),
|
||||||
|
'api_key' => $this->getSiteSettingValue('apiKey'),
|
||||||
|
]];
|
||||||
|
|
||||||
|
$this->logSuccess('短信管理', '更新短信网关配置', ['data' => $updated]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '更新成功',
|
||||||
|
'data' => $updated,
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
$this->logFail('短信管理', '更新短信网关配置', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError(),
|
||||||
|
]);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
$this->logFail('短信管理', '更新短信网关配置', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '更新失败:' . $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台发起“短信测试”:入队一条任务,等待 Android 网关轮询取走并发送
|
||||||
|
*/
|
||||||
|
public function sendTestSms()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$raw = $this->request->post();
|
||||||
|
$phone = trim((string)($raw['phone'] ?? $raw['testPhone'] ?? ''));
|
||||||
|
$content = trim((string)($raw['content'] ?? ''));
|
||||||
|
|
||||||
|
if (empty($phone)) {
|
||||||
|
return json(['code' => 400, 'msg' => '缺少测试手机号']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android 网关文档:国际格式 +8613712345678
|
||||||
|
if (!preg_match('/^\+\d{6,15}$/', $phone)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请使用国际格式手机号(以 + 开头,后为数字)']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前网关配置(来自 mete_system_site_settings label/value)
|
||||||
|
$apiKey = $this->getSiteSettingValue('apiKey');
|
||||||
|
$backendUrl = $this->getSiteSettingValue('backendUrl');
|
||||||
|
if (empty($apiKey)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请先配置短信网关 API KEY']);
|
||||||
|
}
|
||||||
|
if (empty($backendUrl)) {
|
||||||
|
return json(['code' => 400, 'msg' => '请先配置短信网关地址 backendUrl']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = (string)random_int(100000, 999999);
|
||||||
|
if ($content === '') {
|
||||||
|
$content = '短信测试验证码:' . $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容:调用 Uniapp/sms 后端入队发送任务
|
||||||
|
$enqueueUrl = rtrim($backendUrl, '/') . '/api/v1/business/outbound-tasks';
|
||||||
|
$enqueuePayload = [
|
||||||
|
'phone' => $phone,
|
||||||
|
'content' => $content,
|
||||||
|
];
|
||||||
|
$enqueueHeaders = [
|
||||||
|
'X-Api-Key: ' . (string)$apiKey,
|
||||||
|
'Content-Type: application/json; charset=utf-8',
|
||||||
|
'Accept: application/json',
|
||||||
|
];
|
||||||
|
|
||||||
|
Log::write('[sms_enqueue] url=' . $enqueueUrl . ' phone=' . $phone);
|
||||||
|
$enqueueResp = $this->postJson($enqueueUrl, $enqueuePayload, $enqueueHeaders);
|
||||||
|
if (empty($enqueueResp['ok'])) {
|
||||||
|
Log::write('[sms_enqueue] failed http_status=' . ($enqueueResp['status'] ?? '') . ' body=' . ($enqueueResp['body'] ?? ''));
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '短信网关入队失败:' . ($enqueueResp['error'] ?? 'unknown'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$smsGatewayTaskId = (string)($enqueueResp['json']['taskId'] ?? '');
|
||||||
|
Log::write('[sms_enqueue] success taskId=' . $smsGatewayTaskId);
|
||||||
|
|
||||||
|
$enqueueDebug = [
|
||||||
|
'enqueueOk' => (bool)($enqueueResp['ok'] ?? false),
|
||||||
|
'enqueueStatus' => $enqueueResp['status'] ?? null,
|
||||||
|
'enqueueJsonKeys' => array_keys((array)($enqueueResp['json'] ?? [])),
|
||||||
|
'gatewayTaskId' => $smsGatewayTaskId,
|
||||||
|
];
|
||||||
|
|
||||||
|
// 同步一条本地记录(用于前端列表展示/对账)
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
$taskId = Db::name('mete_system_sms_tasks')->insertGetId([
|
||||||
|
'api_key' => (string)$apiKey,
|
||||||
|
'tid' => $this->getTenantId(),
|
||||||
|
'phone' => $phone,
|
||||||
|
'content' => $content,
|
||||||
|
'status' => 0, // pending(本地不自动同步网关状态)
|
||||||
|
'code' => $code, // 预期验证码(用于对账/展示)
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->logSuccess('短信管理', '发送测试短信(调用网关入队)', [
|
||||||
|
'to' => $phone,
|
||||||
|
'local_task_id' => $taskId ?? null,
|
||||||
|
'gateway_task_id' => $smsGatewayTaskId,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '测试短信任务已入队,等待网关发送',
|
||||||
|
'data' => [
|
||||||
|
'taskId' => $smsGatewayTaskId ?: ($taskId ?? null),
|
||||||
|
'code' => $code,
|
||||||
|
],
|
||||||
|
'debug' => empty($smsGatewayTaskId) ? $enqueueDebug : null,
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
$this->logFail('短信管理', '发送测试短信', $e->getMessage());
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->logFail('短信管理', '发送测试短信', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '发送失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单 JSON POST(无 curl 扩展时使用)
|
||||||
|
* @return array{ok:bool,status?:int,body?:string,error?:string,json?:array}
|
||||||
|
*/
|
||||||
|
private function postJson(string $url, array $payload, array $headers): array
|
||||||
|
{
|
||||||
|
$body = json_encode($payload, JSON_UNESCAPED_UNICODE);
|
||||||
|
if ($body === false) {
|
||||||
|
return ['ok' => false, 'error' => 'json_encode failed'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$headerStr = implode("\r\n", $headers);
|
||||||
|
$context = stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'header' => $headerStr,
|
||||||
|
'content' => $body,
|
||||||
|
'timeout' => 10,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$respBody = @file_get_contents($url, false, $context);
|
||||||
|
$status = 0;
|
||||||
|
if (!empty($http_response_header) && is_array($http_response_header)) {
|
||||||
|
foreach ($http_response_header as $line) {
|
||||||
|
if (preg_match('#^HTTP/\\S+\\s+(\\d+)#', $line, $m)) {
|
||||||
|
$status = (int)$m[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($respBody === false) {
|
||||||
|
$last = error_get_last();
|
||||||
|
$errMsg = $last['message'] ?? 'http request failed';
|
||||||
|
return ['ok' => false, 'status' => $status, 'error' => (string)$errMsg];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = null;
|
||||||
|
$decoded = json_decode((string)$respBody, true);
|
||||||
|
if (!is_array($decoded)) {
|
||||||
|
$decoded = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ok = $status >= 200 && $status < 300;
|
||||||
|
return [
|
||||||
|
'ok' => $ok,
|
||||||
|
'status' => $status,
|
||||||
|
'body' => (string)$respBody,
|
||||||
|
'json' => $decoded,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单 JSON GET(无 curl 扩展时使用)
|
||||||
|
* @return array{ok:bool,status?:int,body?:string,error?:string,json?:array}
|
||||||
|
*/
|
||||||
|
private function httpGetJson(string $url, array $headers): array
|
||||||
|
{
|
||||||
|
$headerStr = implode("\r\n", $headers);
|
||||||
|
$context = stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'GET',
|
||||||
|
'header' => $headerStr,
|
||||||
|
'timeout' => 10,
|
||||||
|
// 对 4xx/5xx 也返回响应体,便于排障
|
||||||
|
'ignore_errors' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$respBody = @file_get_contents($url, false, $context);
|
||||||
|
$status = 0;
|
||||||
|
if (!empty($http_response_header) && is_array($http_response_header)) {
|
||||||
|
foreach ($http_response_header as $line) {
|
||||||
|
if (preg_match('#^HTTP/\\S+\\s+(\\d+)#', $line, $m)) {
|
||||||
|
$status = (int)$m[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($respBody === false) {
|
||||||
|
$last = error_get_last();
|
||||||
|
$errMsg = $last['message'] ?? 'http request failed';
|
||||||
|
return ['ok' => false, 'status' => $status, 'error' => (string)$errMsg];
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = json_decode((string)$respBody, true);
|
||||||
|
if (!is_array($decoded)) {
|
||||||
|
$decoded = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ok = $status >= 200 && $status < 300;
|
||||||
|
return [
|
||||||
|
'ok' => $ok,
|
||||||
|
'status' => $status,
|
||||||
|
'body' => (string)$respBody,
|
||||||
|
'json' => $decoded,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android 网关轮询:获取待发送任务
|
||||||
|
*
|
||||||
|
* 约定:
|
||||||
|
* - apiKey 通过 header `X-API-KEY` / `X-SMS-GATEWAY-API-KEY` 或 body/query `apiKey`
|
||||||
|
*/
|
||||||
|
public function gatewayPoll()
|
||||||
|
{
|
||||||
|
$apiKey = $this->getApiKeyFromRequest();
|
||||||
|
if (empty($apiKey)) {
|
||||||
|
Log::write('[sms_gateway_poll] missing apiKey');
|
||||||
|
return json(['code' => 401, 'msg' => '缺少 apiKey']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不强制要求 mete_system_site_settings(apiKey) 与网关入参完全一致;
|
||||||
|
// 直接按任务表的 api_key 匹配,提高兼容性与排障速度。
|
||||||
|
$apiKeySetting = $this->getSiteSettingValue('apiKey');
|
||||||
|
if (empty($apiKeySetting) || (string)$apiKeySetting !== (string)$apiKey) {
|
||||||
|
Log::write('[sms_gateway_poll] apiKey differs from setting; setting=' . $this->maskKey($apiKeySetting) . ' req=' . $this->maskKey($apiKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
$task = Db::name('mete_system_sms_tasks')
|
||||||
|
->where('api_key', (string)$apiKey)
|
||||||
|
->where('status', 0)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->order('id', 'asc')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 没有任务
|
||||||
|
if (!$task) {
|
||||||
|
Log::write('[sms_gateway_poll] no task for apiKey=' . $this->maskKey($apiKey));
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'no task',
|
||||||
|
'data' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记为处理中,避免被重复领取
|
||||||
|
Db::name('mete_system_sms_tasks')->where('id', (int)$task['id'])->update([
|
||||||
|
'status' => 1,
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Log::write('[sms_gateway_poll] send task id=' . (int)$task['id'] . ' phone=' . (string)$task['phone']);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'taskId' => $task['id'],
|
||||||
|
'task_id' => $task['id'],
|
||||||
|
'phone' => $task['phone'],
|
||||||
|
'content' => $task['content'],
|
||||||
|
'smsContent' => $task['content'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android 网关上报:上传实际收到的短信内容并解析验证码
|
||||||
|
*/
|
||||||
|
public function gatewayReport()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$raw = $this->request->post();
|
||||||
|
$apiKey = $this->getApiKeyFromRequest();
|
||||||
|
$taskId = $raw['taskId'] ?? $raw['task_id'] ?? $raw['id'] ?? null;
|
||||||
|
$smsContent = trim((string)($raw['smsContent'] ?? $raw['sms_content'] ?? $raw['content'] ?? $raw['message'] ?? $raw['sms'] ?? ''));
|
||||||
|
$status = $raw['status'] ?? $raw['result'] ?? $raw['state'] ?? null; // success/failed/int
|
||||||
|
|
||||||
|
if (empty($apiKey)) {
|
||||||
|
return json(['code' => 401, 'msg' => '缺少 apiKey']);
|
||||||
|
}
|
||||||
|
if (empty($taskId)) {
|
||||||
|
return json(['code' => 400, 'msg' => '缺少 taskId']);
|
||||||
|
}
|
||||||
|
if ($smsContent === '') {
|
||||||
|
return json(['code' => 400, 'msg' => '缺少 smsContent']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$task = Db::name('mete_system_sms_tasks')
|
||||||
|
->where('id', (int)$taskId)
|
||||||
|
->where('api_key', (string)$apiKey)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$task) {
|
||||||
|
Log::write('[sms_gateway_report] task not found; taskId=' . (int)$taskId . ' apiKey=' . $this->maskKey($apiKey));
|
||||||
|
return json(['code' => 404, 'msg' => '任务不存在或 apiKey 不匹配']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::write('[sms_gateway_report] received taskId=' . (int)$taskId . ' status=' . (string)($status ?? ''));
|
||||||
|
|
||||||
|
// 从短信内容里抓取验证码(通用策略:4-6 位数字)
|
||||||
|
$parsedCode = '';
|
||||||
|
if (preg_match('/(\d{4,6})/', $smsContent, $m)) {
|
||||||
|
$parsedCode = (string)$m[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$update = [
|
||||||
|
'report_raw' => $smsContent,
|
||||||
|
'code' => $parsedCode !== '' ? $parsedCode : (string)$task['code'],
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($status === 'failed' || $status === 'error' || $status === 2) {
|
||||||
|
$update['status'] = 2;
|
||||||
|
} elseif ($status === 'success' || $status === 'reported' || $status === 3 || $status === 1) {
|
||||||
|
// success => reported/done
|
||||||
|
$update['status'] = 3;
|
||||||
|
} else {
|
||||||
|
// 默认当做已上报
|
||||||
|
$update['status'] = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Db::name('mete_system_sms_tasks')->where('id', (int)$task['id'])->update($update);
|
||||||
|
|
||||||
|
$this->logSuccess('短信管理', '网关上报短信(解析验证码)', [
|
||||||
|
'task_id' => $task['id'],
|
||||||
|
'parsed_code' => $update['code'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '上报成功']);
|
||||||
|
} catch (DbException $e) {
|
||||||
|
$this->logFail('短信管理', '网关上报短信', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '服务器错误:' . $e->getMessage()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->logFail('短信管理', '网关上报短信', $e->getMessage());
|
||||||
|
return json(['code' => 500, 'msg' => '服务器错误:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员:获取短信任务列表(租户隔离)
|
||||||
|
*
|
||||||
|
* 支持参数(可选):
|
||||||
|
* - status: 任务状态
|
||||||
|
* - phone: 手机号关键词
|
||||||
|
*/
|
||||||
|
public function getSmsTaskList()
|
||||||
|
{
|
||||||
|
$backendUrl = $this->getSiteSettingValue('backendUrl');
|
||||||
|
$apiKey = $this->getSiteSettingValue('apiKey');
|
||||||
|
|
||||||
|
if (empty($backendUrl) || empty($apiKey)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '短信网关配置未完成(backendUrl/apiKey 缺失)',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = (string)Request::param('status', '');
|
||||||
|
$phoneKeyword = trim((string)Request::param('phone', ''));
|
||||||
|
$limit = (int)Request::param('limit', 50, 'int');
|
||||||
|
$limit = $limit > 0 ? min($limit, 200) : 50;
|
||||||
|
|
||||||
|
// 前端 status: 0/1/2/3 -> uniapp backend status: pending/sending/failed/success
|
||||||
|
$statusMap = [
|
||||||
|
'0' => 'pending',
|
||||||
|
'1' => 'sending',
|
||||||
|
'2' => 'failed',
|
||||||
|
'3' => 'success',
|
||||||
|
];
|
||||||
|
$uniStatus = $status !== '' && isset($statusMap[$status]) ? $statusMap[$status] : '';
|
||||||
|
|
||||||
|
$url = rtrim($backendUrl, '/') . '/api/v1/business/outbound-tasks?limit=' . $limit;
|
||||||
|
if ($uniStatus !== '') {
|
||||||
|
$url .= '&status=' . urlencode($uniStatus);
|
||||||
|
}
|
||||||
|
if ($phoneKeyword !== '') {
|
||||||
|
$url .= '&phone=' . urlencode($phoneKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'X-Api-Key: ' . (string)$apiKey,
|
||||||
|
'Accept: application/json',
|
||||||
|
];
|
||||||
|
|
||||||
|
$resp = $this->httpGetJson($url, $headers);
|
||||||
|
if (empty($resp['ok'])) {
|
||||||
|
// 兼容:如果 uniapp 后端还未部署新增查询接口,则 fallback 到本地队列表(只能看到“已入队”,无法看到发送成功/失败)
|
||||||
|
$fallback = [];
|
||||||
|
try {
|
||||||
|
$fWhere = [
|
||||||
|
['api_key', '=', (string)$apiKey],
|
||||||
|
['delete_time', '=', null],
|
||||||
|
];
|
||||||
|
if ($phoneKeyword !== '') {
|
||||||
|
$fWhere[] = ['phone', 'like', '%' . $phoneKeyword . '%'];
|
||||||
|
}
|
||||||
|
// 前端 status=0/1/2/3,局部队列表字段同样使用数字状态
|
||||||
|
if ($status !== '') {
|
||||||
|
$fWhere[] = ['status', '=', (int)$status];
|
||||||
|
}
|
||||||
|
|
||||||
|
$fallback = Db::name('mete_system_sms_tasks')
|
||||||
|
->where($fWhere)
|
||||||
|
->order('id', 'desc')
|
||||||
|
->limit($limit)
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$fallback = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'uniapp 查询任务接口不可用,已使用本地队列表(仅展示入队状态)',
|
||||||
|
'detail' => [
|
||||||
|
'http_status' => $resp['status'] ?? null,
|
||||||
|
'body_preview' => isset($resp['body']) ? substr((string)$resp['body'], 0, 300) : '',
|
||||||
|
],
|
||||||
|
'list' => $fallback,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tasks = (array)($resp['json']['tasks'] ?? []);
|
||||||
|
|
||||||
|
$statusNumMap = [
|
||||||
|
'pending' => 0,
|
||||||
|
'sending' => 1,
|
||||||
|
'failed' => 2,
|
||||||
|
'success' => 3,
|
||||||
|
];
|
||||||
|
|
||||||
|
$list = array_map(function ($t) use ($statusNumMap) {
|
||||||
|
$content = (string)($t['content'] ?? '');
|
||||||
|
$parsedCode = '';
|
||||||
|
if (preg_match('/(\d{4,6})/', $content, $m)) {
|
||||||
|
$parsedCode = (string)$m[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusStr = (string)($t['status'] ?? '');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $t['taskId'] ?? '',
|
||||||
|
'phone' => $t['phone'] ?? '',
|
||||||
|
'content' => $content,
|
||||||
|
'code' => $parsedCode,
|
||||||
|
'status' => $statusNumMap[$statusStr] ?? 0,
|
||||||
|
'create_time' => isset($t['createdAt']) ? date('Y-m-d H:i:s', (int)($t['createdAt'] / 1000)) : '',
|
||||||
|
'update_time' => isset($t['updatedAt']) ? date('Y-m-d H:i:s', (int)($t['updatedAt'] / 1000)) : '',
|
||||||
|
];
|
||||||
|
}, $tasks);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $list,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员:编辑短信任务(租户隔离)
|
||||||
|
*
|
||||||
|
* body:
|
||||||
|
* - status
|
||||||
|
* - code
|
||||||
|
* - report_raw
|
||||||
|
*/
|
||||||
|
public function editSmsTask($id = null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
$id = $this->request->param('id', $id);
|
||||||
|
|
||||||
|
$data = Request::only(['status', 'code', 'report_raw']);
|
||||||
|
|
||||||
|
if (empty($id)) {
|
||||||
|
return json(['code' => 400, 'msg' => '任务ID不能为空']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data['status'])) {
|
||||||
|
return json(['code' => 400, 'msg' => '状态不能为空']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validate($data, [
|
||||||
|
'status|状态' => 'integer',
|
||||||
|
'code|验证码' => 'max:20',
|
||||||
|
'report_raw|上报内容' => 'max:100000',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$task = Db::name('mete_system_sms_tasks')
|
||||||
|
->where('id', (int)$id)
|
||||||
|
->where('tid', (int)$tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$task) {
|
||||||
|
return json(['code' => 404, 'msg' => '任务不存在或无权限']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$update = [
|
||||||
|
'status' => (int)$data['status'],
|
||||||
|
'code' => (string)($data['code'] ?? ''),
|
||||||
|
'report_raw' => (string)($data['report_raw'] ?? ''),
|
||||||
|
'update_time' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
|
||||||
|
Db::name('mete_system_sms_tasks')
|
||||||
|
->where('id', (int)$id)
|
||||||
|
->where('tid', (int)$tid)
|
||||||
|
->update($update);
|
||||||
|
|
||||||
|
return json(['code' => 200, 'msg' => '编辑成功']);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json(['code' => 400, 'msg' => $e->getError()]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json(['code' => 500, 'msg' => '编辑失败:' . $e->getMessage()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getApiKeyFromRequest(): string
|
||||||
|
{
|
||||||
|
$req = Request::instance();
|
||||||
|
|
||||||
|
$apiKey = (string)$req->header('X-SMS-GATEWAY-API-KEY', '');
|
||||||
|
if ($apiKey !== '') {
|
||||||
|
return $apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiKey = (string)$req->header('X-API-KEY', '');
|
||||||
|
if ($apiKey !== '') {
|
||||||
|
return $apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiKey = (string)$req->header('X-SMS-API-KEY', '');
|
||||||
|
if ($apiKey !== '') {
|
||||||
|
return $apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiKey = (string)$req->header('Authorization', '');
|
||||||
|
if ($apiKey !== '' && preg_match('/Bearer\\s+(.+)/i', $apiKey, $m)) {
|
||||||
|
return (string)$m[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// body/query
|
||||||
|
$apiKey = (string)($req->post('apiKey') ?? $req->post('api_key') ?? $req->param('apiKey', '') ?? $req->param('api_key', ''));
|
||||||
|
return $apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function maskKey(string $key): string
|
||||||
|
{
|
||||||
|
$key = (string)$key;
|
||||||
|
if ($key === '') return '';
|
||||||
|
if (strlen($key) <= 6) return '***';
|
||||||
|
return substr($key, 0, 3) . '***' . substr($key, -3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\Tenant;
|
||||||
|
|
||||||
|
use app\admin\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
use think\Request;
|
||||||
|
use app\model\Tenant\Tenant;
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
use app\model\Template\TemplateSiteConfig;
|
||||||
|
|
||||||
|
class TenantController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取租户列表
|
||||||
|
*/
|
||||||
|
public function getTenant(Request $request)
|
||||||
|
{
|
||||||
|
// 获取参数
|
||||||
|
$page = $request->param('page', 1, 'int');
|
||||||
|
$pageSize = $request->param('pageSize', 10, 'int');
|
||||||
|
$tenantName = $request->param('tenant_name', '');
|
||||||
|
$tenantCode = $request->param('tenant_code', '');
|
||||||
|
$contactPerson = $request->param('contact_person', '');
|
||||||
|
$contactPhone = $request->param('contact_phone', '');
|
||||||
|
|
||||||
|
$where = [['delete_time', '=', null]];
|
||||||
|
|
||||||
|
// 动态增加模糊搜索条件
|
||||||
|
if ($tenantName) $where[] = ['tenant_name', 'like', "%$tenantName%"];
|
||||||
|
if ($tenantCode) $where[] = ['tenant_code', 'like', "%$tenantCode%"];
|
||||||
|
if ($contactPerson) $where[] = ['contact_person', 'like', "%$contactPerson%"];
|
||||||
|
if ($contactPhone) $where[] = ['contact_phone', 'like', "%$contactPhone%"];
|
||||||
|
|
||||||
|
$list = Tenant::where($where)->page($page, $pageSize)->select()->toArray();
|
||||||
|
$total = Tenant::where($where)->count();
|
||||||
|
|
||||||
|
return json(['code' => 200, 'data' => ['list' => $list, 'total' => $total]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取租户详情
|
||||||
|
*/
|
||||||
|
public function getTenantDetail($id)
|
||||||
|
{
|
||||||
|
$detail = Tenant::where('id', $id)->where('delete_time', null)->find()->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $detail
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建租户
|
||||||
|
*/
|
||||||
|
public function createTenant()
|
||||||
|
{
|
||||||
|
$data = $this->request->post();
|
||||||
|
$tenant = Tenant::create($data);
|
||||||
|
if ($tenant) {
|
||||||
|
// 创建租户默认数据
|
||||||
|
$this->createTenantDefaultData($tenant->id);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '创建成功',
|
||||||
|
'data' => $tenant
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '创建失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建租户默认数据
|
||||||
|
* @param int $tenantId 租户ID
|
||||||
|
*/
|
||||||
|
private function createTenantDefaultData(int $tenantId)
|
||||||
|
{
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
// 创建租户默认模板配置
|
||||||
|
TemplateSiteConfig::create([
|
||||||
|
'tid' => $tenantId,
|
||||||
|
'key' => 'current_theme',
|
||||||
|
'value' => 'default',
|
||||||
|
'create_time' => $now,
|
||||||
|
'update_time' => $now
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑租户
|
||||||
|
*/
|
||||||
|
public function editTenant($id)
|
||||||
|
{
|
||||||
|
$data = $this->request->post();
|
||||||
|
$tenant = Tenant::where('id', $id)->update($data);
|
||||||
|
if ($tenant) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功',
|
||||||
|
'data' => $tenant
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '编辑失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除租户
|
||||||
|
*/
|
||||||
|
public function deleteTenant($id)
|
||||||
|
{
|
||||||
|
$tenant = Tenant::where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]);
|
||||||
|
if ($tenant) {
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功',
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '删除失败',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询租户编码重复(不筛选删除数据)
|
||||||
|
*/
|
||||||
|
public function findTenantCode(Request $request)
|
||||||
|
{
|
||||||
|
$tenantCode = $request->param('tenant_code', '');
|
||||||
|
|
||||||
|
if (!$tenantCode) {
|
||||||
|
return json(['code' => 400, 'msg' => '缺少编码参数']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接去表里查,只要有一条一样的就返回重复
|
||||||
|
$hasOne = Tenant::where('tenant_code', $tenantCode)->find();
|
||||||
|
|
||||||
|
if ($hasOne) {
|
||||||
|
return json([
|
||||||
|
'code' => 201,
|
||||||
|
'msg' => '编码已存在',
|
||||||
|
'data' => $hasOne
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编码可用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,25 +10,85 @@ use think\facade\Db;
|
|||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
|
|
||||||
use app\model\AdminUser;
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
class UserController extends BaseController
|
class UserController extends BaseController
|
||||||
{
|
{
|
||||||
|
private function getCurrentTenantIdOrFail(): int
|
||||||
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if ($tid <= 0) {
|
||||||
|
throw new \RuntimeException('未获取到有效租户信息');
|
||||||
|
}
|
||||||
|
return $tid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有用户信息
|
* 获取所有用户信息
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getAllUsers()
|
public function getAllUsers()
|
||||||
{
|
{
|
||||||
$users = AdminUser::where('delete_time', null)->field('id, account, name, phone,email, qq, sex, group_id, status, last_login_ip, login_count, create_time, update_time')->select()->toArray();
|
try {
|
||||||
return json([
|
$tid = $this->getCurrentTenantIdOrFail();
|
||||||
'code' => 200,
|
$users = AdminUser::where('delete_time', null)
|
||||||
'msg' => '获取成功',
|
->where('tid', $tid)
|
||||||
'data' => [
|
->field('id, tid, account, name, phone, birth, email, qq, sex, group_id, status, last_login_ip, login_count, create_time, update_time')
|
||||||
'list' => $users,
|
->select()
|
||||||
'total' => count($users)
|
->toArray();
|
||||||
]
|
return json([
|
||||||
]);
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $users,
|
||||||
|
'total' => count($users)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '获取用户失败:' . $e->getMessage(),
|
||||||
|
'data' => [
|
||||||
|
'list' => [],
|
||||||
|
'total' => 0
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取租户用户
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getTenantUsers(int $tenantId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$tid = $this->getCurrentTenantIdOrFail();
|
||||||
|
if ($tenantId !== $tid) {
|
||||||
|
return json([
|
||||||
|
'code' => 403,
|
||||||
|
'msg' => '禁止跨租户查看用户'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$users = AdminUser::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->field('id, tid, account, name, phone, birth, email, qq, sex, group_id, status, last_login_ip, login_count, create_time, update_time')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $users,
|
||||||
|
'total' => count($users)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '获取用户失败:' . $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,13 +97,22 @@ class UserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function getUserInfo(int $id)
|
public function getUserInfo(int $id)
|
||||||
{
|
{
|
||||||
|
$tid = $this->getTenantId();
|
||||||
$user = AdminUser::where('id', $id)
|
$user = AdminUser::where('id', $id)
|
||||||
->field('id, account, name, phone,email, qq, sex, group_id, status')
|
->where('tid', $tid)
|
||||||
->find();
|
->where('delete_time', null)
|
||||||
|
->field('id, account, name, phone, email, birth, qq, sex, group_id, status, create_time, last_login_ip')
|
||||||
|
->find();
|
||||||
|
if (!$user) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在或无权限访问'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('用户管理', '获取用户信息', ['id' => $id]);
|
$this->logSuccess('用户管理', '获取用户信息', ['id' => $id]);
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '获取成功',
|
'msg' => '获取成功',
|
||||||
@@ -58,10 +127,20 @@ class UserController extends BaseController
|
|||||||
public function changePassword(int $id, string $password)
|
public function changePassword(int $id, string $password)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
AdminUser::where('id', $id)->update([
|
$tid = $this->getCurrentTenantIdOrFail();
|
||||||
|
$affected = AdminUser::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update([
|
||||||
'password' => md5($password),
|
'password' => md5($password),
|
||||||
'update_time' => date('Y-m-d H:i:s')
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
]);
|
]);
|
||||||
|
if (!$affected) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在或无权限修改'
|
||||||
|
]);
|
||||||
|
}
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
$this->logSuccess('用户管理', '修改密码', ['id' => $id]);
|
$this->logSuccess('用户管理', '修改密码', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
@@ -85,12 +164,21 @@ class UserController extends BaseController
|
|||||||
public function addUser()
|
public function addUser()
|
||||||
{
|
{
|
||||||
$data = request()->param();
|
$data = request()->param();
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if ($tid <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '未获取到有效租户信息'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$data['password'] = md5($data['password']);
|
$data['password'] = md5($data['password']);
|
||||||
$data['create_time'] = date('Y-m-d H:i:s');
|
$data['create_time'] = date('Y-m-d H:i:s');
|
||||||
$data['update_time'] = $data['create_time'];
|
$data['update_time'] = $data['create_time'];
|
||||||
$data['group_id'] = 2;
|
$data['group_id'] = 2;
|
||||||
|
$data['tid'] = $tid;
|
||||||
|
|
||||||
$id = AdminUser::insertGetId($data);
|
$id = AdminUser::insertGetId($data);
|
||||||
// 记录操作日志
|
|
||||||
$this->logSuccess('用户管理', '添加用户', ['data' => $data]);
|
$this->logSuccess('用户管理', '添加用户', ['data' => $data]);
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
@@ -107,8 +195,25 @@ class UserController extends BaseController
|
|||||||
{
|
{
|
||||||
$data = request()->param();
|
$data = request()->param();
|
||||||
unset($data['_t'], $data['id']);
|
unset($data['_t'], $data['id']);
|
||||||
|
unset($data['tid']);
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
if ($tid <= 0) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '未获取到有效租户信息'
|
||||||
|
]);
|
||||||
|
}
|
||||||
$data['update_time'] = date('Y-m-d H:i:s');
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
AdminUser::where('id', $id)->update($data);
|
$affected = AdminUser::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->update($data);
|
||||||
|
if (!$affected) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在或无权限编辑'
|
||||||
|
]);
|
||||||
|
}
|
||||||
$this->logSuccess('用户管理', '编辑用户', ['id' => $id]);
|
$this->logSuccess('用户管理', '编辑用户', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
@@ -122,19 +227,32 @@ class UserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function deleteUser(int $id)
|
public function deleteUser(int $id)
|
||||||
{
|
{
|
||||||
$user = AdminUser::where('id', $id)->where('delete_time', null)->find();
|
$tid = $this->getTenantId();
|
||||||
|
if ($tid <= 0) {
|
||||||
if (!$user) {
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 404,
|
'code' => 401,
|
||||||
'msg' => '用户不存在或已删除'
|
'msg' => '未获取到有效租户信息'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
AdminUser::where('id', $id)->update([
|
$user = AdminUser::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在、已删除或无权限操作'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminUser::where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->update([
|
||||||
'delete_time' => date('Y-m-d H:i:s')
|
'delete_time' => date('Y-m-d H:i:s')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->logSuccess('用户管理', '删除用户', ['id' => $id]);
|
$this->logSuccess('用户管理', '删除用户', ['id' => $id]);
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ return [
|
|||||||
// \think\middleware\CheckRequestCache::class,
|
// \think\middleware\CheckRequestCache::class,
|
||||||
// 多语言加载
|
// 多语言加载
|
||||||
// \think\middleware\LoadLangPack::class,
|
// \think\middleware\LoadLangPack::class,
|
||||||
|
// 跨域支持
|
||||||
|
\app\common\middleware\AllowCrossDomain::class,
|
||||||
// Session初始化
|
// Session初始化
|
||||||
\think\middleware\SessionInit::class,
|
\think\middleware\SessionInit::class,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace app\admin\middleware;
|
|
||||||
|
|
||||||
use think\Response;
|
|
||||||
use think\Request;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义跨域中间件
|
|
||||||
* 解决 AJAX 请求 Cookie 传递问题
|
|
||||||
*/
|
|
||||||
class CustomCors
|
|
||||||
{
|
|
||||||
public function handle(Request $request, \Closure $next): Response
|
|
||||||
{
|
|
||||||
$origin = $request->header('origin', '');
|
|
||||||
|
|
||||||
// 允许的域名列表(根据实际情况修改)
|
|
||||||
$allowedDomains = [
|
|
||||||
'http://localhost:3000',
|
|
||||||
'http://localhost:8000',
|
|
||||||
'http://127.0.0.1:3000',
|
|
||||||
'http://127.0.0.1:8000',
|
|
||||||
'http://backapi.yunzer.cn',
|
|
||||||
'http://localhost:5173',
|
|
||||||
'http://www.yunzer.cn',
|
|
||||||
'https://www.yunzer.cn',
|
|
||||||
'http://yunzer.cn',
|
|
||||||
'https://yunzer.cn',
|
|
||||||
'http://back.yunzer.cn',
|
|
||||||
'https://back.yunzer.cn',
|
|
||||||
'http://backend.yunzer.cn',
|
|
||||||
'https://backend.yunzer.cn',
|
|
||||||
];
|
|
||||||
|
|
||||||
// 检查是否为允许的域名
|
|
||||||
if (in_array($origin, $allowedDomains)) {
|
|
||||||
$header['Access-Control-Allow-Origin'] = $origin;
|
|
||||||
} else {
|
|
||||||
// 对于同源请求,允许当前域名
|
|
||||||
if (!empty($origin)) {
|
|
||||||
$header['Access-Control-Allow-Origin'] = $origin;
|
|
||||||
} else {
|
|
||||||
$header['Access-Control-Allow-Origin'] = '*';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 OPTIONS 预检请求,直接返回
|
|
||||||
if ($request->method() === 'OPTIONS') {
|
|
||||||
$header['Access-Control-Allow-Credentials'] = 'true';
|
|
||||||
$header['Access-Control-Max-Age'] = 1800;
|
|
||||||
$header['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
|
|
||||||
$header['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With';
|
|
||||||
\think\facade\Log::record('CORS OPTIONS preflight for: ' . $origin);
|
|
||||||
return response('', 200, $header);
|
|
||||||
}
|
|
||||||
|
|
||||||
$header['Access-Control-Allow-Credentials'] = 'true';
|
|
||||||
$header['Access-Control-Max-Age'] = 1800;
|
|
||||||
$header['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
|
|
||||||
$header['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With';
|
|
||||||
|
|
||||||
return $next($request)->header($header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+16
-108
@@ -1,114 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
use think\facade\Route;
|
use think\facade\Route;
|
||||||
|
|
||||||
// 首页路由
|
/**
|
||||||
Route::get('/', 'app\\admin\\controller\\Index@index');
|
* 自动加载子路由文件
|
||||||
Route::get('index/index', 'app\\admin\\controller\\Index@index');
|
* 路由文件存放在 routes/ 目录下
|
||||||
|
*/
|
||||||
|
$routesPath = __DIR__ . '/routes';
|
||||||
|
|
||||||
|
// 检查路由目录是否存在
|
||||||
|
if (is_dir($routesPath)) {
|
||||||
|
// 获取所有 .php 文件
|
||||||
|
$routeFiles = glob($routesPath . '/*.php');
|
||||||
|
|
||||||
// 静态文件路由 - 必须在其他路由之前定义,使用通配符匹配所有storage路径
|
// 按名称排序,确保加载顺序
|
||||||
Route::get('storage/:path', 'app\\admin\\controller\\StorageController@index')->pattern(['path' => '.*']);
|
sort($routeFiles);
|
||||||
|
|
||||||
// 登录路由
|
// 加载每个路由文件
|
||||||
Route::post('login', 'app\\admin\\controller\\LoginController@login');
|
foreach ($routeFiles as $file) {
|
||||||
Route::post('logout', 'app\\admin\\controller\\LoginController@logout');
|
require_once $file;
|
||||||
Route::get('user/info', 'app\\admin\\controller\\LoginController@userInfo');
|
}
|
||||||
|
}
|
||||||
// 菜单路由
|
|
||||||
Route::get('allmenu', 'app\\admin\\controller\\MenuController@getAllMenus');
|
|
||||||
Route::get('menu/:id', 'app\\admin\\controller\\MenuController@getMenus');
|
|
||||||
Route::post('createMenu', 'app\\admin\\controller\\MenuController@createMenu');
|
|
||||||
Route::put('updateMenu/:id', 'app\\admin\\controller\\MenuController@updateMenu');
|
|
||||||
Route::delete('deleteMenu/:id', 'app\\admin\\controller\\MenuController@deleteMenu');
|
|
||||||
Route::patch('menu/status/:id', 'app\\admin\\controller\\MenuController@updateMenuStatus');
|
|
||||||
|
|
||||||
// 前端导航路由
|
|
||||||
Route::get('frontmenus', 'app\\admin\\controller\\FrontMenuController@getFrontMenus');
|
|
||||||
Route::post('createfrontmenu', 'app\\admin\\controller\\FrontMenuController@createFrontMenu');
|
|
||||||
Route::post('editfrontmenu/:id', 'app\\admin\\controller\\FrontMenuController@editFrontMenu');
|
|
||||||
Route::delete('deletefrontmenu/:id', 'app\\admin\\controller\\FrontMenuController@deleteFrontMenu');
|
|
||||||
|
|
||||||
// Banner路由
|
|
||||||
Route::get('allbanners', 'app\\admin\\controller\\BannerController@getAllBanners');
|
|
||||||
Route::post('createbanner', 'app\\admin\\controller\\BannerController@createBanner');
|
|
||||||
Route::post('editbanner/:id', 'app\\admin\\controller\\BannerController@editBanner');
|
|
||||||
Route::delete('deletebanner/:id', 'app\\admin\\controller\\BannerController@deleteBanner');
|
|
||||||
|
|
||||||
// 单页路由
|
|
||||||
Route::get('allonepages', 'app\\admin\\controller\\OnePageController@getAllOnePages');
|
|
||||||
Route::post('createonepage', 'app\\admin\\controller\\OnePageController@createOnePage');
|
|
||||||
Route::post('editonepage/:id', 'app\\admin\\controller\\OnePageController@editOnePage');
|
|
||||||
Route::delete('deleteonepage/:id', 'app\\admin\\controller\\OnePageController@deleteOnePage');
|
|
||||||
|
|
||||||
// 文章路由
|
|
||||||
Route::get('articlesList', 'app\\admin\\controller\\Article\\ArticleController@getArticlesList');
|
|
||||||
Route::get('allarticles', 'app\\admin\\controller\\Article\\ArticleController@getAllArticles');
|
|
||||||
Route::get('articles/:id', 'app\\admin\\controller\\Article\\ArticleController@getArticle');
|
|
||||||
Route::post('createarticle', 'app\\admin\\controller\\Article\\ArticleController@createArticle');
|
|
||||||
Route::post('editarticle/:id', 'app\\admin\\controller\\Article\\ArticleController@editArticle');
|
|
||||||
Route::delete('deletearticle/:id', 'app\\admin\\controller\\Article\\ArticleController@deleteArticle');
|
|
||||||
Route::post('publisharticle/:id', 'app\\admin\\controller\\Article\\ArticleController@publishArticle');
|
|
||||||
Route::post('unPublisharticle/:id', 'app\\admin\\controller\\Article\\ArticleController@unPublishArticle');
|
|
||||||
Route::post('articleRecommend/:id', 'app\\admin\\controller\\Article\\ArticleController@articleRecommend');
|
|
||||||
Route::post('unArticleRecommend/:id', 'app\\admin\\controller\\Article\\ArticleController@unArticleRecommend');
|
|
||||||
Route::post('articleTop/:id', 'app\\admin\\controller\\Article\\ArticleController@articleTop');
|
|
||||||
Route::post('unArticleTop/:id', 'app\\admin\\controller\\Article\\ArticleController@unArticleTop');
|
|
||||||
|
|
||||||
// 文章分类路由
|
|
||||||
Route::get('allcategories', 'app\\admin\\controller\\Article\\ArticleCategoryController@getAllArticleCategories');
|
|
||||||
Route::get('categories', 'app\\admin\\controller\\Article\\ArticleCategoryController@getArticleCategories');
|
|
||||||
Route::delete('categories/:id', 'app\\admin\\controller\\Article\\ArticleCategoryController@deleteCategory');
|
|
||||||
Route::post('createCategory', 'app\\admin\\controller\\Article\\ArticleCategoryController@createCategory');
|
|
||||||
Route::post('editCategory/:id', 'app\\admin\\controller\\Article\\ArticleCategoryController@editCategory');
|
|
||||||
|
|
||||||
// 文件路由
|
|
||||||
Route::get('usercate', 'app\\admin\\controller\\FileController@getUserCate');
|
|
||||||
Route::get('allfiles', 'app\\admin\\controller\\FileController@getAllFiles');
|
|
||||||
Route::get('catefiles/:id', 'app\\admin\\controller\\FileController@getCateFiles');
|
|
||||||
Route::post('uploadfile', 'app\\admin\\controller\\FileController@uploadFile');
|
|
||||||
Route::post('updatefile/:id', 'app\\admin\\controller\\FileController@updateFile');
|
|
||||||
Route::delete('deletefile/:id', 'app\\admin\\controller\\FileController@deleteFile');
|
|
||||||
Route::get('movefile/:id', 'app\\admin\\controller\\FileController@moveFile');
|
|
||||||
Route::post('createfilecate', 'app\\admin\\controller\\FileController@createFileCate');
|
|
||||||
Route::post('renamefilecate/:id', 'app\\admin\\controller\\FileController@renameFileCate');
|
|
||||||
Route::delete('deletefilecate/:id', 'app\\admin\\controller\\FileController@deleteFileCate');
|
|
||||||
|
|
||||||
// 用户路由
|
|
||||||
Route::get('getAllUsers', 'app\\admin\\controller\\UserController@getAllUsers');
|
|
||||||
Route::get('getUserInfo/:id', 'app\\admin\\controller\\UserController@getUserInfo');
|
|
||||||
Route::post('addUser', 'app\\admin\\controller\\UserController@addUser');
|
|
||||||
Route::post('editUser/:id', 'app\\admin\\controller\\UserController@editUser');
|
|
||||||
Route::delete('deleteUser/:id', 'app\\admin\\controller\\UserController@deleteUser');
|
|
||||||
Route::post('changePassword', 'app\\admin\\controller\\UserController@changePassword');
|
|
||||||
|
|
||||||
// 角色路由
|
|
||||||
Route::get('allRoles', 'app\\admin\\controller\\RoleController@getAllRoles');
|
|
||||||
Route::get('roles/:id', 'app\\admin\\controller\\RoleController@getRoleById');
|
|
||||||
Route::post('roles', 'app\\admin\\controller\\RoleController@createRole');
|
|
||||||
Route::put('roles/:id', 'app\\admin\\controller\\RoleController@updateRole');
|
|
||||||
Route::delete('roles/:id', 'app\\admin\\controller\\RoleController@deleteRole');
|
|
||||||
|
|
||||||
// 操作日志路由(注意:具体路径要在动态路径之前)
|
|
||||||
Route::get('operationLogs/statistics', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationStatistics');
|
|
||||||
Route::get('operationLogs/:id', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationLogDetail');
|
|
||||||
Route::get('operationLogs', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationLogs');
|
|
||||||
|
|
||||||
// 站点设置路由
|
|
||||||
Route::get('normalInfos', 'app\\admin\\controller\\SiteSettingsController@getNormalInfos');
|
|
||||||
Route::post('saveNormalInfos', 'app\\admin\\controller\\SiteSettingsController@saveNormalInfos');
|
|
||||||
Route::get('legalInfos', 'app\\admin\\controller\\SiteSettingsController@getLegalInfos');
|
|
||||||
Route::post('saveLegalInfos', 'app\\admin\\controller\\SiteSettingsController@saveLegalInfos');
|
|
||||||
|
|
||||||
// 数据统计路由
|
|
||||||
Route::get('contentstats', 'app\\admin\\controller\\AnalyticsController@getContentStats');
|
|
||||||
Route::get('usersstats', 'app\\admin\\controller\\AnalyticsController@getUserStats');
|
|
||||||
|
|
||||||
// 模块管理路由
|
|
||||||
Route::get('modules/list', 'app\\admin\\controller\\ModulesController@getList');
|
|
||||||
Route::get('modules/:id', 'app\\admin\\controller\\ModulesController@getDetail');
|
|
||||||
Route::post('modules', 'app\\admin\\controller\\ModulesController@add');
|
|
||||||
Route::put('modules/:id', 'app\\admin\\controller\\ModulesController@edit');
|
|
||||||
Route::delete('modules/:id', 'app\\admin\\controller\\ModulesController@delete');
|
|
||||||
Route::post('modules/batchDelete', 'app\\admin\\controller\\ModulesController@batchDelete');
|
|
||||||
Route::post('modules/status', 'app\\admin\\controller\\ModulesController@changeStatus');
|
|
||||||
Route::get('modules/select/list', 'app\\admin\\controller\\ModulesController@getSelectList');
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 数据统计路由
|
||||||
|
Route::get('contentstats', 'app\\admin\\controller\\Cms\\Analytics\\AnalyticsController@getContentStats');
|
||||||
|
Route::get('usersstats', 'app\\admin\\controller\\Cms\\Analytics\\AnalyticsController@getUserStats');
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 文章路由
|
||||||
|
Route::get('articlesList', 'app\\admin\\controller\\Cms\\Article\\ArticleController@getArticlesList');
|
||||||
|
Route::get('allarticles', 'app\\admin\\controller\\Cms\\Article\\ArticleController@getAllArticles');
|
||||||
|
Route::get('articles/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@getArticle');
|
||||||
|
Route::post('createarticle', 'app\\admin\\controller\\Cms\\Article\\ArticleController@createArticle');
|
||||||
|
Route::post('editarticle/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@editArticle');
|
||||||
|
Route::delete('deletearticle/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@deleteArticle');
|
||||||
|
Route::post('publisharticle/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@publishArticle');
|
||||||
|
Route::post('unPublisharticle/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@unPublishArticle');
|
||||||
|
Route::post('articleRecommend/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@articleRecommend');
|
||||||
|
Route::post('unArticleRecommend/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@unArticleRecommend');
|
||||||
|
Route::post('articleTop/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@articleTop');
|
||||||
|
Route::post('unArticleTop/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleController@unArticleTop');
|
||||||
|
|
||||||
|
// 文章分类路由
|
||||||
|
Route::get('allcategories', 'app\\admin\\controller\\Cms\\Article\\ArticleCategoryController@getAllArticleCategories');
|
||||||
|
Route::get('categories', 'app\\admin\\controller\\Cms\\Article\\ArticleCategoryController@getArticleCategories');
|
||||||
|
Route::delete('categories/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleCategoryController@deleteCategory');
|
||||||
|
Route::post('createCategory', 'app\\admin\\controller\\Cms\\Article\\ArticleCategoryController@createCategory');
|
||||||
|
Route::post('editCategory/:id', 'app\\admin\\controller\\Cms\\Article\\ArticleCategoryController@editCategory');
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 宝贝管理路由
|
||||||
|
Route::group('babys', function() {
|
||||||
|
// 获取宝贝列表
|
||||||
|
Route::get('list', 'app\admin\controller\BabyHealth\BabysController/getBabyList');
|
||||||
|
// 获取宝贝详情
|
||||||
|
Route::get(':id', 'app\admin\controller\BabyHealth\BabysController/getBabyDetail');
|
||||||
|
// 创建宝贝
|
||||||
|
Route::post('create', 'app\admin\controller\BabyHealth\BabysController/createBaby');
|
||||||
|
// 更新宝贝
|
||||||
|
Route::post('update/:id', 'app\admin\controller\BabyHealth\BabysController/editBaby');
|
||||||
|
// 删除宝贝
|
||||||
|
Route::delete('delete/:id', 'app\admin\controller\BabyHealth\BabysController/deleteBaby');
|
||||||
|
// 获取父母信息
|
||||||
|
Route::get('parents/:id', 'app\admin\controller\BabyHealth\BabysController/getParents');
|
||||||
|
// 绑定父母
|
||||||
|
Route::post('bind-parents/:id', 'app\admin\controller\BabyHealth\BabysController/bindParent');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 用户管理路由
|
||||||
|
Route::group('babyhealthUser', function() {
|
||||||
|
Route::get('list', 'app\admin\controller\BabyHealth\UserController/getUserList');
|
||||||
|
Route::get('detail/:id', 'app\admin\controller\BabyHealth\UserController/getUserDetail');
|
||||||
|
Route::post('create', 'app\admin\controller\BabyHealth\UserController/createUser');
|
||||||
|
Route::post('update/:id', 'app\admin\controller\BabyHealth\UserController/updateUser');
|
||||||
|
Route::delete('delete/:id', 'app\admin\controller\BabyHealth\UserController/deleteUser');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 统计路由
|
||||||
|
Route::group('babyhealthDashborad', function() {
|
||||||
|
Route::get('dashborad', 'app\admin\controller\BabyHealth\DashboradController/getDashborad');
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// Banner路由
|
||||||
|
Route::get('allbanners', 'app\\admin\\controller\\Cms\\Banner\\BannerController@getAllBanners');
|
||||||
|
Route::post('createbanner', 'app\\admin\\controller\\Cms\\Banner\\BannerController@createBanner');
|
||||||
|
Route::post('editbanner/:id', 'app\\admin\\controller\\Cms\\Banner\\BannerController@editBanner');
|
||||||
|
Route::delete('deletebanner/:id', 'app\\admin\\controller\\Cms\\Banner\\BannerController@deleteBanner');
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 首页路由
|
||||||
|
Route::get('/', 'app\\admin\\controller\\Index@index');
|
||||||
|
Route::get('index/index', 'app\\admin\\controller\\Index@index');
|
||||||
|
|
||||||
|
// 静态文件路由 - 必须在其他路由之前定义,使用通配符匹配所有storage路径
|
||||||
|
Route::get('storage/:path', 'app\\admin\\controller\\StorageController@index')->pattern(['path' => '.*']);
|
||||||
|
|
||||||
|
// 登录路由
|
||||||
|
Route::post('loginInfo', 'app\\admin\\controller\\LoginController@loginInfo');
|
||||||
|
Route::post('login', 'app\\admin\\controller\\LoginController@login');
|
||||||
|
Route::post('sendLoginCode', 'app\\admin\\controller\\LoginController@sendLoginCode');
|
||||||
|
Route::post('loginBySms', 'app\\admin\\controller\\LoginController@loginBySms');
|
||||||
|
Route::post('sendRegisterCode', 'app\\admin\\controller\\LoginController@sendRegisterCode');
|
||||||
|
Route::post('sendResetCode', 'app\\admin\\controller\\LoginController@sendResetCode');
|
||||||
|
Route::post('register', 'app\\admin\\controller\\LoginController@register');
|
||||||
|
Route::post('resetPassword', 'app\\admin\\controller\\LoginController@resetPassword');
|
||||||
|
Route::post('logout', 'app\\admin\\controller\\LoginController@logout');
|
||||||
|
Route::get('user/info', 'app\\admin\\controller\\LoginController@userInfo');
|
||||||
|
|
||||||
|
// 极验路由
|
||||||
|
Route::get('login/getGeetest3Infos', 'app\\admin\\controller\\LoginController@getGeetest3Infos');
|
||||||
|
Route::get('login/getGeetest4Infos', 'app\\admin\\controller\\LoginController@getGeetest4Infos');
|
||||||
|
Route::get('login/getOpenVerify', 'app\\admin\\controller\\LoginController@getOpenVerify');
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 需求路由
|
||||||
|
Route::get('demandList', 'app\\admin\\controller\\Cms\\Demand\\DemandController@getDemandList');
|
||||||
|
Route::post('addDemand', 'app\\admin\\controller\\Cms\\Demand\\DemandController@addDemand');
|
||||||
|
Route::post('editDemand/:id', 'app\\admin\\controller\\Cms\\Demand\\DemandController@editDemand');
|
||||||
|
Route::post('deleteDemand/:id', 'app\\admin\\controller\\Cms\\Demand\\DemandController@deleteDemand');
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 主域名池管理路由
|
||||||
|
Route::group('domain/pool', function () {
|
||||||
|
Route::get('index', 'app\admin\controller\Cms\Domain\DomainPoolController/index');
|
||||||
|
Route::get('getEnabledDomains', 'app\admin\controller\Cms\Domain\DomainPoolController/getEnabledDomains');
|
||||||
|
Route::post('create', 'app\admin\controller\Cms\Domain\DomainPoolController/create');
|
||||||
|
Route::post('update', 'app\admin\controller\Cms\Domain\DomainPoolController/update');
|
||||||
|
Route::delete('delete/:id', 'app\admin\controller\Cms\Domain\DomainPoolController/delete');
|
||||||
|
Route::post('toggleStatus', 'app\admin\controller\Cms\Domain\DomainPoolController/toggleStatus');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 租户域名绑定路由
|
||||||
|
Route::group('domain/tenant', function () {
|
||||||
|
Route::get('index', 'app\admin\controller\Cms\Domain\TenantDomainController/index');
|
||||||
|
Route::get('myDomains', 'app\admin\controller\Cms\Domain\TenantDomainController/myDomains');
|
||||||
|
Route::post('apply', 'app\admin\controller\Cms\Domain\TenantDomainController/apply');
|
||||||
|
Route::post('audit', 'app\admin\controller\Cms\Domain\TenantDomainController/audit');
|
||||||
|
Route::post('toggleStatus', 'app\admin\controller\Cms\Domain\TenantDomainController/toggleStatus');
|
||||||
|
Route::delete('delete/:id', 'app\admin\controller\Cms\Domain\TenantDomainController/delete');
|
||||||
|
});
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 邮箱管理路由
|
||||||
|
Route::group('email', function () {
|
||||||
|
// 获取邮箱信息
|
||||||
|
Route::get('info', 'app\admin\controller\System\EmailController/getEmailInfo');
|
||||||
|
// 编辑邮箱信息
|
||||||
|
Route::post('editinfo', 'app\admin\controller\System\EmailController/editEmailInfo');
|
||||||
|
// 发送测试邮件
|
||||||
|
Route::post('sendtestemail', 'app\admin\controller\System\EmailController/sendTestEmail');
|
||||||
|
});
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 组织机构管理路由
|
||||||
|
Route::group('erp', function() {
|
||||||
|
Route::get('getOrganization', 'app\admin\controller\Erp\OrganizationController/getOrganization');
|
||||||
|
Route::get('getOrganizationDetail/:id', 'app\admin\controller\Erp\OrganizationController/getOrganizationDetail');
|
||||||
|
Route::post('createOrganization', 'app\admin\controller\Erp\OrganizationController/createOrganization');
|
||||||
|
Route::post('editOrganization/:id', 'app\admin\controller\Erp\OrganizationController/editOrganization');
|
||||||
|
Route::delete('deleteOrganization/:id', 'app\admin\controller\Erp\OrganizationController/deleteOrganization');
|
||||||
|
Route::get('getCompanys', 'app\admin\controller\Erp\OrganizationController/getCompanys');
|
||||||
|
Route::get('getDepartments', 'app\admin\controller\Erp\OrganizationController/getDepartments');
|
||||||
|
|
||||||
|
});
|
||||||
|
// 员工管理路由
|
||||||
|
Route::group('erp', function() {
|
||||||
|
Route::get('getEmployee', 'app\admin\controller\Erp\EmployeeController/getEmployee');
|
||||||
|
Route::get('getEmployeeDetail/:id', 'app\admin\controller\Erp\EmployeeController/getEmployeeDetail');
|
||||||
|
Route::post('createEmployee', 'app\admin\controller\Erp\EmployeeController/createEmployee');
|
||||||
|
Route::post('editEmployee/:id', 'app\admin\controller\Erp\EmployeeController/editEmployee');
|
||||||
|
Route::delete('deleteEmployee/:id', 'app\admin\controller\Erp\EmployeeController/deleteEmployee');
|
||||||
|
});
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 文件路由
|
||||||
|
Route::get('usercate', 'app\\admin\\controller\\System\\FileController@getUserCate');
|
||||||
|
Route::get('allfiles', 'app\\admin\\controller\\System\\FileController@getAllFiles');
|
||||||
|
Route::get('catefiles/:id', 'app\\admin\\controller\\System\\FileController@getCateFiles');
|
||||||
|
Route::post('uploadfile', 'app\\admin\\controller\\System\\FileController@uploadFile');
|
||||||
|
Route::post('uploadfiles', 'app\\admin\\controller\\System\\FileController@uploadFile');
|
||||||
|
Route::post('updatefile/:id', 'app\\admin\\controller\\System\\FileController@updateFile');
|
||||||
|
Route::delete('deletefile/:id', 'app\\admin\\controller\\System\\FileController@deleteFile');
|
||||||
|
Route::get('movefile/:id', 'app\\admin\\controller\\System\\FileController@moveFile');
|
||||||
|
Route::post('createfilecate', 'app\\admin\\controller\\System\\FileController@createFileCate');
|
||||||
|
Route::post('renamefilecate/:id', 'app\\admin\\controller\\System\\FileController@renameFileCate');
|
||||||
|
Route::delete('deletefilecate/:id', 'app\\admin\\controller\\System\\FileController@deleteFileCate');
|
||||||
|
|
||||||
|
Route::post('uploadavatar', 'app\\admin\\controller\\System\\FileController@uploadAvatar');
|
||||||
|
Route::post('uploadavatar/:id', 'app\\admin\\controller\\System\\FileController@updateAvatar');
|
||||||
|
Route::post('batchdeletefiles', 'app\\admin\\controller\\System\\FileController@batchDeleteFiles');
|
||||||
|
|
||||||
|
Route::post('batchDeleteFilesPermanently', 'app\\admin\\controller\\System\\FileController@batchDeleteFilesPermanently');
|
||||||
|
Route::post('batchMoveFiles', 'app\\admin\\controller\\System\\FileController@batchMoveFiles');
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 友情链接路由
|
||||||
|
Route::get('friendlinks', 'app\admin\controller\Cms\Friendlink\FriendlinkController@getList');
|
||||||
|
Route::get('friendlinks/all', 'app\admin\controller\Cms\Friendlink\FriendlinkController@getAll');
|
||||||
|
Route::post('friendlinks', 'app\admin\controller\Cms\Friendlink\FriendlinkController@add');
|
||||||
|
Route::put('friendlinks/:id', 'app\admin\controller\Cms\Friendlink\FriendlinkController@update');
|
||||||
|
Route::delete('friendlinks/:id', 'app\admin\controller\Cms\Friendlink\FriendlinkController@delete');
|
||||||
|
Route::post('friendlinks/batchdelete', 'app\admin\controller\Cms\Friendlink\FriendlinkController@batchDelete');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 前端导航路由
|
||||||
|
Route::get('frontmenus', 'app\\admin\\controller\\Cms\\FrontMenu\\FrontMenuController@getFrontMenus');
|
||||||
|
Route::post('createfrontmenu', 'app\\admin\\controller\\Cms\\FrontMenu\\FrontMenuController@createFrontMenu');
|
||||||
|
Route::post('editfrontmenu/:id', 'app\\admin\\controller\\Cms\\FrontMenu\\FrontMenuController@editFrontMenu');
|
||||||
|
Route::delete('deletefrontmenu/:id', 'app\\admin\\controller\\Cms\\FrontMenu\\FrontMenuController@deleteFrontMenu');
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 菜单路由
|
||||||
|
Route::get('allmenu', 'app\\admin\\controller\\MenuController@getAllMenus');
|
||||||
|
Route::get('menu/:id', 'app\\admin\\controller\\MenuController@getMenus');
|
||||||
|
Route::post('createMenu', 'app\\admin\\controller\\MenuController@createMenu');
|
||||||
|
Route::put('updateMenu/:id', 'app\\admin\\controller\\MenuController@updateMenu');
|
||||||
|
Route::delete('deleteMenu/:id', 'app\\admin\\controller\\MenuController@deleteMenu');
|
||||||
|
Route::patch('menu/status/:id', 'app\\admin\\controller\\MenuController@updateMenuStatus');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 模块中心路由
|
||||||
|
Route::get('moduleCategory', 'app\\admin\\controller\\ModuleCenterController@getModuleCategory');
|
||||||
|
Route::get('moduleCenter/modules', 'app\\admin\\controller\\ModuleCenterController@getModuleList');
|
||||||
|
Route::post('moduleCenter/editCategory', 'app\\admin\\controller\\ModuleCenterController@editCategory');
|
||||||
|
Route::post('moduleCenter/editModules', 'app\\admin\\controller\\ModuleCenterController@editModules');
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 模块管理路由
|
||||||
|
Route::get('modules/list', 'app\\admin\\controller\\ModulesController@getList');
|
||||||
|
Route::get('modules/getTenantList', 'app\\admin\\controller\\ModulesController@getTenantList');
|
||||||
|
Route::get('modules/:id', 'app\\admin\\controller\\ModulesController@getDetail');
|
||||||
|
Route::post('modules', 'app\\admin\\controller\\ModulesController@add');
|
||||||
|
Route::put('modules/:id', 'app\\admin\\controller\\ModulesController@edit');
|
||||||
|
Route::delete('modules/:id', 'app\\admin\\controller\\ModulesController@delete');
|
||||||
|
Route::post('modules/batchDelete', 'app\\admin\\controller\\ModulesController@batchDelete');
|
||||||
|
Route::post('modules/status', 'app\\admin\\controller\\ModulesController@changeStatus');
|
||||||
|
Route::get('modules/select/list', 'app\\admin\\controller\\ModulesController@getSelectList');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 单页路由
|
||||||
|
Route::get('allonepages', 'app\\admin\\controller\\Cms\\OnePage\\OnePageController@getAllOnePages');
|
||||||
|
Route::post('createonepage', 'app\\admin\\controller\\Cms\\OnePage\\OnePageController@createOnePage');
|
||||||
|
Route::post('editonepage/:id', 'app\\admin\\controller\\Cms\\OnePage\\OnePageController@editOnePage');
|
||||||
|
Route::delete('deleteonepage/:id', 'app\\admin\\controller\\Cms\\OnePage\\OnePageController@deleteOnePage');
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 操作日志路由(注意:具体路径要在动态路径之前)
|
||||||
|
Route::get('operationLogs/statistics', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationStatistics');
|
||||||
|
Route::get('operationLogs/:id', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationLogDetail');
|
||||||
|
Route::get('operationLogs', 'app\\admin\\controller\\OperationLog\\OperationLogController@getOperationLogs');
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 特色产品路由
|
||||||
|
Route::get('productsList', 'app\admin\controller\Cms\Products\ProductsController@productsList');
|
||||||
|
Route::post('addProducts', 'app\admin\controller\Cms\Products\ProductsController@addProducts');
|
||||||
|
Route::put('editProducts/:id', 'app\admin\controller\Cms\Products\ProductsController@editProducts');
|
||||||
|
Route::delete('deleteProducts/:id', 'app\admin\controller\Cms\Products\ProductsController@deleteProducts');
|
||||||
|
|
||||||
|
// 产品分类
|
||||||
|
Route::get('productsTypesList', 'app\admin\controller\Cms\Products\ProductsTypesController@productsTypesList');
|
||||||
|
Route::post('addProductsTypes', 'app\admin\controller\Cms\Products\ProductsTypesController@addProductsTypes');
|
||||||
|
Route::put('editProductsTypes/:id', 'app\admin\controller\Cms\Products\ProductsTypesController@editProductsTypes');
|
||||||
|
Route::delete('deleteProductsTypes/:id', 'app\admin\controller\Cms\Products\ProductsTypesController@deleteProductsTypes');
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 角色路由
|
||||||
|
Route::get('allRoles', 'app\\admin\\controller\\System\\RoleController@getAllRoles');
|
||||||
|
Route::get('roles/:id', 'app\\admin\\controller\\System\\RoleController@getRoleById');
|
||||||
|
Route::post('roles', 'app\\admin\\controller\\System\\RoleController@createRole');
|
||||||
|
Route::put('roles/:id', 'app\\admin\\controller\\System\\RoleController@updateRole');
|
||||||
|
Route::delete('roles/:id', 'app\\admin\\controller\\System\\RoleController@deleteRole');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 特色服务路由
|
||||||
|
Route::get('servicesList', 'app\admin\controller\Cms\Services\ServicesController@servicesList');
|
||||||
|
Route::post('addServices', 'app\admin\controller\Cms\Services\ServicesController@addServices');
|
||||||
|
Route::put('editServices/:id', 'app\admin\controller\Cms\Services\ServicesController@editServices');
|
||||||
|
Route::delete('deleteServices/:id', 'app\admin\controller\Cms\Services\ServicesController@deleteServices');
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 站点设置路由
|
||||||
|
Route::get('normalInfos', 'app\\admin\\controller\\SiteSettingsController@getNormalInfos');
|
||||||
|
Route::post('saveNormalInfos', 'app\\admin\\controller\\SiteSettingsController@saveNormalInfos');
|
||||||
|
Route::get('loginVerifyInfos', 'app\\admin\\controller\\SiteSettingsController@getVerifyInfos');
|
||||||
|
Route::post('saveloginVerifyInfos', 'app\\admin\\controller\\SiteSettingsController@saveVerifyInfos');
|
||||||
|
Route::get('legalInfos', 'app\\admin\\controller\\SiteSettingsController@getLegalInfos');
|
||||||
|
Route::post('saveLegalInfos', 'app\\admin\\controller\\SiteSettingsController@saveLegalInfos');
|
||||||
|
Route::get('companyInfos', 'app\\admin\\controller\\SiteSettingsController@getCompanyInfos');
|
||||||
|
Route::post('saveCompanyInfos', 'app\\admin\\controller\\SiteSettingsController@saveCompanyInfos');
|
||||||
|
Route::get('companySeo', 'app\\admin\\controller\\SiteSettingsController@getCompanySeo');
|
||||||
|
Route::post('saveCompanySeo', 'app\\admin\\controller\\SiteSettingsController@saveCompanySeo');
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 短信管理路由
|
||||||
|
Route::group('sms', function () {
|
||||||
|
// 获取短信网关配置
|
||||||
|
Route::get('info', 'app\\admin\\controller\\System\\SmsController@getSmsInfo');
|
||||||
|
|
||||||
|
// 编辑短信网关配置
|
||||||
|
Route::post('editinfo', 'app\\admin\\controller\\System\\SmsController@editSmsInfo');
|
||||||
|
|
||||||
|
// 发送测试短信(入队任务)
|
||||||
|
Route::post('sendtest', 'app\\admin\\controller\\System\\SmsController@sendTestSms');
|
||||||
|
|
||||||
|
// Android 网关轮询待发送任务
|
||||||
|
Route::post('gateway/poll', 'app\\admin\\controller\\System\\SmsController@gatewayPoll');
|
||||||
|
// 兼容:如果网关端只请求 poll(不带 gateway)
|
||||||
|
Route::post('poll', 'app\\admin\\controller\\System\\SmsController@gatewayPoll');
|
||||||
|
Route::get('poll', 'app\\admin\\controller\\System\\SmsController@gatewayPoll');
|
||||||
|
|
||||||
|
// Android 网关上报短信内容(解析验证码)
|
||||||
|
Route::post('gateway/report', 'app\\admin\\controller\\System\\SmsController@gatewayReport');
|
||||||
|
// 兼容:如果网关端只请求 report(不带 gateway)
|
||||||
|
Route::post('report', 'app\\admin\\controller\\System\\SmsController@gatewayReport');
|
||||||
|
|
||||||
|
// 管理员:短信任务列表(租户隔离)
|
||||||
|
Route::get('taskList', 'app\\admin\\controller\\System\\SmsController@getSmsTaskList');
|
||||||
|
|
||||||
|
// 管理员:编辑短信任务(租户隔离)
|
||||||
|
Route::post('taskEdit/:id', 'app\\admin\\controller\\System\\SmsController@editSmsTask');
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 租户管理路由
|
||||||
|
Route::group('tenant', function() {
|
||||||
|
Route::get('getTenant', 'app\admin\controller\Tenant\TenantController/getTenant');
|
||||||
|
Route::get('getTenantDetail/:id', 'app\admin\controller\Tenant\TenantController/getTenantDetail');
|
||||||
|
Route::post('createTenant', 'app\admin\controller\Tenant\TenantController/createTenant');
|
||||||
|
Route::post('editTenant/:id', 'app\admin\controller\Tenant\TenantController/editTenant');
|
||||||
|
Route::delete('deleteTenant/:id', 'app\admin\controller\Tenant\TenantController/deleteTenant');
|
||||||
|
Route::get('findTenantCode', 'app\admin\controller\Tenant\TenantController/findTenantCode');
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 模板管理路由
|
||||||
|
Route::get('theme', 'app\admin\controller\Cms\Theme\ThemeController@index');
|
||||||
|
Route::post('theme/switch', 'app\admin\controller\Cms\Theme\ThemeController@switch');
|
||||||
|
Route::get('theme/data', 'app\admin\controller\Cms\Theme\ThemeController@getData');
|
||||||
|
Route::post('theme/data', 'app\admin\controller\Cms\Theme\ThemeController@saveData');
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 用户路由
|
||||||
|
Route::get('getAllUsers', 'app\\admin\\controller\\UserController@getAllUsers');
|
||||||
|
Route::get('getTenantUsers/:tenantId', 'app\\admin\\controller\\UserController@getTenantUsers');
|
||||||
|
Route::get('getUserInfo/:id', 'app\\admin\\controller\\UserController@getUserInfo');
|
||||||
|
Route::post('addUser', 'app\\admin\\controller\\UserController@addUser');
|
||||||
|
Route::post('editUser/:id', 'app\\admin\\controller\\UserController@editUser');
|
||||||
|
Route::delete('deleteUser/:id', 'app\\admin\\controller\\UserController@deleteUser');
|
||||||
|
Route::post('changePassword', 'app\\admin\\controller\\UserController@changePassword');
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
// 关键修正:命名空间对应控制器目录
|
||||||
|
namespace app\api;
|
||||||
|
|
||||||
|
use think\App;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\Validate;
|
||||||
|
use think\Request;
|
||||||
|
|
||||||
|
// 在控制器方法中添加
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
|
||||||
|
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制器基础类
|
||||||
|
*/
|
||||||
|
abstract class BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Request实例
|
||||||
|
* @var Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用实例
|
||||||
|
* @var App
|
||||||
|
*/
|
||||||
|
protected $app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否批量验证
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $batchValidate = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制器中间件
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $middleware = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
* @access public
|
||||||
|
* @param App $app 应用对象
|
||||||
|
*/
|
||||||
|
public function __construct(App $app)
|
||||||
|
{
|
||||||
|
$this->app = $app;
|
||||||
|
$this->request = $this->app->request;
|
||||||
|
|
||||||
|
// 控制器初始化
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证数据
|
||||||
|
* @access protected
|
||||||
|
* @param array $data 数据
|
||||||
|
* @param string|array $validate 验证器名或者验证规则数组
|
||||||
|
* @param array $message 提示信息
|
||||||
|
* @param bool $batch 是否批量验证
|
||||||
|
* @return array|string|true
|
||||||
|
* @throws ValidateException
|
||||||
|
*/
|
||||||
|
protected function validate(array $data, string|array $validate, array $message = [], bool $batch = false)
|
||||||
|
{
|
||||||
|
if (is_array($validate)) {
|
||||||
|
$v = new Validate();
|
||||||
|
$v->rule($validate);
|
||||||
|
} else {
|
||||||
|
if (strpos($validate, '.')) {
|
||||||
|
// 支持场景
|
||||||
|
[$validate, $scene] = explode('.', $validate);
|
||||||
|
}
|
||||||
|
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
|
||||||
|
$v = new $class();
|
||||||
|
if (!empty($scene)) {
|
||||||
|
$v->scene($scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$v->message($message);
|
||||||
|
|
||||||
|
// 是否批量验证
|
||||||
|
if ($batch || $this->batchValidate) {
|
||||||
|
$v->batch(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $v->failException(true)->check($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的公共文件
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
use app\api\BaseController;
|
||||||
|
|
||||||
|
|
||||||
|
class Index extends BaseController
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return '后端运行中...';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hello($name = 'ThinkPHP8')
|
||||||
|
{
|
||||||
|
return 'hello,' . $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
use app\api\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Cache;
|
||||||
|
use think\response\Json;
|
||||||
|
use app\service\JwtService;
|
||||||
|
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
use app\model\System\SystemSiteSettings;
|
||||||
|
|
||||||
|
class LoginController extends BaseController
|
||||||
|
{
|
||||||
|
private function generateToken($userInfo): string
|
||||||
|
{
|
||||||
|
return JwtService::generateToken($userInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function verifyToken($token): ?array
|
||||||
|
{
|
||||||
|
return JwtService::verifyToken($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录接口
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function login(): Json
|
||||||
|
{
|
||||||
|
$data = $this->request->param();
|
||||||
|
|
||||||
|
if (isset($data['email'])) {
|
||||||
|
$data['account'] = $data['email'];
|
||||||
|
} elseif (isset($data['phone'])) {
|
||||||
|
$data['account'] = $data['phone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->validate($data, [
|
||||||
|
'account|账号' => 'require|length:3,32',
|
||||||
|
'password|密码' => 'require|length:6,32'
|
||||||
|
]);
|
||||||
|
} catch (ValidateException $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => $e->getError()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = AdminUser::where('account', $data['account'])
|
||||||
|
->where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '账号不存在或已禁用'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md5($data['password']) !== $user['password']) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '密码错误'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminUser::where('id', $user['id'])->update([
|
||||||
|
'login_count' => $user['login_count'] + 1,
|
||||||
|
'last_login_ip' => $this->request->ip()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$userInfo = [
|
||||||
|
'id' => $user['id'],
|
||||||
|
'account' => $user['account'],
|
||||||
|
'name' => $user['name'],
|
||||||
|
'tid' => $user['tid'],
|
||||||
|
'group_id' => $user['group_id']
|
||||||
|
];
|
||||||
|
|
||||||
|
$token = $this->generateToken($userInfo);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '登录成功',
|
||||||
|
'data' => [
|
||||||
|
'token' => $token,
|
||||||
|
'user' => $userInfo
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function logout(): Json
|
||||||
|
{
|
||||||
|
$authHeader = $this->request->header('Authorization', '');
|
||||||
|
$userInfo = null;
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '退出成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录用户信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function userInfo(): Json
|
||||||
|
{
|
||||||
|
$authHeader = $this->request->header('Authorization', '');
|
||||||
|
|
||||||
|
if (!preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => '未登录'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokenData = $this->verifyToken($matches[1]);
|
||||||
|
|
||||||
|
if (!$tokenData || !isset($tokenData['user'])) {
|
||||||
|
return json([
|
||||||
|
'code' => 401,
|
||||||
|
'msg' => 'Token无效'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = (array)$tokenData['user'];
|
||||||
|
$user_id = $user['id'];
|
||||||
|
|
||||||
|
$userData = AdminUser::where('id', $user_id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->field('id, account, name, phone, qq, sex, group_id, status, create_time, update_time')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$userData) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $userData->toArray()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAdminUserFromToken(): array
|
||||||
|
{
|
||||||
|
return JwtService::getUserFromHeader($this->request->header('Authorization', ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function loginInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
$loginInfo = SystemSiteSettings::select();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $loginInfo
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\api\controller;
|
||||||
|
|
||||||
|
use app\api\BaseController;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
|
||||||
|
use app\model\System\AdminUser;
|
||||||
|
|
||||||
|
class UserController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取所有用户信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getAllUsers()
|
||||||
|
{
|
||||||
|
$users = AdminUser::where('delete_time', null)->field('id, account, name, phone, birth, email, qq, sex, group_id, status, last_login_ip, login_count, create_time, update_time')->select()->toArray();
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => [
|
||||||
|
'list' => $users,
|
||||||
|
'total' => count($users)
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getUserInfo(int $id)
|
||||||
|
{
|
||||||
|
$user = AdminUser::where('id', $id)
|
||||||
|
->field('id, account, name, phone, email, birth, qq, sex, group_id, status, create_time, last_login_ip')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('用户管理', '获取用户信息', ['id' => $id]);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '获取成功',
|
||||||
|
'data' => $user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function changePassword(int $id, string $password)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
AdminUser::where('id', $id)->update([
|
||||||
|
'password' => md5($password),
|
||||||
|
'update_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('用户管理', '修改密码', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '修改成功'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// 记录失败日志
|
||||||
|
$this->logFail('用户管理', '修改密码', $e->getMessage());
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '修改失败'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加用户
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function addUser()
|
||||||
|
{
|
||||||
|
$data = request()->param();
|
||||||
|
$data['password'] = md5($data['password']);
|
||||||
|
$data['create_time'] = date('Y-m-d H:i:s');
|
||||||
|
$data['update_time'] = $data['create_time'];
|
||||||
|
$data['group_id'] = 2;
|
||||||
|
$id = AdminUser::insertGetId($data);
|
||||||
|
// 记录操作日志
|
||||||
|
$this->logSuccess('用户管理', '添加用户', ['data' => $data]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '添加成功',
|
||||||
|
'data' => ['id' => $id]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑用户
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function editUser(int $id)
|
||||||
|
{
|
||||||
|
$data = request()->param();
|
||||||
|
unset($data['_t'], $data['id']);
|
||||||
|
$data['update_time'] = date('Y-m-d H:i:s');
|
||||||
|
AdminUser::where('id', $id)->update($data);
|
||||||
|
$this->logSuccess('用户管理', '编辑用户', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '编辑成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function deleteUser(int $id)
|
||||||
|
{
|
||||||
|
$user = AdminUser::where('id', $id)->where('delete_time', null)->find();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '用户不存在或已删除'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminUser::where('id', $id)->update([
|
||||||
|
'delete_time' => date('Y-m-d H:i:s')
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->logSuccess('用户管理', '删除用户', ['id' => $id]);
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => '删除成功'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
// 这是系统自动生成的event定义文件
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
// 全局中间件定义文件
|
||||||
|
return [
|
||||||
|
// 全局请求缓存
|
||||||
|
// \think\middleware\CheckRequestCache::class,
|
||||||
|
// 多语言加载
|
||||||
|
// \think\middleware\LoadLangPack::class,
|
||||||
|
// Session初始化
|
||||||
|
\app\common\middleware\AllowCrossDomain::class,
|
||||||
|
\think\middleware\SessionInit::class,
|
||||||
|
];
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动加载子路由文件
|
||||||
|
* 路由文件存放在 routes/ 目录下
|
||||||
|
*/
|
||||||
|
$routesPath = __DIR__ . '/routes';
|
||||||
|
|
||||||
|
// 检查路由目录是否存在
|
||||||
|
if (is_dir($routesPath)) {
|
||||||
|
// 获取所有 .php 文件
|
||||||
|
$routeFiles = glob($routesPath . '/*.php');
|
||||||
|
|
||||||
|
// 按名称排序,确保加载顺序
|
||||||
|
sort($routeFiles);
|
||||||
|
|
||||||
|
// 加载每个路由文件
|
||||||
|
foreach ($routeFiles as $file) {
|
||||||
|
require_once $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 登录相关路由(统一加 /api 前缀,和前端保持一致)
|
||||||
|
Route::post('loginInfo', 'app\\api\\controller\\LoginController@loginInfo');
|
||||||
|
Route::post('login', 'app\\api\\controller\\LoginController@login');
|
||||||
|
Route::post('logout', 'app\\api\\controller\\LoginController@logout');
|
||||||
|
Route::get('user/info', 'app\\api\\controller\\LoginController@userInfo');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 模板相关路由
|
||||||
|
Route::get('theme', 'app\admin\controller\ThemeController@index');
|
||||||
|
Route::post('theme/switch', 'app\admin\controller\ThemeController@switch');
|
||||||
|
Route::get('theme/data', 'app\admin\controller\ThemeController@getData');
|
||||||
|
Route::post('theme/data', 'app\admin\controller\ThemeController@saveData');
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Route;
|
||||||
|
|
||||||
|
// 用户路由
|
||||||
|
Route::get('getAllUsers', 'app\\api\\controller\\UserController@getAllUsers');
|
||||||
|
Route::get('getUserInfo/:id', 'app\\api\\controller\\UserController@getUserInfo');
|
||||||
|
Route::post('addUser', 'app\\api\\controller\\UserController@addUser');
|
||||||
|
Route::post('editUser/:id', 'app\\api\\controller\\UserController@editUser');
|
||||||
|
Route::delete('deleteUser/:id', 'app\\api\\controller\\UserController@deleteUser');
|
||||||
|
Route::post('changePassword', 'app\\api\\controller\\UserController@changePassword');
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\middleware;
|
||||||
|
|
||||||
|
use think\Response;
|
||||||
|
use think\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公共跨域中间件
|
||||||
|
* 供所有应用共用
|
||||||
|
*/
|
||||||
|
class AllowCrossDomain
|
||||||
|
{
|
||||||
|
public function handle(Request $request, \Closure $next): Response
|
||||||
|
{
|
||||||
|
$origin = $request->header('origin', '');
|
||||||
|
|
||||||
|
// 允许所有来源(生产环境建议限制具体域名)
|
||||||
|
$header['Access-Control-Allow-Origin'] = $origin ?: '*';
|
||||||
|
|
||||||
|
if ($request->method() === 'OPTIONS') {
|
||||||
|
$header['Access-Control-Allow-Credentials'] = 'true';
|
||||||
|
$header['Access-Control-Max-Age'] = 1800;
|
||||||
|
$header['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
|
||||||
|
$header['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With, X-Current-Domain';
|
||||||
|
return response('', 200, $header);
|
||||||
|
}
|
||||||
|
|
||||||
|
$header['Access-Control-Allow-Credentials'] = 'true';
|
||||||
|
$header['Access-Control-Max-Age'] = 1800;
|
||||||
|
$header['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
|
||||||
|
$header['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With, X-Current-Domain';
|
||||||
|
|
||||||
|
return $next($request)->header($header);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\common\middleware;
|
||||||
|
|
||||||
|
use think\facade\Db;
|
||||||
|
use think\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 域名解析中间件
|
||||||
|
* 通过访问域名自动识别租户
|
||||||
|
*/
|
||||||
|
class DomainParse
|
||||||
|
{
|
||||||
|
public function handle(Request $request, \Closure $next)
|
||||||
|
{
|
||||||
|
$host = $request->host(true); // 获取完整域名,不带端口
|
||||||
|
|
||||||
|
// 你的后台/平台域名(排除,不走租户逻辑)
|
||||||
|
$adminDomains = ['back.yunzer.cn', 'api.yunzer.cn'];
|
||||||
|
$platformDomains = ['www.yunzer.cn', 'yunzer.cn'];
|
||||||
|
|
||||||
|
// 后台/平台/API域名,直接放行
|
||||||
|
if (in_array($host, $adminDomains) || in_array($host, $platformDomains)) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析域名(兼容 yunzer.com.cn/dh2.fun)
|
||||||
|
$domainParts = explode('.', $host);
|
||||||
|
$allowMainDomains = ['yunzer.com.cn', 'dh2.fun'];
|
||||||
|
$mainDomain = '';
|
||||||
|
|
||||||
|
foreach ($allowMainDomains as $domain) {
|
||||||
|
$domainLen = count(explode('.', $domain));
|
||||||
|
$currentLen = count($domainParts);
|
||||||
|
if ($currentLen > $domainLen) {
|
||||||
|
$matchMain = implode('.', array_slice($domainParts, -$domainLen));
|
||||||
|
if ($matchMain === $domain) {
|
||||||
|
$mainDomain = $matchMain;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非租户主域名,放行(走API默认界面,可改为跳转到平台)
|
||||||
|
if (empty($mainDomain)) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询租户域名绑定记录
|
||||||
|
$tenantDomain = Db::name('mete_tenant_domain')
|
||||||
|
->where('full_domain', $host)
|
||||||
|
->where('status', 1)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($tenantDomain) {
|
||||||
|
// 1. 写入租户ID到请求(核心,后续所有逻辑都能获取)
|
||||||
|
$request->tenantId = $tenantDomain['tid'];
|
||||||
|
$request->header('X-Tenant-Id', (string)$tenantDomain['tid']);
|
||||||
|
|
||||||
|
// 2. 额外:写入租户域名信息,方便模板使用
|
||||||
|
$request->tenantDomain = $host;
|
||||||
|
$request->tenantMainDomain = $mainDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use think\App;
|
|||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
use think\Validate;
|
use think\Validate;
|
||||||
use think\Request;
|
use think\Request;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
// 在控制器方法中添加
|
// 在控制器方法中添加
|
||||||
header('Access-Control-Allow-Origin: *');
|
header('Access-Control-Allow-Origin: *');
|
||||||
@@ -44,6 +45,12 @@ abstract class BaseController
|
|||||||
*/
|
*/
|
||||||
protected $middleware = [];
|
protected $middleware = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前租户ID
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $tenantId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造方法
|
* 构造方法
|
||||||
* @access public
|
* @access public
|
||||||
@@ -59,7 +66,65 @@ abstract class BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
protected function initialize() {}
|
protected function initialize()
|
||||||
|
{
|
||||||
|
// 自动检测并设置租户ID
|
||||||
|
$this->initTenantId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化租户ID
|
||||||
|
* 优先从 Referer 获取来源域名,否则使用当前访问域名
|
||||||
|
* 从 mete_tenant_domain 表查询对应的 tid
|
||||||
|
*/
|
||||||
|
protected function initTenantId(): void
|
||||||
|
{
|
||||||
|
// 优先从 Referer 获取来源域名(跨域调用场景)
|
||||||
|
$referer = $this->request->header('Referer');
|
||||||
|
if ($referer) {
|
||||||
|
$host = parse_url($referer, PHP_URL_HOST);
|
||||||
|
} else {
|
||||||
|
// 否则使用当前访问域名
|
||||||
|
$host = $this->request->host(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询域名对应的租户ID
|
||||||
|
$tenantDomain = Db::name('mete_tenant_domain')
|
||||||
|
->where('full_domain', $host)
|
||||||
|
->where('status', 1)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if ($tenantDomain) {
|
||||||
|
$this->tenantId = (int)$tenantDomain['tid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前租户ID
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getTenantId(): int
|
||||||
|
{
|
||||||
|
return $this->tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据域名获取租户ID(静态方法,方便全局调用)
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function getTenantIdByDomain(string $baseUrl): int
|
||||||
|
{
|
||||||
|
|
||||||
|
// 查询域名对应的租户ID
|
||||||
|
$tenantDomain = Db::name('mete_tenant_domain')
|
||||||
|
->where('full_domain', $baseUrl)
|
||||||
|
->where('status', 1)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
return $tenantDomain ? (int)$tenantDomain['tid'] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证数据
|
* 验证数据
|
||||||
|
|||||||
@@ -1,32 +1,33 @@
|
|||||||
<?php
|
<?php
|
||||||
declare (strict_types = 1);
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace app\index\controller\Article;
|
namespace app\index\controller\Article;
|
||||||
|
|
||||||
use app\index\BaseController;
|
use app\index\BaseController;
|
||||||
use app\model\Articles;
|
|
||||||
use app\model\ArticlesCategory;
|
|
||||||
use Symfony\Component\VarDumper\VarDumper;
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
use think\exception\ValidateException;
|
use think\exception\ValidateException;
|
||||||
use think\facade\Request;
|
use think\facade\Request;
|
||||||
use think\facade\Session;
|
use think\facade\Session;
|
||||||
use think\response\Json;
|
use think\response\Json;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
|
use app\model\Cms\Articles;
|
||||||
|
use app\model\Cms\ArticlesCategory;
|
||||||
|
|
||||||
class ArticleController extends BaseController
|
class ArticleController extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 获取新闻中心顶部4篇文章
|
* 获取技术中心顶部4篇文章
|
||||||
* @return Json
|
* @return Json
|
||||||
*/
|
*/
|
||||||
public function getNewsCenterTop4(): Json
|
public function getNewsCenterTop4(): Json
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 1. 查询新闻中心主分类
|
// 1. 查询技术中心主分类
|
||||||
$newsCenterCategory = ArticlesCategory::where('name', '新闻中心')
|
$newsCenterCategory = ArticlesCategory::where('name', '技术中心')
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
if (!$newsCenterCategory) {
|
if (!$newsCenterCategory) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
@@ -34,18 +35,18 @@ class ArticleController extends BaseController
|
|||||||
'list' => [],
|
'list' => [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 获取新闻中心及其子分类的ID列表
|
// 2. 获取技术中心及其子分类的ID列表
|
||||||
$mainCategoryId = $newsCenterCategory['id'];
|
$mainCategoryId = $newsCenterCategory['id'];
|
||||||
|
|
||||||
// 查询子分类
|
// 查询子分类
|
||||||
$subCategories = ArticlesCategory::where('cid', $mainCategoryId)
|
$subCategories = ArticlesCategory::where('cid', $mainCategoryId)
|
||||||
->where('delete_time', null)
|
->where('delete_time', null)
|
||||||
->column('id');
|
->column('id');
|
||||||
|
|
||||||
// 合并主分类和子分类ID
|
// 合并主分类和子分类ID
|
||||||
$categoryIds = array_merge([$mainCategoryId], $subCategories);
|
$categoryIds = array_merge([$mainCategoryId], $subCategories);
|
||||||
|
|
||||||
if (empty($categoryIds)) {
|
if (empty($categoryIds)) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
@@ -53,7 +54,7 @@ class ArticleController extends BaseController
|
|||||||
'list' => [],
|
'list' => [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 查询符合条件的文章,按指定优先级排序,取最新4篇
|
// 3. 查询符合条件的文章,按指定优先级排序,取最新4篇
|
||||||
$articles = Articles::published()
|
$articles = Articles::published()
|
||||||
->whereIn('cate', $categoryIds)
|
->whereIn('cate', $categoryIds)
|
||||||
@@ -75,7 +76,7 @@ class ArticleController extends BaseController
|
|||||||
])
|
])
|
||||||
->limit(4)
|
->limit(4)
|
||||||
->select();
|
->select();
|
||||||
|
|
||||||
// 4. 处理文章数据,去除HTML标签并生成desc字段
|
// 4. 处理文章数据,去除HTML标签并生成desc字段
|
||||||
foreach ($articles as &$article) {
|
foreach ($articles as &$article) {
|
||||||
// 使用PHP的strip_tags函数去除HTML标签,然后截取前100个字符
|
// 使用PHP的strip_tags函数去除HTML标签,然后截取前100个字符
|
||||||
@@ -83,7 +84,7 @@ class ArticleController extends BaseController
|
|||||||
// 移除原始content字段,减少返回数据大小
|
// 移除原始content字段,减少返回数据大小
|
||||||
unset($article['content']);
|
unset($article['content']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => 'success',
|
'msg' => 'success',
|
||||||
@@ -92,15 +93,53 @@ class ArticleController extends BaseController
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// 打印完整错误信息到日志
|
// 打印完整错误信息到日志
|
||||||
$errorMsg = '错误信息:' . $e->getMessage() . ' | 错误行号:' . $e->getLine() . ' | 执行SQL:' . Articles::getLastSql();
|
$errorMsg = '错误信息:' . $e->getMessage() . ' | 错误行号:' . $e->getLine() . ' | 执行SQL:' . Articles::getLastSql();
|
||||||
trace('新闻中心文章查询失败: ' . $errorMsg, 'error');
|
trace('技术中心文章查询失败: ' . $errorMsg, 'error');
|
||||||
return json([
|
return json([
|
||||||
'code' => 500,
|
'code' => 500,
|
||||||
'msg' => '新闻中心文章查询失败,请稍后重试',
|
'msg' => '技术中心文章查询失败,请稍后重试',
|
||||||
'list' => []
|
'list' => []
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文章分类列表(mete_articles_category:当前租户 tid、启用状态)
|
||||||
|
* 支持 baseUrl=租户前台域名,与 getCenterNews 一致,便于 api 域名跨域调用时解析 tid
|
||||||
|
*
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getArticleCategories(): Json
|
||||||
|
{
|
||||||
|
$baseUrl = $this->request->get('baseUrl', '');
|
||||||
|
if (!empty($baseUrl)) {
|
||||||
|
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
if (empty($tid)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '无法识别租户信息',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$articleCategories = ArticlesCategory::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('status', 1)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->order('id', 'asc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $articleCategories,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 游客文章阅读量函数
|
* 游客文章阅读量函数
|
||||||
* @return Json
|
* @return Json
|
||||||
@@ -118,7 +157,7 @@ class ArticleController extends BaseController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
||||||
|
|
||||||
if (!$article) {
|
if (!$article) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 404,
|
'code' => 404,
|
||||||
@@ -164,7 +203,7 @@ class ArticleController extends BaseController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
||||||
|
|
||||||
if (!$article) {
|
if (!$article) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 404,
|
'code' => 404,
|
||||||
@@ -210,15 +249,15 @@ class ArticleController extends BaseController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
$article = Articles::where('id', $id)->where('delete_time', null)->find();
|
||||||
|
|
||||||
if (!$article) {
|
if (!$article) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 404,
|
'code' => 404,
|
||||||
'msg' => '文章不存在',
|
'msg' => '文章不存在',
|
||||||
'list' => []
|
'list' => []
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($article->likes <= 0) {
|
if ($article->likes <= 0) {
|
||||||
return json([
|
return json([
|
||||||
'code' => 400,
|
'code' => 400,
|
||||||
@@ -226,10 +265,10 @@ class ArticleController extends BaseController
|
|||||||
'list' => []
|
'list' => []
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$article->dec('likes');
|
$article->dec('likes');
|
||||||
$article->save();
|
$article->save();
|
||||||
|
|
||||||
return json([
|
return json([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'msg' => '取消点赞成功',
|
'msg' => '取消点赞成功',
|
||||||
@@ -246,4 +285,4 @@ class ArticleController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,282 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\index\controller\Article;
|
||||||
|
|
||||||
|
use app\index\BaseController;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
|
use think\exception\ValidateException;
|
||||||
|
use think\facade\Request;
|
||||||
|
use think\facade\Session;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\db\exception\DbException;
|
||||||
|
|
||||||
|
use app\model\Cms\Articles;
|
||||||
|
use app\model\Cms\ArticlesCategory;
|
||||||
|
use tidy;
|
||||||
|
|
||||||
|
class NewsCenterController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 根据域名获取新闻数据
|
||||||
|
*
|
||||||
|
* 返回字段:list 列表;total 当前租户下已发布新闻总数;count 当前筛选(全部或 cate)下的条数,翻页按 count 与 page_size。
|
||||||
|
*
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getCenterNews(): Json
|
||||||
|
{
|
||||||
|
$baseUrl = (string) $this->request->param('baseUrl', '');
|
||||||
|
|
||||||
|
if ($baseUrl !== '') {
|
||||||
|
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
if (empty($tid)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '无法识别租户信息',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// param 合并 GET,避免个别环境下仅 get 取不到查询串
|
||||||
|
$cateId = (int) $this->request->param('cate', 0);
|
||||||
|
$listPage = (int) $this->request->param('page', 0);
|
||||||
|
$pageSizeReq = (int) $this->request->param('page_size', 0);
|
||||||
|
|
||||||
|
// 点击左侧分类:文章 cate 可能挂在子分类上,需包含「该分类 + 其下所有子分类」id
|
||||||
|
$categoryIdsForFilter = [];
|
||||||
|
if ($cateId > 0) {
|
||||||
|
$categoryIdsForFilter = $this->resolveCategoryBranchIds($cateId, $tid);
|
||||||
|
if ($categoryIdsForFilter === []) {
|
||||||
|
$categoryIdsForFilter = [$cateId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseQuery = static function () use ($tid, $cateId, $categoryIdsForFilter) {
|
||||||
|
$q = Articles::published()
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null);
|
||||||
|
if ($cateId > 0 && $categoryIdsForFilter !== []) {
|
||||||
|
$q->whereIn('cate', $categoryIdsForFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $q;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当前租户下「全部」已发布新闻数(不受 cate 筛选影响)
|
||||||
|
$totalTenantNews = (int) Articles::published()
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
// 当前列表条件下的总数:tid +(可选)cate,用于翻页总页数 = ceil(count / page_size)
|
||||||
|
$countFiltered = (int) $baseQuery()->count();
|
||||||
|
|
||||||
|
$useListPagination = $listPage > 0 && $pageSizeReq > 0;
|
||||||
|
|
||||||
|
if ($useListPagination) {
|
||||||
|
// 新闻中心列表页:服务端分页;不要用查询参数名 page,避免与路由占位符冲突
|
||||||
|
$pageSizeReq = max(1, min($pageSizeReq, 50));
|
||||||
|
$listPage = max(1, $listPage);
|
||||||
|
$articles = $baseQuery()
|
||||||
|
->order('publish_date', 'desc')
|
||||||
|
->page($listPage, $pageSizeReq)
|
||||||
|
->select();
|
||||||
|
} else {
|
||||||
|
// 首页等:按 limit 取前 N 条(默认 8)
|
||||||
|
$limit = (int) $this->request->param('limit', 8);
|
||||||
|
if ($limit < 1) {
|
||||||
|
$limit = 8;
|
||||||
|
}
|
||||||
|
if ($limit > 200) {
|
||||||
|
$limit = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
$articles = $baseQuery()
|
||||||
|
->order('publish_date', 'desc')
|
||||||
|
->limit($limit)
|
||||||
|
->select();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理图片:如果文章 image 为空,则取分类的 image
|
||||||
|
foreach ($articles as &$article) {
|
||||||
|
if (empty($article['image']) && !empty($article['cate'])) {
|
||||||
|
$category = ArticlesCategory::where('id', $article['cate'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if ($category && !empty($category['image'])) {
|
||||||
|
$article['image'] = $category['image'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($article);
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $articles,
|
||||||
|
// 当前租户下新闻总条数(全部状态为已发布)
|
||||||
|
'total' => $totalTenantNews,
|
||||||
|
// 当前筛选(全部或某分类)下的条数,列表翻页按 count 与 page_size 计算
|
||||||
|
'count' => $countFiltered,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析分类筛选用的 id 列表:自身 + mete_articles_category 中 cid=该 id 的所有子孙(同 tid、未删除)
|
||||||
|
*/
|
||||||
|
private function resolveCategoryBranchIds(int $rootId, int $tid): array
|
||||||
|
{
|
||||||
|
if ($rootId <= 0 || $tid <= 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$root = ArticlesCategory::where('id', $rootId)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if (!$root) {
|
||||||
|
return [$rootId];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = [$rootId];
|
||||||
|
$queue = [$rootId];
|
||||||
|
while ($queue !== []) {
|
||||||
|
$pid = array_shift($queue);
|
||||||
|
$children = ArticlesCategory::where('cid', $pid)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->column('id');
|
||||||
|
foreach ($children as $id) {
|
||||||
|
$id = (int) $id;
|
||||||
|
if ($id > 0 && !in_array($id, $ids, true)) {
|
||||||
|
$ids[] = $id;
|
||||||
|
$queue[] = $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取新闻详情
|
||||||
|
* @param int $id 文章ID
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getNewsDetail(int $id): Json
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$baseUrl = $this->request->get('baseUrl', '');
|
||||||
|
if (!empty($baseUrl)) {
|
||||||
|
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
$query = Articles::published()->where('id', $id);
|
||||||
|
if ($tid > 0) {
|
||||||
|
$query->where('tid', $tid);
|
||||||
|
}
|
||||||
|
$article = $query->find();
|
||||||
|
if (!$article) {
|
||||||
|
return json([
|
||||||
|
'code' => 404,
|
||||||
|
'msg' => '文章不存在',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $article,
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '获取新闻详情失败:' . $e->getMessage(),
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上一篇下一篇
|
||||||
|
* @param int $id 文章ID
|
||||||
|
* @param int $cate 分类ID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getNextPreviousArticles(int $id, int $cate): array
|
||||||
|
{
|
||||||
|
$nextArticle = Articles::where('id', '<', $id)
|
||||||
|
->where('cate', $cate)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->where('status', 2)
|
||||||
|
->field('id,title')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
$previousArticle = Articles::where('id', '>', $id)
|
||||||
|
->where('cate', $cate)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->where('status', 2)
|
||||||
|
->field('id,title')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'next' => $nextArticle,
|
||||||
|
'previous' => $previousArticle,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过分类 ID 获取分类名称
|
||||||
|
* @param int $cateId 分类ID
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getCategoryName(int $id): string
|
||||||
|
{
|
||||||
|
$categoryInfo = ArticlesCategory::where('id', $id)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$categoryInfo) {
|
||||||
|
return '未分类';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $categoryInfo['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取相关文章
|
||||||
|
*/
|
||||||
|
private function getRelatedArticles(int $id, int $cate): array
|
||||||
|
{
|
||||||
|
$articles = Articles::where('id', '<>', $id)
|
||||||
|
->where('cate', $cate)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->where('status', 2)
|
||||||
|
->order('top', 'desc')
|
||||||
|
->order('recommend', 'desc')
|
||||||
|
->order('sort', 'desc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->limit(5)
|
||||||
|
->select();
|
||||||
|
|
||||||
|
foreach ($articles as &$article) {
|
||||||
|
$article['cate'] = $this->getCategoryName($article['cate']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $articles,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\index\controller;
|
||||||
|
|
||||||
|
use app\index\BaseController;
|
||||||
|
use think\response\Json;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Banner 控制器
|
||||||
|
*/
|
||||||
|
class BannerController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取 Banner 列表
|
||||||
|
* @return Json
|
||||||
|
*/
|
||||||
|
public function getBanners()
|
||||||
|
{
|
||||||
|
$baseUrl = $this->request->get('baseUrl', '');
|
||||||
|
|
||||||
|
if (!empty($baseUrl)) {
|
||||||
|
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tid = $this->getTenantId();
|
||||||
|
|
||||||
|
if (empty($tid)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '无法识别租户信息',
|
||||||
|
'list' => [],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询该租户下的 Banner
|
||||||
|
$banners = Db::name('mete_apps_cms_banner')
|
||||||
|
->where('tid', $tid)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->order('id', 'desc')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 处理图片路径
|
||||||
|
foreach ($banners as &$banner) {
|
||||||
|
if (!empty($banner['image'])) {
|
||||||
|
// 如果图片路径已经是完整 URL,直接返回
|
||||||
|
if (!preg_match('/^https?:\/\//', $banner['image'])) {
|
||||||
|
// 拼接完整 URL
|
||||||
|
$banner['image'] = $this->request->scheme() . '://' . $this->request->host() .
|
||||||
|
(strpos($banner['image'], '/') === 0 ? '' : '/') . $banner['image'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'list' => $banners,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,409 @@ namespace app\index\controller;
|
|||||||
|
|
||||||
use app\model\Banner;
|
use app\model\Banner;
|
||||||
use app\index\BaseController;
|
use app\index\BaseController;
|
||||||
use app\model\FrontMenu;
|
use app\model\Cms\FrontMenu;
|
||||||
use app\model\OnePage;
|
use app\model\Cms\OnePage;
|
||||||
|
use app\model\System\SystemSiteSetting;
|
||||||
|
use app\service\ThemeService;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
|
use think\facade\Env;
|
||||||
|
use think\facade\Request;
|
||||||
|
use app\model\Cms\TemplateSiteConfig;
|
||||||
|
use app\model\Cms\Friendlink;
|
||||||
|
use app\model\Cms\Services;
|
||||||
|
use app\model\Cms\Products;
|
||||||
|
use app\model\Tenant\Tenant;
|
||||||
|
use app\model\Cms\Articles;
|
||||||
|
use app\model\Cms\ArticlesCategory;
|
||||||
|
|
||||||
class Index extends BaseController
|
class Index extends BaseController
|
||||||
{
|
{
|
||||||
|
private ThemeService $themeService;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->themeService = new ThemeService();
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return '您好!这是一个[index]示例应用';
|
// 获取请求对象
|
||||||
|
$request = $this->request ?? Request::instance();
|
||||||
|
|
||||||
|
// 优先从请求对象获取中间件设置的租户ID(通过域名解析)
|
||||||
|
$tid = $request->tenantId ?? 0;
|
||||||
|
|
||||||
|
// 兼容:从header获取
|
||||||
|
if ($tid == 0) {
|
||||||
|
$headerTid = $request->header('X-Tenant-Id');
|
||||||
|
$tid = $headerTid ? (int) $headerTid : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试:检查tid
|
||||||
|
if ($tid === 0) {
|
||||||
|
die('tenantId未获取到,请检查域名解析');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取租户选择的模板
|
||||||
|
$themeKey = 'default';
|
||||||
|
if ($tid > 0) {
|
||||||
|
// 不使用软删除过滤
|
||||||
|
$config = TemplateSiteConfig::where('tid', $tid)
|
||||||
|
->where('key', 'current_theme')
|
||||||
|
->withoutField('delete_time')
|
||||||
|
->find();
|
||||||
|
$themeKey = $config['value'] ?? 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板路径:/themes/{theme_key}/,优先使用index.php,其次index.html
|
||||||
|
$themeBasePath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeKey;
|
||||||
|
$themeUrlPath = '/themes/' . $themeKey . '/';
|
||||||
|
|
||||||
|
if (is_file($themeBasePath . DIRECTORY_SEPARATOR . 'index.php')) {
|
||||||
|
// 渲染PHP模板(直接include)
|
||||||
|
return $this->renderPhpTemplate($themeBasePath . DIRECTORY_SEPARATOR . 'index.php', $themeUrlPath);
|
||||||
|
} elseif (is_file($themeBasePath . DIRECTORY_SEPARATOR . 'index.html')) {
|
||||||
|
// 读取HTML模板内容
|
||||||
|
$content = file_get_contents($themeBasePath . DIRECTORY_SEPARATOR . 'index.html');
|
||||||
|
// 修复资源路径:将相对路径转换为绝对路径
|
||||||
|
$content = $this->fixTemplateAssets($content, $themeUrlPath);
|
||||||
|
return response($content, 200, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板不存在,返回默认
|
||||||
|
return view('index/index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用页面渲染
|
||||||
|
* 根据页面名称(如 about, blog, portfolio 等)渲染对应模板
|
||||||
|
* @param string $page 页面名称
|
||||||
|
* @return \think\response|\think\response\View
|
||||||
|
*/
|
||||||
|
public function page(string $page = 'index')
|
||||||
|
{
|
||||||
|
$request = $this->request ?? Request::instance();
|
||||||
|
|
||||||
|
// 获取租户ID
|
||||||
|
$tid = $request->tenantId ?? 0;
|
||||||
|
if ($tid == 0) {
|
||||||
|
$headerTid = $request->header('X-Tenant-Id');
|
||||||
|
$tid = $headerTid ? (int) $headerTid : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tid === 0) {
|
||||||
|
die('tenantId未获取到,请检查域名解析');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取租户选择的模板
|
||||||
|
$themeKey = 'default';
|
||||||
|
if ($tid > 0) {
|
||||||
|
$config = TemplateSiteConfig::where('tid', $tid)
|
||||||
|
->where('key', 'current_theme')
|
||||||
|
->withoutField('delete_time')
|
||||||
|
->find();
|
||||||
|
$themeKey = $config['value'] ?? 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板路径
|
||||||
|
$themeBasePath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeKey;
|
||||||
|
$themeUrlPath = '/themes/' . $themeKey . '/';
|
||||||
|
|
||||||
|
// 安全检查:只允许字母、数字、中划线
|
||||||
|
$page = preg_replace('/[^a-zA-Z0-9\-]/', '', $page);
|
||||||
|
if (empty($page)) {
|
||||||
|
$page = 'index';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 PHP 模板(优先)或 HTML 模板
|
||||||
|
$templateFile = $themeBasePath . DIRECTORY_SEPARATOR . $page . '.php';
|
||||||
|
$templateHtmlFile = $themeBasePath . DIRECTORY_SEPARATOR . $page . '.html';
|
||||||
|
|
||||||
|
if (is_file($templateFile)) {
|
||||||
|
return $this->renderPhpTemplate($templateFile, $themeUrlPath);
|
||||||
|
} elseif (is_file($templateHtmlFile)) {
|
||||||
|
$content = file_get_contents($templateHtmlFile);
|
||||||
|
$content = $this->fixTemplateAssets($content, $themeUrlPath);
|
||||||
|
return response($content, 200, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板不存在
|
||||||
|
return response('页面不存在', 404, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章详情页
|
||||||
|
* @param int $id 文章ID
|
||||||
|
* @return \think\response
|
||||||
|
*/
|
||||||
|
public function articleDetail(int $id = 0)
|
||||||
|
{
|
||||||
|
$request = $this->request ?? Request::instance();
|
||||||
|
|
||||||
|
// 获取租户ID
|
||||||
|
$tid = $request->tenantId ?? 0;
|
||||||
|
if ($tid == 0) {
|
||||||
|
$headerTid = $request->header('X-Tenant-Id');
|
||||||
|
$tid = $headerTid ? (int) $headerTid : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tid === 0) {
|
||||||
|
die('tenantId未获取到,请检查域名解析');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 与 NewsCenterController::getNewsDetail 一致:已发布 + 当前租户(网页直出,非 JSON)
|
||||||
|
$templateVars = $this->buildArticleDetailTemplateVars($id, $tid);
|
||||||
|
if ($templateVars === null) {
|
||||||
|
return response('文章不存在', 404, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取租户选择的模板
|
||||||
|
$themeKey = 'default';
|
||||||
|
if ($tid > 0) {
|
||||||
|
$config = TemplateSiteConfig::where('tid', $tid)
|
||||||
|
->where('key', 'current_theme')
|
||||||
|
->withoutField('delete_time')
|
||||||
|
->find();
|
||||||
|
$themeKey = $config['value'] ?? 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板路径
|
||||||
|
$themeBasePath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeKey;
|
||||||
|
$themeUrlPath = '/themes/' . $themeKey . '/';
|
||||||
|
|
||||||
|
// 查找文章详情模板
|
||||||
|
$templateFile = $themeBasePath . DIRECTORY_SEPARATOR . 'article_detail.php';
|
||||||
|
$templateHtmlFile = $themeBasePath . DIRECTORY_SEPARATOR . 'article_detail.html';
|
||||||
|
$blogDetailsFile = $themeBasePath . DIRECTORY_SEPARATOR . 'blog-details.php';
|
||||||
|
$blogDetailsHtmlFile = $themeBasePath . DIRECTORY_SEPARATOR . 'blog-details.html';
|
||||||
|
|
||||||
|
// 优先使用 article_detail 模板
|
||||||
|
if (is_file($templateFile)) {
|
||||||
|
return $this->renderPhpTemplate($templateFile, $themeUrlPath, $templateVars);
|
||||||
|
} elseif (is_file($templateHtmlFile)) {
|
||||||
|
$content = file_get_contents($templateHtmlFile);
|
||||||
|
$content = $this->fixTemplateAssets($content, $themeUrlPath);
|
||||||
|
return response($content, 200, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
} elseif (is_file($blogDetailsFile)) {
|
||||||
|
return $this->renderPhpTemplate($blogDetailsFile, $themeUrlPath, $templateVars);
|
||||||
|
} elseif (is_file($blogDetailsHtmlFile)) {
|
||||||
|
$content = file_get_contents($blogDetailsHtmlFile);
|
||||||
|
$content = $this->fixTemplateAssets($content, $themeUrlPath);
|
||||||
|
return response($content, 200, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response('文章不存在', 404, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装文章详情页模板变量(数据源与 getNewsDetail 一致,并限定租户 + 已发布)
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>|null
|
||||||
|
*/
|
||||||
|
private function buildArticleDetailTemplateVars(int $id, int $tid): ?array
|
||||||
|
{
|
||||||
|
$article = Articles::published()
|
||||||
|
->where('id', $id)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
if (!$article) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = $article->toArray();
|
||||||
|
|
||||||
|
$categoryName = '未分类';
|
||||||
|
if (!empty($row['cate'])) {
|
||||||
|
$cat = ArticlesCategory::where('id', $row['cate'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if ($cat) {
|
||||||
|
$categoryName = (string) $cat['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$coverPath = $row['image'] ?? '';
|
||||||
|
if ($coverPath === '' && !empty($row['cate'])) {
|
||||||
|
$category = ArticlesCategory::where('id', $row['cate'])
|
||||||
|
->where('delete_time', null)
|
||||||
|
->find();
|
||||||
|
if ($category && !empty($category['image'])) {
|
||||||
|
$coverPath = (string) $category['image'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiUrl = rtrim((string) (Env::get('app.api_url', '') ?: 'https://api.yunzer.cn'), '/');
|
||||||
|
$articleCoverUrl = $this->resolveArticleMediaUrl($coverPath, $apiUrl);
|
||||||
|
|
||||||
|
$descPlain = strip_tags((string) ($row['desc'] ?? ''));
|
||||||
|
$title = (string) ($row['title'] ?? '详情');
|
||||||
|
$descShort = $descPlain !== ''
|
||||||
|
? (function_exists('mb_substr') ? mb_substr($descPlain, 0, 160) : substr($descPlain, 0, 160))
|
||||||
|
: $title;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'article' => $row,
|
||||||
|
'articleCoverUrl' => $articleCoverUrl,
|
||||||
|
'articleCategoryName' => $categoryName,
|
||||||
|
'pageTitle' => $title . ' - 新闻详情',
|
||||||
|
'pageDescription' => $descShort,
|
||||||
|
'pageKeywords' => $title,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章封面等资源 URL(与列表页逻辑一致:相对路径拼 API 域名)
|
||||||
|
*/
|
||||||
|
private function resolveArticleMediaUrl(string $path, string $apiUrl): string
|
||||||
|
{
|
||||||
|
if ($path === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (strpos($path, 'http://') === 0 || strpos($path, 'https://') === 0) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
if (strpos($path, '/') === 0) {
|
||||||
|
return $apiUrl . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $apiUrl . '/' . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复模板中的资源路径
|
||||||
|
* 将相对路径 (assets/, css/, js/, images/) 转换为绝对路径 (/themes/xxx/)
|
||||||
|
*/
|
||||||
|
private function fixTemplateAssets(string $content, string $themeUrlPath): string
|
||||||
|
{
|
||||||
|
// 需要修复的资源目录
|
||||||
|
$assetsDirs = ['assets', 'css', 'js', 'images', 'img', 'fonts', 'plugins', 'libs'];
|
||||||
|
|
||||||
|
foreach ($assetsDirs as $dir) {
|
||||||
|
// 匹配 src="assets/..." 或 href="css/..." 等相对路径
|
||||||
|
// 不匹配已以 / 开头的绝对路径
|
||||||
|
$content = preg_replace(
|
||||||
|
'/(src|href)=["\'](' . $dir . '\/[^"\']*)["\']/',
|
||||||
|
'$1="' . $themeUrlPath . '$2"',
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
// 匹配 src='assets/...'
|
||||||
|
$content = preg_replace(
|
||||||
|
'/(src|href)=[\']([^\/][^\'\"]*\/[^\'\"]*)[\']/',
|
||||||
|
'$1="' . $themeUrlPath . '$2"',
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染PHP模板文件
|
||||||
|
*/
|
||||||
|
private function renderPhpTemplate(string $templateFile, string $themeUrlPath = '', array $templateVars = [])
|
||||||
|
{
|
||||||
|
// 定义模板基础URL常量,供模板使用
|
||||||
|
if (!defined('THEME_URL')) {
|
||||||
|
define('THEME_URL', $themeUrlPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
// 获取URL参数
|
||||||
|
$getParams = Request::get();
|
||||||
|
extract($getParams, EXTR_OVERWRITE);
|
||||||
|
extract($templateVars, EXTR_OVERWRITE);
|
||||||
|
include $templateFile;
|
||||||
|
$content = ob_get_clean();
|
||||||
|
|
||||||
|
// 修复PHP模板输出中的资源路径
|
||||||
|
$content = $this->fixTemplateAssets($content, $themeUrlPath);
|
||||||
|
|
||||||
|
return response($content, 200, ['Content-Type' => 'text/html; charset=utf-8']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端初始化接口 - 返回当前模板和填充数据
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
// 优先从请求对象获取中间件设置的租户ID(通过域名解析)
|
||||||
|
$tid = $this->request->tenantId ?? 0;
|
||||||
|
|
||||||
|
// 兼容:URL参数传递的tid作为备用
|
||||||
|
$tid = $tid > 0 ? $tid : Request::param('tid', 0, 'int');
|
||||||
|
|
||||||
|
// 从TemplateSiteConfig获取配置(根据租户ID)
|
||||||
|
$config = null;
|
||||||
|
if ($tid > 0) {
|
||||||
|
$config = TemplateSiteConfig::where('tid', $tid)
|
||||||
|
->where('key', 'current_theme')
|
||||||
|
->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
$themeKey = $config['value'] ?? 'default';
|
||||||
|
|
||||||
|
// 模板路径:/themes/{theme_key}/,优先使用index.php,其次index.html
|
||||||
|
$themeBasePath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeKey;
|
||||||
|
|
||||||
|
if (is_file($themeBasePath . DIRECTORY_SEPARATOR . 'index.php')) {
|
||||||
|
$themePath = '/themes/' . $themeKey . '/index.php';
|
||||||
|
} else {
|
||||||
|
$themePath = '/themes/' . $themeKey . '/index.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'theme_key' => $themeKey,
|
||||||
|
'theme_path' => $themePath
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志列表
|
||||||
|
*/
|
||||||
|
public function getLogs()
|
||||||
|
{
|
||||||
|
$logPath = Env::get('runtime_path') . 'log/';
|
||||||
|
$logs = [];
|
||||||
|
|
||||||
|
// 读取最近的日志文件
|
||||||
|
$files = glob($logPath . '*.log');
|
||||||
|
if ($files) {
|
||||||
|
// 按修改时间排序,最新的在前
|
||||||
|
usort($files, function ($a, $b) {
|
||||||
|
return filemtime($b) - filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 读取最新的日志文件
|
||||||
|
$latestFile = reset($files);
|
||||||
|
if (file_exists($latestFile)) {
|
||||||
|
$content = file_get_contents($latestFile);
|
||||||
|
$lines = explode("\n", $content);
|
||||||
|
|
||||||
|
// 倒序遍历,只取最近的100条
|
||||||
|
$count = 0;
|
||||||
|
for ($i = count($lines) - 1; $i >= 0 && $count < 100; $i--) {
|
||||||
|
if (!empty(trim($lines[$i]))) {
|
||||||
|
$logs[] = $lines[$i];
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再倒序回来,使最新的日志在最后
|
||||||
|
$logs = array_reverse($logs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => $logs
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,15 +488,15 @@ class Index extends BaseController
|
|||||||
$requestPath = $this->request->pathinfo();
|
$requestPath = $this->request->pathinfo();
|
||||||
$path = str_replace('onepage/', '', $requestPath);
|
$path = str_replace('onepage/', '', $requestPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保路径以 / 开头
|
// 确保路径以 / 开头
|
||||||
if (empty($path) || $path[0] !== '/') {
|
if (empty($path) || $path[0] !== '/') {
|
||||||
$path = '/' . $path;
|
$path = '/' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解码路径
|
// 解码路径
|
||||||
$path = urldecode($path);
|
$path = urldecode($path);
|
||||||
|
|
||||||
// 查找对应路径的单页
|
// 查找对应路径的单页
|
||||||
$onePage = OnePage::where('path', $path)
|
$onePage = OnePage::where('path', $path)
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
@@ -130,4 +524,86 @@ class Index extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取首页综合数据
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function getHomeData()
|
||||||
|
{
|
||||||
|
$baseUrl = Request::param('baseUrl', '');
|
||||||
|
|
||||||
|
if (empty($baseUrl)) {
|
||||||
|
return json(['code' => 400, 'msg' => '缺少 baseUrl 参数']);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 通过域名获取租户ID
|
||||||
|
$tid = BaseController::getTenantIdByDomain($baseUrl);
|
||||||
|
|
||||||
|
if (empty($tid)) {
|
||||||
|
return json([
|
||||||
|
'code' => 400,
|
||||||
|
'msg' => '无法识别租户信息',
|
||||||
|
'data' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取站点基础信息 (normalinfos)
|
||||||
|
$normalInfos = SystemSiteSetting::where('tid', $tid)
|
||||||
|
->field('sitename,logo,logow,ico,description,copyright,companyname,icp,companyintroduction')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 获取特色服务列表
|
||||||
|
$servicesList = Services::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->field('id,title,desc,thumb,url')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 获取企业产品列表
|
||||||
|
$productsList = Products::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->field('id,title,desc,content,thumb,url')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 获取友情链接列表
|
||||||
|
$friendlinkList = Friendlink::where('delete_time', null)
|
||||||
|
->where('tid', $tid)
|
||||||
|
->where('status', 1)
|
||||||
|
->order('sort', 'asc')
|
||||||
|
->field('id,link_name,link_url,link_logo')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// 获取联系方式
|
||||||
|
$contact = Tenant::where('id', $tid)
|
||||||
|
->where('status', 1)
|
||||||
|
->where('delete_time', null)
|
||||||
|
->field('contact_phone,contact_email,address,worktime')
|
||||||
|
->find();
|
||||||
|
|
||||||
|
// 合并返回
|
||||||
|
return json([
|
||||||
|
'code' => 200,
|
||||||
|
'msg' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'normal' => $normalInfos ?: (object) [],
|
||||||
|
'contact' => $contact ?: (object) [],
|
||||||
|
'services' => $servicesList,
|
||||||
|
'products' => $productsList,
|
||||||
|
'links' => $friendlinkList
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return json([
|
||||||
|
'code' => 500,
|
||||||
|
'msg' => '服务器错误:' . $e->getMessage(),
|
||||||
|
'data' => null
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,434 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace app\index\controller;
|
|
||||||
|
|
||||||
use app\index\BaseController;
|
|
||||||
use Symfony\Component\VarDumper\VarDumper;
|
|
||||||
use think\exception\ValidateException;
|
|
||||||
use think\facade\Request;
|
|
||||||
use think\facade\Session;
|
|
||||||
use think\response\Json;
|
|
||||||
use think\db\exception\DbException;
|
|
||||||
|
|
||||||
use app\model\Articles;
|
|
||||||
use app\model\ArticlesCategory;
|
|
||||||
|
|
||||||
|
|
||||||
class NewsCenterController extends BaseController
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 根据分类获取文章
|
|
||||||
* @param string $category 分类名称
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function getNewsByCategory(string $category): Json
|
|
||||||
{
|
|
||||||
// 查询分类
|
|
||||||
$categoryInfo = ArticlesCategory::where('name', $category)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$categoryInfo) {
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => [],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询文章
|
|
||||||
$articles = Articles::published()
|
|
||||||
->where('cate', $categoryInfo['id'])
|
|
||||||
->order('publish_date', 'desc')
|
|
||||||
->limit(4)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => $articles,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取企业新闻
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function getCompanyNews(): Json
|
|
||||||
{
|
|
||||||
// 获取分页参数
|
|
||||||
$page = Request::param('page', 1);
|
|
||||||
$limit = Request::param('limit', 10);
|
|
||||||
$page = max(1, intval($page));
|
|
||||||
$limit = max(1, min(50, intval($limit))); // 限制每页最多50条
|
|
||||||
|
|
||||||
// 查询分类
|
|
||||||
$categoryInfo = ArticlesCategory::where('name', '企业新闻')
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$categoryInfo) {
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => [],
|
|
||||||
'total' => 0,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询总数
|
|
||||||
$total = Articles::where('cate', $categoryInfo['id'])
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// 查询文章
|
|
||||||
$articles = Articles::where('cate', $categoryInfo['id'])
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->order('top', 'desc')
|
|
||||||
->order('recommend', 'desc')
|
|
||||||
->order('sort', 'desc')
|
|
||||||
->order('publish_date', 'desc')
|
|
||||||
->page($page, $limit)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => $articles,
|
|
||||||
'total' => $total,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取金蝶新闻
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function getKingdeeNews(): Json
|
|
||||||
{
|
|
||||||
// 获取分页参数
|
|
||||||
$page = Request::param('page', 1);
|
|
||||||
$limit = Request::param('limit', 10);
|
|
||||||
$page = max(1, intval($page));
|
|
||||||
$limit = max(1, min(50, intval($limit))); // 限制每页最多50条
|
|
||||||
|
|
||||||
// 查询分类
|
|
||||||
$categoryInfo = ArticlesCategory::where('name', '金蝶新闻')
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$categoryInfo) {
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => [],
|
|
||||||
'total' => 0,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询总数
|
|
||||||
$total = Articles::where('cate', $categoryInfo['id'])
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// 查询文章
|
|
||||||
$articles = Articles::where('cate', $categoryInfo['id'])
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->order('top', 'desc')
|
|
||||||
->order('recommend', 'desc')
|
|
||||||
->order('sort', 'desc')
|
|
||||||
->order('publish_date', 'desc')
|
|
||||||
->page($page, $limit)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => $articles,
|
|
||||||
'total' => $total,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取技术中心子分类
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function getTechnologyCategories(): Json
|
|
||||||
{
|
|
||||||
// 获取"技术中心"主分类
|
|
||||||
$parentCategory = ArticlesCategory::where('name', '技术中心')
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$parentCategory) {
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'data' => []
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找所有子分类
|
|
||||||
$subCategories = ArticlesCategory::where('cid', $parentCategory['id'])
|
|
||||||
->where('delete_time', null)
|
|
||||||
->field('id,name,desc,sort,image')
|
|
||||||
->order('sort', 'desc')
|
|
||||||
->select();
|
|
||||||
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'data' => $subCategories
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取技术中心
|
|
||||||
* @return Json
|
|
||||||
*/
|
|
||||||
public function getTechnologyCenter(): Json
|
|
||||||
{
|
|
||||||
// 1. 分页参数规范化
|
|
||||||
$page = max(1, intval(Request::param('page', 1)));
|
|
||||||
$limit = max(1, min(50, intval(Request::param('limit', 10))));
|
|
||||||
|
|
||||||
// 获取分类ID参数(可选)
|
|
||||||
$categoryId = Request::param('category_id', null);
|
|
||||||
|
|
||||||
// 2. 第一步:获取“技术中心”主分类的 id
|
|
||||||
$parentCategory = ArticlesCategory::where('name', '技术中心')
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
// print_r($parentCategory['id']);
|
|
||||||
|
|
||||||
if (!$parentCategory) {
|
|
||||||
return $this->emptyResponse($page, $limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 第二步:查找 cid 等于主分类 id 的所有子分类 id
|
|
||||||
$subCategoryQuery = ArticlesCategory::where('cid', $parentCategory['id'])
|
|
||||||
->where('delete_time', null);
|
|
||||||
|
|
||||||
// print_r($subCategoryQuery->select());
|
|
||||||
|
|
||||||
// 如果指定了分类ID,则只查询该分类
|
|
||||||
if ($categoryId) {
|
|
||||||
$subCategoryQuery->where('id', $categoryId);
|
|
||||||
}
|
|
||||||
|
|
||||||
$subCategoryIds = $subCategoryQuery->column('id');
|
|
||||||
|
|
||||||
// print_r($subCategoryIds);
|
|
||||||
|
|
||||||
if (empty($subCategoryIds)) {
|
|
||||||
return $this->emptyResponse($page, $limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 第三步:查询 Articles 表,并限定字段
|
|
||||||
$articleQuery = Articles::whereIn('cate', $subCategoryIds)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2);
|
|
||||||
|
|
||||||
// 获取总数
|
|
||||||
$total = (clone $articleQuery)->count();
|
|
||||||
|
|
||||||
// 获取列表:限定返回 id, title, desc, publish_date, image, likes, views
|
|
||||||
$articles = $articleQuery->field('id,title,desc,publish_date,image,likes,views,cate')
|
|
||||||
->order([
|
|
||||||
'top' => 'desc',
|
|
||||||
'recommend' => 'desc',
|
|
||||||
'sort' => 'desc',
|
|
||||||
'publish_date' => 'desc'
|
|
||||||
])
|
|
||||||
->page($page, $limit)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
// 如果文章没有image,查询对应分类的image
|
|
||||||
$categoryImages = ArticlesCategory::whereIn('id', $subCategoryIds)->column('image', 'id');
|
|
||||||
|
|
||||||
foreach ($articles as &$article) {
|
|
||||||
if (empty($article['image']) && isset($categoryImages[$article['cate']])) {
|
|
||||||
$article['image'] = $categoryImages[$article['cate']];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => $articles,
|
|
||||||
'total' => $total,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 统一空返回
|
|
||||||
*/
|
|
||||||
private function emptyResponse($page, $limit): Json
|
|
||||||
{
|
|
||||||
return json([
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => [],
|
|
||||||
'total' => 0,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取金蝶新闻详情
|
|
||||||
*/
|
|
||||||
public function getKingdeeNewsDetail(int $id): Json
|
|
||||||
{
|
|
||||||
$article = Articles::where('id', $id)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->field('id,title,cate,image,desc,author,content,publisher,publish_date,views,likes,is_trans,transurl')
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$article) {
|
|
||||||
return json(['code' => 404, 'msg' => '文章不存在', 'data' => null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cate = (int) $article['cate'];
|
|
||||||
|
|
||||||
// 转换为数组再处理
|
|
||||||
$articleData = $article->toArray();
|
|
||||||
// $articleData['catename'] = $this->getCategoryName($cate);
|
|
||||||
|
|
||||||
// 获取相关文章
|
|
||||||
$articleData['relatedArticles'] = $this->getRelatedArticles($id, $cate);
|
|
||||||
|
|
||||||
// 获取上一篇下一篇
|
|
||||||
$articleData['nextPreviousArticles'] = $this->getNextPreviousArticles($id, $cate);
|
|
||||||
|
|
||||||
// 增加浏览量
|
|
||||||
Articles::where('id', $id)->inc('views')->update();
|
|
||||||
|
|
||||||
return json(['code' => 200, 'msg' => 'success', 'data' => $articleData]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取企业新闻详情
|
|
||||||
*/
|
|
||||||
public function getCompanyNewsDetail(int $id): Json
|
|
||||||
{
|
|
||||||
$article = Articles::where('id', $id)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$article) {
|
|
||||||
return json(['code' => 404, 'msg' => '文章不存在', 'data' => null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cate = (int) $article['cate'];
|
|
||||||
|
|
||||||
// 转换为数组再处理
|
|
||||||
$articleData = $article->toArray();
|
|
||||||
$articleData['catename'] = $this->getCategoryName($cate);
|
|
||||||
|
|
||||||
// 获取相关文章
|
|
||||||
$articleData['relatedArticles'] = $this->getRelatedArticles($id, $cate);
|
|
||||||
|
|
||||||
// 获取上一篇下一篇
|
|
||||||
$articleData['nextPreviousArticles'] = $this->getNextPreviousArticles($id, $cate);
|
|
||||||
|
|
||||||
// 增加浏览量
|
|
||||||
Articles::where('id', $id)->inc('views')->update();
|
|
||||||
|
|
||||||
return json(['code' => 200, 'msg' => 'success', 'data' => $articleData]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取上一篇下一篇
|
|
||||||
* @param int $id 文章ID
|
|
||||||
* @param int $cate 分类ID
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getNextPreviousArticles(int $id, int $cate): array
|
|
||||||
{
|
|
||||||
$nextArticle = Articles::where('id', '<', $id)
|
|
||||||
->where('cate', $cate)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->field('id,title')
|
|
||||||
->find();
|
|
||||||
|
|
||||||
$previousArticle = Articles::where('id', '>', $id)
|
|
||||||
->where('cate', $cate)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->field('id,title')
|
|
||||||
->find();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'next' => $nextArticle,
|
|
||||||
'previous' => $previousArticle,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过分类 ID 获取分类名称
|
|
||||||
* @param int $cateId 分类ID
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function getCategoryName(int $id): string
|
|
||||||
{
|
|
||||||
$categoryInfo = ArticlesCategory::where('id', $id)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->find();
|
|
||||||
|
|
||||||
if (!$categoryInfo) {
|
|
||||||
return '未分类';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $categoryInfo['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取相关文章
|
|
||||||
*/
|
|
||||||
private function getRelatedArticles(int $id, int $cate): array
|
|
||||||
{
|
|
||||||
$articles = Articles::where('id', '<>', $id)
|
|
||||||
->where('cate', $cate)
|
|
||||||
->where('delete_time', null)
|
|
||||||
->where('status', 2)
|
|
||||||
->order('top', 'desc')
|
|
||||||
->order('recommend', 'desc')
|
|
||||||
->order('sort', 'desc')
|
|
||||||
->order('id', 'desc')
|
|
||||||
->limit(5)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
foreach ($articles as &$article) {
|
|
||||||
$article['cate'] = $this->getCategoryName($article['cate']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'code' => 200,
|
|
||||||
'msg' => 'success',
|
|
||||||
'list' => $articles,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
// 全局中间件定义文件
|
|
||||||
return [
|
return [
|
||||||
// 全局跨域中间件
|
\app\common\middleware\AllowCrossDomain::class,
|
||||||
\think\middleware\AllowCrossDomain::class,
|
\app\common\middleware\DomainParse::class,
|
||||||
// 全局请求缓存
|
|
||||||
// \think\middleware\CheckRequestCache::class,
|
|
||||||
// 多语言加载
|
|
||||||
// \think\middleware\LoadLangPack::class,
|
|
||||||
// Session初始化
|
|
||||||
\think\middleware\SessionInit::class,
|
\think\middleware\SessionInit::class,
|
||||||
];
|
];
|
||||||
+25
-14
@@ -5,23 +5,34 @@ use think\facade\Route;
|
|||||||
Route::get('/', 'app\index\controller\Index@index');
|
Route::get('/', 'app\index\controller\Index@index');
|
||||||
Route::get('index/index', 'app\index\controller\Index@index');
|
Route::get('index/index', 'app\index\controller\Index@index');
|
||||||
|
|
||||||
// --- 文章详情路由 ---
|
// --- 模板通用页面路由 ---
|
||||||
Route::get('kingdeenews/detail/:id', 'app\index\controller\NewsCenterController@getKingdeeNewsDetail');
|
Route::get('article_detail/:id', 'app\index\controller\Index@articleDetail');
|
||||||
Route::get('companynews/detail/:id', 'app\index\controller\NewsCenterController@getCompanyNewsDetail');
|
Route::get(':page', 'app\index\controller\Index@page')
|
||||||
|
->pattern(['page' => 'about|blog|blog-details|contact|portfolio|portfolio-details|service-details|services|team|articles']);
|
||||||
|
|
||||||
// --- 文章列表路由 ---
|
// --- 模板初始化接口 ---
|
||||||
Route::get('kingdeenews$', 'app\index\controller\NewsCenterController@getKingdeeNews');
|
Route::get('init', 'app\index\controller\Index@init');
|
||||||
Route::get('companynews$', 'app\index\controller\NewsCenterController@getCompanyNews');
|
|
||||||
Route::get('technologyCenter$', 'app\index\controller\NewsCenterController@getTechnologyCenter');
|
|
||||||
Route::get('technologyCategories$', 'app\index\controller\NewsCenterController@getTechnologyCategories');
|
|
||||||
Route::get('newscentertop4', 'app\index\controller\Article\ArticleController@getNewsCenterTop4');
|
|
||||||
Route::get('newsbycategory/:category', 'app\index\controller\NewsCenterController@getNewsByCategory');
|
|
||||||
|
|
||||||
// --- 文章互动路由 ---
|
// --- Banner 路由 ---
|
||||||
|
Route::get('getBanners', 'app\index\controller\BannerController@getBanners');
|
||||||
|
|
||||||
|
// --- 前端其他数据路由 ---
|
||||||
|
Route::get('footerdata', 'app\index\controller\Index@getFooterData');
|
||||||
|
Route::get('companyInfos', 'app\index\controller\Index@getCompanyInfos');
|
||||||
|
Route::post('requirement', 'app\index\controller\Index@requirement');
|
||||||
|
Route::get('homeData', 'app\index\controller\Index@getHomeData');
|
||||||
|
|
||||||
|
// --- 新闻中心列表路由 ---
|
||||||
|
Route::get('getCenterNews', 'app\index\controller\Article\NewsCenterController@getCenterNews');
|
||||||
|
Route::get('getNewsDetail/:id', 'app\index\controller\Article\NewsCenterController@getNewsDetail');
|
||||||
|
|
||||||
|
|
||||||
|
// --- 文章分类路由 ---
|
||||||
|
Route::get('getArticleCategories', 'app\index\controller\Article\ArticleController@getArticleCategories');
|
||||||
|
|
||||||
|
// --- 新闻中心互动路由 ---
|
||||||
Route::post('articleViews/:id', 'app\index\controller\Article\ArticleController@articleViews');
|
Route::post('articleViews/:id', 'app\index\controller\Article\ArticleController@articleViews');
|
||||||
Route::post('articleLikes/:id', 'app\index\controller\Article\ArticleController@articleLikes');
|
Route::post('articleLikes/:id', 'app\index\controller\Article\ArticleController@articleLikes');
|
||||||
Route::post('articleUnlikes/:id', 'app\index\controller\Article\ArticleController@articleUnlikes');
|
Route::post('articleUnlikes/:id', 'app\index\controller\Article\ArticleController@articleUnlikes');
|
||||||
|
|
||||||
// --- 前端导航与单页路由 ---
|
|
||||||
Route::get('headmenu', 'app\index\controller\Index@getHeadMenu');
|
|
||||||
Route::rule('onepage/:path', 'app\index\controller\Index@getOnePageByPath', 'GET')->pattern(['path' => '.*']);
|
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>后端运行状态</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#log-content {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 1200px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
#log-content div {
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
#log-content div:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
#log-content p {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.refresh-info {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>后端服务运行状态</h1>
|
||||||
|
<p>实时监控系统运行情况</p>
|
||||||
|
<div id="log-content">
|
||||||
|
<p>正在加载日志...</p>
|
||||||
|
</div>
|
||||||
|
<div class="refresh-info">
|
||||||
|
<span id="last-refresh">最后刷新: 从未</span>
|
||||||
|
<span> | </span>
|
||||||
|
<span>每5秒自动刷新</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 加载日志
|
||||||
|
function loadLogs() {
|
||||||
|
fetch('/getLogs')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const logContent = document.getElementById('log-content');
|
||||||
|
if (data.code === 200) {
|
||||||
|
logContent.innerHTML = '';
|
||||||
|
if (data.data && data.data.length > 0) {
|
||||||
|
data.data.forEach(log => {
|
||||||
|
const logItem = document.createElement('div');
|
||||||
|
logItem.textContent = log;
|
||||||
|
logContent.appendChild(logItem);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logContent.innerHTML = '<p>暂无日志记录</p>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logContent.innerHTML = '<p>加载日志失败: ' + (data.msg || '未知错误') + '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新最后刷新时间
|
||||||
|
const now = new Date();
|
||||||
|
const timeStr = now.toLocaleString('zh-CN');
|
||||||
|
document.getElementById('last-refresh').textContent = '最后刷新: ' + timeStr;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('加载日志失败:', error);
|
||||||
|
const logContent = document.getElementById('log-content');
|
||||||
|
logContent.innerHTML = '<p>加载日志失败: 网络错误</p>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始加载日志
|
||||||
|
loadLogs();
|
||||||
|
|
||||||
|
// 定时刷新日志,每5秒一次
|
||||||
|
setInterval(loadLogs, 5000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -11,15 +11,17 @@ class AdminModules extends Model
|
|||||||
{
|
{
|
||||||
use SoftDelete;
|
use SoftDelete;
|
||||||
|
|
||||||
protected $name = 'admin_modules';
|
protected $name = 'mete_admin_modules';
|
||||||
|
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'mid' => 'integer',
|
||||||
'name' => 'string',
|
'name' => 'string',
|
||||||
'code' => 'string',
|
'code' => 'string',
|
||||||
'path' => 'string',
|
'path' => 'string',
|
||||||
'icon' => 'string',
|
'icon' => 'string',
|
||||||
'description' => 'string',
|
'description' => 'string',
|
||||||
|
'type' => 'integer',
|
||||||
'sort' => 'integer',
|
'sort' => 'integer',
|
||||||
'status' => 'integer',
|
'status' => 'integer',
|
||||||
'is_show' => 'integer',
|
'is_show' => 'integer',
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章分类模型
|
||||||
|
*/
|
||||||
|
class AppsBabyhealthBabys extends Model
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
protected $name = 'mete_apps_babyhealth_babys';
|
||||||
|
|
||||||
|
// 字段类型转换
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'name' => 'string',
|
||||||
|
'nickname' => 'string',
|
||||||
|
'sex' => 'integer',
|
||||||
|
'birth' => 'date',
|
||||||
|
'father' => 'integer',
|
||||||
|
'mother' => 'integer',
|
||||||
|
'status' => 'integer',
|
||||||
|
'height' => 'double',
|
||||||
|
'weight' => 'double',
|
||||||
|
'avatar' => 'string',
|
||||||
|
'status' => 'integer',
|
||||||
|
'create_time' => 'datetime',
|
||||||
|
'update_time' => 'datetime',
|
||||||
|
'delete_time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章分类模型
|
||||||
|
*/
|
||||||
|
class AppsBabyhealthUsers extends Model
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
protected $name = 'mete_apps_babyhealth_users';
|
||||||
|
|
||||||
|
// 字段类型转换
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'account' => 'string',
|
||||||
|
'password' => 'string',
|
||||||
|
'phone' => 'string',
|
||||||
|
'email' => 'string',
|
||||||
|
'name' => 'string',
|
||||||
|
'sex' => 'integer',
|
||||||
|
'birth' => 'date',
|
||||||
|
'avatar' => 'string',
|
||||||
|
'status' => 'integer',
|
||||||
|
'create_time' => 'datetime',
|
||||||
|
'update_time' => 'datetime',
|
||||||
|
'delete_time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -36,6 +36,7 @@ class Articles extends Model
|
|||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
'cate' => 'integer',
|
'cate' => 'integer',
|
||||||
'sort' => 'integer',
|
'sort' => 'integer',
|
||||||
'status' => 'integer',
|
'status' => 'integer',
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -36,6 +36,11 @@ class ArticlesCategory extends Model
|
|||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'cid' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
|
'name' => 'string',
|
||||||
|
'image' => 'string',
|
||||||
|
'desc' => 'string',
|
||||||
'sort' => 'integer',
|
'sort' => 'integer',
|
||||||
'status' => 'integer',
|
'status' => 'integer',
|
||||||
'create_time' => 'datetime',
|
'create_time' => 'datetime',
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -23,11 +23,12 @@ class Banner extends Model
|
|||||||
use SoftDelete;
|
use SoftDelete;
|
||||||
|
|
||||||
// 数据库表名
|
// 数据库表名
|
||||||
protected $name = 'mete_banner';
|
protected $name = 'mete_apps_cms_banner';
|
||||||
|
|
||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
'desc' => 'string',
|
'desc' => 'string',
|
||||||
'url' => 'string',
|
'url' => 'string',
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\model\Cms;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章分类模型
|
||||||
|
*/
|
||||||
|
class Demand extends Model
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
protected $name = 'mete_apps_cms_demand';
|
||||||
|
|
||||||
|
// 字段类型转换
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
|
'title' => 'string',
|
||||||
|
'desc' => 'string',
|
||||||
|
'applicant' => 'string',
|
||||||
|
'phone' => 'string',
|
||||||
|
'status' => 'integer',
|
||||||
|
'create_time' => 'datetime',
|
||||||
|
'update_time' => 'datetime',
|
||||||
|
'delete_time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -17,22 +17,22 @@ use think\model\concern\SoftDelete;
|
|||||||
/**
|
/**
|
||||||
* 文章分类模型
|
* 文章分类模型
|
||||||
*/
|
*/
|
||||||
class AdminUser extends Model
|
class DemandCategory extends Model
|
||||||
{
|
{
|
||||||
// 启用软删除
|
// 启用软删除
|
||||||
use SoftDelete;
|
use SoftDelete;
|
||||||
|
|
||||||
// 数据库表名
|
// 数据库表名
|
||||||
protected $name = 'mete_admin_user';
|
protected $name = 'mete_demand_category';
|
||||||
|
|
||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
'sex' => 'integer',
|
'title' => 'string',
|
||||||
'group_id' => 'integer',
|
'desc' => 'string',
|
||||||
'login_count' => 'integer',
|
'applicant' => 'string',
|
||||||
|
'phone' => 'string',
|
||||||
'status' => 'integer',
|
'status' => 'integer',
|
||||||
'api_key_status' => 'integer',
|
|
||||||
'create_time' => 'datetime',
|
'create_time' => 'datetime',
|
||||||
'update_time' => 'datetime',
|
'update_time' => 'datetime',
|
||||||
'delete_time' => 'datetime',
|
'delete_time' => 'datetime',
|
||||||
@@ -40,3 +40,4 @@ class AdminUser extends Model
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\model\Cms;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文章分类模型
|
||||||
|
*/
|
||||||
|
class Friendlink extends Model
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
protected $name = 'mete_apps_cms_friendlink';
|
||||||
|
|
||||||
|
// 字段类型转换
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
|
'link_name' => 'string',
|
||||||
|
'link_url' => 'string',
|
||||||
|
'link_logo' => 'string',
|
||||||
|
'description' => 'string',
|
||||||
|
'sort' => 'integer',
|
||||||
|
'status' => 'integer',
|
||||||
|
'create_time' => 'datetime',
|
||||||
|
'update_time' => 'datetime',
|
||||||
|
'delete_time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -23,16 +23,19 @@ class FrontMenu extends Model
|
|||||||
use SoftDelete;
|
use SoftDelete;
|
||||||
|
|
||||||
// 数据库表名
|
// 数据库表名
|
||||||
protected $name = 'mete_front_menu';
|
protected $name = 'mete_apps_cms_front_menu';
|
||||||
|
|
||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
'pid' => 'integer',
|
'pid' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
|
'image' => 'string',
|
||||||
'type' => 'integer',
|
'type' => 'integer',
|
||||||
'path' => 'string',
|
'path' => 'string',
|
||||||
'component_path' => 'string',
|
'component_path' => 'string',
|
||||||
|
'sort' => 'integer',
|
||||||
'desc' => 'string',
|
'desc' => 'string',
|
||||||
'create_time' => 'datetime',
|
'create_time' => 'datetime',
|
||||||
'update_time' => 'datetime',
|
'update_time' => 'datetime',
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: Liu21st <liu21st@gmail.com>
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
namespace app\model;
|
namespace app\model\Cms;
|
||||||
|
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\concern\SoftDelete;
|
use think\model\concern\SoftDelete;
|
||||||
@@ -23,11 +23,12 @@ class OnePage extends Model
|
|||||||
use SoftDelete;
|
use SoftDelete;
|
||||||
|
|
||||||
// 数据库表名
|
// 数据库表名
|
||||||
protected $name = 'mete_onepage';
|
protected $name = 'mete_apps_cms_onepage';
|
||||||
|
|
||||||
// 字段类型转换
|
// 字段类型转换
|
||||||
protected $type = [
|
protected $type = [
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
'content' => 'string',
|
'content' => 'string',
|
||||||
'path' => 'string',
|
'path' => 'string',
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: Liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace app\model\Cms;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特色服务模型
|
||||||
|
*/
|
||||||
|
class Products extends Model
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
|
||||||
|
// 数据库表名
|
||||||
|
protected $name = 'mete_apps_cms_products';
|
||||||
|
|
||||||
|
// 字段类型转换
|
||||||
|
protected $type = [
|
||||||
|
'id' => 'integer',
|
||||||
|
'tid' => 'integer',
|
||||||
|
'title' => 'string',
|
||||||
|
'desc' => 'string',
|
||||||
|
'content' => 'string',
|
||||||
|
'thumb' => 'string',
|
||||||
|
'url' => 'string',
|
||||||
|
'sort' => 'integer',
|
||||||
|
'create_time' => 'datetime',
|
||||||
|
'update_time' => 'datetime',
|
||||||
|
'delete_time' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user