no message

This commit is contained in:
hajimi
2026-06-11 12:15:29 +08:00
parent 10ebe39c30
commit 96efa1d905
5859 changed files with 815501 additions and 5 deletions
+117
View File
@@ -1,3 +1,120 @@
## Sport Era 服务器部署脚本
部署脚本位置:
- Windows 原生:`scripts/deploy-server.ps1`
- Bash 兼容版:`scripts/deploy-server.sh`
脚本通过 SSH 别名 `sbnews` 连接服务器,打包本地 `server` 代码并在服务器目录解压安装。Windows 下优先使用 `deploy-server.ps1`,不依赖 WSL。
### PowerShell 一次执行命令
在 Windows PowerShell 中执行:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net
```
如果 `sbnews` 配置在 `C:\Users\Administrator\.ssh\config` 中,默认会使用 Windows 的 `ssh.exe` 读取该配置。
### 全量发布
不传 commit id 即为全量发布:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net
```
全量模式默认只打包以下目录:
```text
server/app
server/config
server/extend
server/public/dongqiudi-crawler
server/route
```
默认会排除运行态或较大目录,例如 `.env``vendor``runtime``public/uploads``public/admin``public/mobile`、爬虫 `data/logs/venv`。如确实需要包含,可追加参数:
```bash
--include-env
--include-vendor
--include-runtime
--include-uploads
--include-public-builds
--include-crawler-data
```
### 增量发布
传入两个 commit id,脚本会对比差异,只打包 `--to` 版本中的变更文件,并在服务器删除两个 commit 之间被删除的文件:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From <old_commit> -To <new_commit> -RemoteDir /www/wwwroot/test-server.sbnews.net
```
示例:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From abc1234 -To def5678 -RemoteDir /www/wwwroot/test-server.sbnews.net
```
### 自动增量发布
如果只是发布最近一次提交的后端改动,可以使用 `--auto-incremental`,脚本会自动对比 `HEAD~1``HEAD`
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net
```
先演练不上传:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun
```
注意:自动增量只包含最近两个提交之间已经提交到 Git 的差异,不会包含工作区未提交文件。如有多次提交需要一起发布,请继续使用 `--from <old_commit> --to <new_commit>`
如果当前根目录 Git 只把 `server` 记录为 gitlink/submodule,且本机没有 `server/.git` 子仓库元数据,脚本无法拿到 `server` 内部的文件级差异;此时会自动降级为打包当前工作区默认的 5 个 server 目录,保证可以继续发布。
### 只演练不上传
先确认打包范围、包大小和增量删除清单:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun
```
脚本会在打包后打印 `update log`:增量模式包含 commit 范围、commit 摘要、变更文件和删除文件;全量模式包含当前最新 commit 和默认打包目录。
每条部署日志都会带耗时,例如 `[+0.123s][total 1.456s]``+` 表示距离上一条日志的耗时,`total` 表示本次脚本启动后的累计耗时。服务器解压安装阶段会额外打印 `[deploy][remote]` 日志,用来判断耗时是在本地、上传还是远端解压。
### 发布后执行命令
如果需要解压后在服务器项目目录执行命令,可使用 `--post-install`
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net -PostInstall "php think optimize:clear"
```
### 常见问题
1. `ssh: Could not resolve hostname sbnews`:检查 Windows 的 `C:\Users\Administrator\.ssh\config` 是否存在 `Host sbnews`,或直接用 `-HostName <服务器IP>`
2. PowerShell 禁止执行脚本:使用示例中的 `-ExecutionPolicy Bypass -File`,或以管理员身份调整当前用户执行策略。
3. `tar: Cannot utime``Cannot change mode`:远端目录权限不足,请加 `-Sudo`。脚本会使用 `sudo tar` 覆盖解压,并默认跳过还原 owner/permission,减少权限冲突。
4. 增量发布提示 commit 无效:确认 commit id 属于当前根目录 Git 可识别的历史。
5. `server is tracked as a root gitlink`:脚本检测到根 Git 只记录了 `server` 指针,无法做文件级增量,会自动改为打包当前工作区默认 5 个 server 目录。
6. 仍需使用 Bash 兼容版时,可继续运行 `bash ./scripts/deploy-server.sh ...`
<a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/fastbuildAI.png)</a><br>
<a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/likeshop.png)</a><br>
<a href="https://www.buildingai.cc">![BuildingAI](https://server.likeshop.cn/uploads/gitad/fastbuildAI.png)</a><br>
Submodule admin deleted from 44251a602e
+56
View File
@@ -0,0 +1,56 @@
CREATE TABLE IF NOT EXISTS `la_ai_chat_session` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` int unsigned NOT NULL DEFAULT 0 COMMENT '登录用户ID,匿名为0',
`client_id` varchar(80) NOT NULL DEFAULT '' COMMENT '匿名客户端ID',
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '会话标题',
`last_message` varchar(500) NOT NULL DEFAULT '' COMMENT '最后用户消息',
`last_answer` varchar(500) NOT NULL DEFAULT '' COMMENT '最后助手回复',
`message_count` int unsigned NOT NULL DEFAULT 0 COMMENT '消息数',
`last_active_time` int unsigned NOT NULL DEFAULT 0 COMMENT '最后活跃时间',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_user_active` (`user_id`, `last_active_time`),
KEY `idx_client_active` (`client_id`, `last_active_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI助手会话表';
CREATE TABLE IF NOT EXISTS `la_ai_chat_message` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`session_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '会话ID',
`user_id` int unsigned NOT NULL DEFAULT 0 COMMENT '登录用户ID',
`client_id` varchar(80) NOT NULL DEFAULT '' COMMENT '匿名客户端ID',
`role` varchar(20) NOT NULL DEFAULT 'user' COMMENT 'user/assistant',
`content` mediumtext NULL COMMENT '消息内容',
`sources_json` json NULL COMMENT '引用来源',
`model` varchar(100) NOT NULL DEFAULT '' COMMENT '模型',
`tokens_used` int unsigned NOT NULL DEFAULT 0 COMMENT 'token消耗',
`cost_ms` int unsigned NOT NULL DEFAULT 0 COMMENT '耗时毫秒',
`status` tinyint unsigned NOT NULL DEFAULT 1 COMMENT '1成功2失败',
`error_msg` varchar(500) NOT NULL DEFAULT '' COMMENT '错误信息',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_session_id` (`session_id`),
KEY `idx_user_time` (`user_id`, `create_time`),
KEY `idx_client_time` (`client_id`, `create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI助手消息表';
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'assistant_system_prompt', '你是世博头条 AI 助手,面向普通用户回答站内体育资讯、赛事、社区、彩票和加密行情相关问题。必须优先依据提供的站内资料和实时上下文回答;资料不足时要直接说明不足并建议用户换关键词。不要声称可以访问后台、源码、服务器或未提供的内部数据。回答使用中文,结构清晰,语气专业克制。涉及赛事预测、彩票或加密行情时,必须说明仅供参考,不构成投资或购彩建议。', '世博头条 AI 助手系统提示词', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'assistant_system_prompt');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'assistant_kb_topk', '6', 'AI助手知识库召回数量', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'assistant_kb_topk');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'assistant_history_limit', '8', 'AI助手发送给模型的历史消息数量', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'assistant_history_limit');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'assistant_rate_limit_per_minute', '10', 'AI助手单用户/客户端每分钟请求上限', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'assistant_rate_limit_per_minute');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'assistant_enable_crypto_realtime', '1', 'AI助手是否启用加密行情实时查询:1启用0关闭', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'assistant_enable_crypto_realtime');
+2 -2
View File
@@ -1,7 +1,7 @@
CREATE TABLE IF NOT EXISTS `la_ai_kb_document` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`domain` varchar(32) NOT NULL DEFAULT '' COMMENT 'article/post/lottery',
`subtype` varchar(32) NOT NULL DEFAULT '' COMMENT 'article/post/draw_result/ai_history',
`domain` varchar(32) NOT NULL DEFAULT '' COMMENT 'article/post/lottery/match',
`subtype` varchar(32) NOT NULL DEFAULT '' COMMENT 'article/post/draw_result/ai_history/event',
`source_id` bigint unsigned NOT NULL DEFAULT 0,
`title` varchar(255) NOT NULL DEFAULT '',
`summary` text NULL,
+34
View File
@@ -0,0 +1,34 @@
CREATE TABLE IF NOT EXISTS `la_private_chat_session` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_a_id` int unsigned NOT NULL DEFAULT 0 COMMENT '较小用户ID',
`user_b_id` int unsigned NOT NULL DEFAULT 0 COMMENT '较大用户ID',
`last_message_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '最后消息ID',
`last_message_type` varchar(20) NOT NULL DEFAULT 'text' COMMENT '最后消息类型 text/image',
`last_message_content` varchar(500) NOT NULL DEFAULT '' COMMENT '最后消息内容',
`last_sender_id` int unsigned NOT NULL DEFAULT 0 COMMENT '最后发送者',
`user_a_unread` int unsigned NOT NULL DEFAULT 0 COMMENT '用户A未读数',
`user_b_unread` int unsigned NOT NULL DEFAULT 0 COMMENT '用户B未读数',
`last_active_time` int unsigned NOT NULL DEFAULT 0 COMMENT '最后活跃时间',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_pair` (`user_a_id`, `user_b_id`),
KEY `idx_user_a_active` (`user_a_id`, `last_active_time`),
KEY `idx_user_b_active` (`user_b_id`, `last_active_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户私聊会话表';
CREATE TABLE IF NOT EXISTS `la_private_chat_message` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`session_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '会话ID',
`sender_id` int unsigned NOT NULL DEFAULT 0 COMMENT '发送者',
`receiver_id` int unsigned NOT NULL DEFAULT 0 COMMENT '接收者',
`message_type` varchar(20) NOT NULL DEFAULT 'text' COMMENT '消息类型 text/image',
`content` text NULL COMMENT '消息内容',
`read_time` int unsigned NOT NULL DEFAULT 0 COMMENT '接收者阅读时间',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_session_id` (`session_id`, `id`),
KEY `idx_receiver_read` (`receiver_id`, `read_time`),
KEY `idx_sender_time` (`sender_id`, `create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户私聊消息表';
+35
View File
@@ -0,0 +1,35 @@
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'qwen_api_key', '', 'DashScope Qwen API Key(留空时读取 server/.env 的 DASHSCOPE_API_KEY', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'qwen_api_key');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'qwen_base_url', 'https://dashscope.aliyuncs.com/compatible-mode', 'DashScope OpenAI-compatible Base URL(不带 /v1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'qwen_base_url');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'qwen_model', 'qwen3.7-plus', '默认文本生成模型', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'qwen_model');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'ai_request_timeout', '300', 'AI 模型请求超时时间(秒,30-300)', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'ai_request_timeout');
UPDATE `la_ai_config`
SET `value` = '300', `update_time` = UNIX_TIMESTAMP()
WHERE `name` = 'ai_request_timeout';
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'embedding_api_key', '', '知识库 Embedding API Key(留空时读取 server/.env 的 DASHSCOPE_API_KEY', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'embedding_api_key');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'embedding_base_url', 'https://dashscope.aliyuncs.com/compatible-mode', '知识库 Embedding API Base URL(不带 /v1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'embedding_base_url');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'embedding_model', 'text-embedding-v4', '知识库 Embedding 模型名', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'embedding_model');
INSERT INTO `la_ai_config` (`name`, `value`, `remark`, `create_time`, `update_time`)
SELECT 'embedding_dim', '1024', '知识库 Embedding 维度', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (SELECT 1 FROM `la_ai_config` WHERE `name` = 'embedding_dim');
+101
View File
@@ -0,0 +1,101 @@
"""
接口验证: 社区私聊 v1
路径:
- GET /api/chat/sessions
- POST /api/chat/open
- GET /api/chat/messages
- POST /api/chat/send
运行前请通过环境变量提供两个已登录用户 token:
PRIVATE_CHAT_TOKEN_A、PRIVATE_CHAT_TOKEN_B。
"""
import os
import requests
BASE_URL = os.getenv("BASE_URL", "http://127.0.0.1:8000")
TOKEN_A = os.getenv("PRIVATE_CHAT_TOKEN_A", "")
TOKEN_B = os.getenv("PRIVATE_CHAT_TOKEN_B", "")
TARGET_USER_ID = int(os.getenv("PRIVATE_CHAT_TARGET_USER_ID", "0"))
def assert_api_ok(resp):
assert resp.status_code == 200, resp.text
data = resp.json()
assert data["code"] == 1, data
return data["data"]
def require_env():
assert TOKEN_A, "请设置 PRIVATE_CHAT_TOKEN_A"
assert TOKEN_B, "请设置 PRIVATE_CHAT_TOKEN_B"
assert TARGET_USER_ID > 0, "请设置 PRIVATE_CHAT_TARGET_USER_ID"
def test_private_chat_flow():
require_env()
headers_a = {"token": TOKEN_A}
headers_b = {"token": TOKEN_B}
session = assert_api_ok(
requests.post(
f"{BASE_URL}/api/chat/open",
json={"target_user_id": TARGET_USER_ID},
headers=headers_a,
timeout=10,
)
)
assert session["target_user"]["id"] == TARGET_USER_ID
assert "is_mutual" in session["relationship"]
assert "relationship_text" in session["relationship"]
message = assert_api_ok(
requests.post(
f"{BASE_URL}/api/chat/send",
json={
"session_id": session["id"],
"message_type": "text",
"content": "私聊接口冒烟测试",
},
headers=headers_a,
timeout=10,
)
)
assert message["message_type"] == "text"
assert message["content"] == "私聊接口冒烟测试"
messages = assert_api_ok(
requests.get(
f"{BASE_URL}/api/chat/messages",
params={"session_id": session["id"], "after_id": 0},
headers=headers_b,
timeout=10,
)
)
assert any(item["id"] == message["id"] for item in messages["lists"])
image_message = assert_api_ok(
requests.post(
f"{BASE_URL}/api/chat/send",
json={
"session_id": session["id"],
"message_type": "image",
"content": "/uploads/private-chat-test.png",
},
headers=headers_a,
timeout=10,
)
)
assert image_message["message_type"] == "image"
sessions = assert_api_ok(
requests.get(f"{BASE_URL}/api/chat/sessions", headers=headers_a, timeout=10)
)
assert any(item["id"] == session["id"] for item in sessions["lists"])
if __name__ == "__main__":
test_private_chat_flow()
print("私聊接口冒烟通过")
+708
View File
@@ -0,0 +1,708 @@
[CmdletBinding()]
param(
[string]$SourceDir = "server",
[Parameter(Mandatory = $true)]
[string]$RemoteDir,
[string]$HostName = "sbnews",
[string]$SshBin = "ssh.exe",
[switch]$AutoIncremental,
[string]$From = "",
[string]$To = "",
[string]$RemoteTmp = "/tmp",
[string]$PostInstall = "",
[switch]$Sudo,
[switch]$KeepRemoteTemp,
[switch]$IncludeVendor,
[switch]$IncludeEnv,
[switch]$IncludeRuntime,
[switch]$IncludeUploads,
[switch]$IncludePublicBuilds,
[switch]$IncludeCrawlerData,
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
$Utf8NoBom = [System.Text.UTF8Encoding]::new($false)
[Console]::OutputEncoding = $Utf8NoBom
$OutputEncoding = $Utf8NoBom
$DeployWatch = [System.Diagnostics.Stopwatch]::StartNew()
$script:LastLogMs = 0.0
function Format-Duration {
param([Int64]$Milliseconds)
$span = [TimeSpan]::FromMilliseconds([Math]::Max(0, $Milliseconds))
if ($span.TotalMinutes -ge 1) {
return "{0}m{1:00}.{2:000}s" -f [Math]::Floor($span.TotalMinutes), $span.Seconds, $span.Milliseconds
}
return "{0}.{1:000}s" -f [Math]::Floor($span.TotalSeconds), $span.Milliseconds
}
function Write-DeployLog {
param([string]$Message)
$total = [Int64]$DeployWatch.ElapsedMilliseconds
$step = $total - $script:LastLogMs
$script:LastLogMs = $total
Write-Host ("[deploy][+{0}][total {1}] {2}" -f (Format-Duration $step), (Format-Duration $total), $Message)
}
function Fail {
param([string]$Message)
throw "[deploy][error] $Message"
}
function Require-Command {
param([string]$Name)
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
Fail "missing command: $Name"
}
}
function Normalize-DeployDir {
param([string]$Value)
return $Value.TrimEnd("/", "\")
}
function Normalize-ComparePath {
param([string]$Value)
return ([System.IO.Path]::GetFullPath($Value).TrimEnd("\", "/") -replace "\\", "/").ToLowerInvariant()
}
function ConvertTo-RemoteSingleQuoted {
param([string]$Value)
return "'" + $Value.Replace("'", "'\''") + "'"
}
function Invoke-Native {
param(
[Parameter(Mandatory = $true)]
[string]$FilePath,
[string[]]$Arguments = @()
)
& $FilePath @Arguments
if ($LASTEXITCODE -ne 0) {
Fail "command failed ($LASTEXITCODE): $FilePath $($Arguments -join ' ')"
}
}
function Invoke-NativeOutput {
param(
[Parameter(Mandatory = $true)]
[string]$FilePath,
[string[]]$Arguments = @()
)
$output = & $FilePath @Arguments
if ($LASTEXITCODE -ne 0) {
Fail "command failed ($LASTEXITCODE): $FilePath $($Arguments -join ' ')"
}
return $output
}
function ConvertTo-WindowsArgument {
param([string]$Value)
if ($null -eq $Value) {
return '""'
}
if ($Value -notmatch '[\s"]') {
return $Value
}
$result = '"'
$slashes = 0
foreach ($ch in $Value.ToCharArray()) {
if ($ch -eq '\') {
$slashes++
continue
}
if ($ch -eq '"') {
$result += ('\' * (($slashes * 2) + 1))
$result += '"'
$slashes = 0
continue
}
if ($slashes -gt 0) {
$result += ('\' * $slashes)
$slashes = 0
}
$result += $ch
}
if ($slashes -gt 0) {
$result += ('\' * ($slashes * 2))
}
$result += '"'
return $result
}
function Set-ProcessArguments {
param(
[System.Diagnostics.ProcessStartInfo]$ProcessStartInfo,
[string[]]$Arguments
)
$argumentListProperty = $ProcessStartInfo.GetType().GetProperty("ArgumentList")
$argumentList = $null
if ($null -ne $argumentListProperty) {
$argumentList = $argumentListProperty.GetValue($ProcessStartInfo, $null)
}
if ($null -ne $argumentList) {
foreach ($arg in $Arguments) {
[void]$argumentList.Add($arg)
}
return
}
$ProcessStartInfo.Arguments = (($Arguments | ForEach-Object { ConvertTo-WindowsArgument $_ }) -join " ")
}
function Start-ProcessWithInputFile {
param(
[string]$FilePath,
[string[]]$Arguments,
[string]$InputFile
)
$psi = [System.Diagnostics.ProcessStartInfo]::new()
$psi.FileName = $FilePath
$psi.UseShellExecute = $false
$psi.RedirectStandardInput = $true
Set-ProcessArguments -ProcessStartInfo $psi -Arguments $Arguments
$process = [System.Diagnostics.Process]::Start($psi)
try {
$fileStream = [System.IO.File]::OpenRead($InputFile)
try {
$fileStream.CopyTo($process.StandardInput.BaseStream)
} finally {
$fileStream.Dispose()
}
$process.StandardInput.Close()
$process.WaitForExit()
if ($process.ExitCode -ne 0) {
Fail "command failed ($($process.ExitCode)): $FilePath $($Arguments -join ' ')"
}
} finally {
$process.Dispose()
}
}
function Start-ProcessWithInputText {
param(
[string]$FilePath,
[string[]]$Arguments,
[string]$InputText
)
$psi = [System.Diagnostics.ProcessStartInfo]::new()
$psi.FileName = $FilePath
$psi.UseShellExecute = $false
$psi.RedirectStandardInput = $true
Set-ProcessArguments -ProcessStartInfo $psi -Arguments $Arguments
$process = [System.Diagnostics.Process]::Start($psi)
try {
$process.StandardInput.Write($InputText)
$process.StandardInput.Close()
$process.WaitForExit()
if ($process.ExitCode -ne 0) {
Fail "command failed ($($process.ExitCode)): $FilePath $($Arguments -join ' ')"
}
} finally {
$process.Dispose()
}
}
function Remove-IfExists {
param([string]$Path)
if (Test-Path -LiteralPath $Path) {
Remove-Item -LiteralPath $Path -Recurse -Force
}
}
function Copy-FullPayload {
Write-DeployLog "building full payload from current working tree: $SourceDir"
Write-DeployLog "full include paths: $($FullIncludePaths -join ' ')"
$payloadTar = Join-Path $WorkDir "payload-copy.tar"
$tarArgs = @(
"-cf", $payloadTar,
"-C", $SourceAbs,
"--exclude=.git",
"--exclude=.idea",
"--exclude=.vscode",
"--exclude=.tmp",
"--exclude=.gitignore",
"--exclude=*.log",
"--exclude=release-*.zip",
"--exclude=*.zip",
"--exclude=__pycache__",
"--exclude=*.pyc"
)
if (-not $IncludeEnv) {
$tarArgs += "--exclude=.env"
}
if (-not $IncludeVendor) {
$tarArgs += "--exclude=vendor"
}
if (-not $IncludeRuntime) {
$tarArgs += "--exclude=runtime"
}
if (-not $IncludeUploads) {
$tarArgs += "--exclude=public/uploads"
}
if (-not $IncludePublicBuilds) {
$tarArgs += @("--exclude=public/admin", "--exclude=public/mobile")
}
if (-not $IncludeCrawlerData) {
$tarArgs += @(
"--exclude=public/dongqiudi-crawler/data",
"--exclude=public/dongqiudi-crawler/logs",
"--exclude=public/dongqiudi-crawler/venv",
"--exclude=public/dongqiudi-crawler/__pycache__"
)
}
$tarArgs += $FullIncludePaths
Invoke-Native "tar" $tarArgs
Invoke-Native "tar" @("-xf", $payloadTar, "-C", $PayloadDir)
}
function Strip-SourcePrefix {
param([string]$Path)
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
return $Path
}
$prefix = "$GitPathPrefix/"
if ($Path.StartsWith($prefix)) {
return $Path.Substring($prefix.Length)
}
return $Path
}
function Test-DeployIncludedPath {
param([string]$RelativePath)
foreach ($include in $FullIncludePaths) {
if ($RelativePath -eq $include -or $RelativePath.StartsWith("$include/")) {
return $true
}
}
return $false
}
function Test-UnderSourceDir {
param([string]$GitPath)
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
return (Test-DeployIncludedPath $GitPath)
}
if (-not $GitPath.StartsWith("$GitPathPrefix/")) {
return $false
}
return (Test-DeployIncludedPath (Strip-SourcePrefix $GitPath))
}
function Get-ShortCommit {
param([string]$Commit)
try {
return (Invoke-NativeOutput "git" @("-C", $GitCwd, "rev-parse", "--short", $Commit) | Select-Object -First 1)
} catch {
return $Commit
}
}
function Write-FileListLog {
param(
[string]$Title,
[string]$Prefix,
[string[]]$Items
)
Write-DeployLog $Title
$list = @($Items | Where-Object { $_ } | Sort-Object -Unique)
if ($list.Count -eq 0) {
Write-Host " (none)"
return
}
foreach ($item in $list) {
Write-Host " $Prefix $item"
}
}
function Write-UpdateLog {
Write-DeployLog "update log:"
if ($Mode -eq "incremental") {
$fromShort = Get-ShortCommit $FromCommit
$toShort = Get-ShortCommit $ToCommit
Write-DeployLog "commit range: $fromShort -> $toShort"
$logArgs = @("-C", $GitCwd, "-c", "i18n.logOutputEncoding=utf-8", "log", "--encoding=UTF-8", "--no-merges", "--date=format:%Y-%m-%d %H:%M:%S", "--pretty=format: * %h %ad %an %s", "$FromCommit..$ToCommit")
if ($SourceIsGitLink) {
Write-DeployLog "$SourceDir is a root gitlink, showing root repository commits for the selected range"
} elseif (-not [string]::IsNullOrEmpty($GitPathPrefix)) {
$logArgs += @("--", $GitPathPrefix)
}
$commitLines = @(& git @logArgs)
Write-DeployLog "commits:"
if ($commitLines.Count -gt 0) {
$commitLines | ForEach-Object { Write-Host $_ }
} else {
Write-Host " (none)"
}
Write-FileListLog "changed files:" "+" $ChangedDisplayPaths
Write-FileListLog "deleted files:" "-" $DeletedDisplayPaths
} else {
Write-DeployLog "mode: full deploy from current working tree"
Write-DeployLog "full include paths: $($FullIncludePaths -join ' ')"
$commitLines = @(& git -C $GitCwd -c i18n.logOutputEncoding=utf-8 log -1 --encoding=UTF-8 "--date=format:%Y-%m-%d %H:%M:%S" "--pretty=format: * %h %ad %an %s")
Write-DeployLog "latest commit:"
if ($commitLines.Count -gt 0) {
$commitLines | ForEach-Object { Write-Host $_ }
} else {
Write-Host " (none)"
}
}
}
function Build-IncrementalPayload {
if ($SourceIsGitLink) {
Write-DeployLog "$SourceDir is tracked as a root gitlink; exact file-level diff is unavailable without $SourceDir/.git"
Write-DeployLog "building fallback payload from current working tree include paths: $($FullIncludePaths -join ' ')"
$script:ChangedDisplayPaths = @($FullIncludePaths)
Copy-FullPayload
return
}
$diffArgs = @("-C", $GitCwd, "diff", "--name-status", "--find-renames", $FromCommit, $ToCommit)
if (-not [string]::IsNullOrEmpty($GitPathPrefix)) {
$diffArgs += @("--", $GitPathPrefix)
}
$rawDiff = @(& git @diffArgs)
if ($LASTEXITCODE -ne 0) {
Fail "git diff failed"
}
$changedGitPaths = New-Object System.Collections.Generic.List[string]
$script:ChangedDisplayPaths = @()
$script:DeletedDisplayPaths = @()
foreach ($line in $rawDiff) {
if ([string]::IsNullOrWhiteSpace($line)) {
continue
}
$parts = $line -split "`t"
$status = $parts[0]
if ($status -eq "D") {
$path1 = $parts[1]
if (Test-UnderSourceDir $path1) {
$script:DeletedDisplayPaths += (Strip-SourcePrefix $path1)
}
} elseif ($status -like "R*" -or $status -like "C*") {
if ($parts.Count -lt 3) {
continue
}
$path1 = $parts[1]
$path2 = $parts[2]
if (Test-UnderSourceDir $path2) {
[void]$changedGitPaths.Add($path2)
$script:ChangedDisplayPaths += (Strip-SourcePrefix $path2)
if ($status -like "R*" -and (Test-UnderSourceDir $path1)) {
$script:DeletedDisplayPaths += (Strip-SourcePrefix $path1)
}
}
} else {
$path1 = $parts[1]
if (Test-UnderSourceDir $path1) {
[void]$changedGitPaths.Add($path1)
$script:ChangedDisplayPaths += (Strip-SourcePrefix $path1)
}
}
}
$script:ChangedDisplayPaths = @($script:ChangedDisplayPaths | Sort-Object -Unique)
$script:DeletedDisplayPaths = @($script:DeletedDisplayPaths | Sort-Object -Unique)
$changedGitPaths = @($changedGitPaths | Sort-Object -Unique)
if ($changedGitPaths.Count -eq 0 -and $script:DeletedDisplayPaths.Count -eq 0) {
Write-DeployLog "no changed files detected between $FromCommit and $ToCommit under $SourceDir"
$script:NoChanges = $true
return
}
if ($script:DeletedDisplayPaths.Count -gt 0) {
Set-Content -LiteralPath $DeletedPathsFile -Value $script:DeletedDisplayPaths -Encoding UTF8
}
if ($changedGitPaths.Count -gt 0) {
$incrementalTar = Join-Path $WorkDir "incremental.tar"
Write-DeployLog "building incremental payload from commit $ToCommit"
Invoke-Native "git" (@("-C", $GitCwd, "archive", "--format=tar", "--output=$incrementalTar", $ToCommit, "--") + $changedGitPaths)
Invoke-Native "tar" @("-xf", $incrementalTar, "-C", $ExtractDir)
if ($SourceIsGitRepo) {
$extractSource = $ExtractDir
} else {
$extractSource = Join-Path $ExtractDir $SourceDir
}
if (Test-Path -LiteralPath $extractSource) {
Get-ChildItem -LiteralPath $extractSource -Force | Copy-Item -Destination $PayloadDir -Recurse -Force
}
}
}
$SourceDir = Normalize-DeployDir $SourceDir
$RemoteDir = Normalize-DeployDir $RemoteDir
$RemoteTmp = Normalize-DeployDir $RemoteTmp
if ($AutoIncremental -and ($From -or $To)) {
Fail "-AutoIncremental cannot be used with -From/-To"
}
if ($AutoIncremental) {
$Mode = "incremental"
$FromCommit = "HEAD~1"
$ToCommit = "HEAD"
} elseif ($From -or $To) {
if (-not $From -or -not $To) {
Fail "incremental deploy requires both -From and -To"
}
$Mode = "incremental"
$FromCommit = $From
$ToCommit = $To
} else {
$Mode = "full"
$FromCommit = ""
$ToCommit = ""
}
Require-Command "git"
Require-Command "tar"
Require-Command $SshBin
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$RepoRoot = (Resolve-Path (Join-Path $ScriptDir "..")).Path
$SourceAbs = Join-Path $RepoRoot $SourceDir
if (-not (Test-Path -LiteralPath $SourceAbs -PathType Container)) {
Fail "source directory not found: $SourceDir"
}
$FullIncludePaths = @("app", "config", "extend", "public/dongqiudi-crawler", "route")
$GitCwd = $RepoRoot
$GitPathPrefix = $SourceDir
$SourceIsGitRepo = $false
$SourceIsGitLink = $false
$sourceGitTop = (& git -C $SourceAbs rev-parse --show-toplevel 2>$null | Select-Object -First 1)
if ($LASTEXITCODE -eq 0 -and $sourceGitTop -and (Normalize-ComparePath $sourceGitTop) -eq (Normalize-ComparePath $SourceAbs)) {
$GitCwd = $SourceAbs
$GitPathPrefix = ""
$SourceIsGitRepo = $true
} else {
& git -C $RepoRoot rev-parse --show-toplevel *> $null
if ($LASTEXITCODE -ne 0 -and $Mode -eq "incremental") {
Fail "incremental deploy requires git metadata in $SourceDir or repo root"
}
}
$lsFiles = @(& git -C $RepoRoot ls-files -s -- $SourceDir)
if (-not $SourceIsGitRepo -and ($lsFiles | Where-Object { $_ -match "^160000\s" })) {
$SourceIsGitLink = $true
}
if ($Mode -eq "incremental") {
& git -C $GitCwd rev-parse --verify "$FromCommit^{commit}" *> $null
if ($LASTEXITCODE -ne 0) {
Fail "invalid -From commit: $FromCommit"
}
& git -C $GitCwd rev-parse --verify "$ToCommit^{commit}" *> $null
if ($LASTEXITCODE -ne 0) {
Fail "invalid -To commit: $ToCommit"
}
$FromCommit = (Invoke-NativeOutput "git" @("-C", $GitCwd, "rev-parse", $FromCommit) | Select-Object -First 1)
$ToCommit = (Invoke-NativeOutput "git" @("-C", $GitCwd, "rev-parse", $ToCommit) | Select-Object -First 1)
}
$TempRoot = Join-Path ([System.IO.Path]::GetTempPath()) "sport-era-deploy"
New-Item -ItemType Directory -Force -Path $TempRoot | Out-Null
$WorkDir = Join-Path $TempRoot ("deploy-server-" + [System.Guid]::NewGuid().ToString("N"))
$PackageRoot = Join-Path $WorkDir "package"
$PayloadDir = Join-Path $PackageRoot "payload"
$ExtractDir = Join-Path $WorkDir "extract"
$ArchivePath = Join-Path $WorkDir ("{0}-{1}.tar.gz" -f ($SourceDir -replace "[\\/]", "-"), $Mode)
$DeletedPathsFile = Join-Path $PackageRoot ".deleted-paths.txt"
$DeployInfoFile = Join-Path $PackageRoot ".deploy-info.txt"
$script:ChangedDisplayPaths = @()
$script:DeletedDisplayPaths = @()
$script:NoChanges = $false
try {
New-Item -ItemType Directory -Force -Path $PayloadDir, $ExtractDir | Out-Null
New-Item -ItemType File -Force -Path $DeletedPathsFile | Out-Null
if ($Mode -eq "full") {
Copy-FullPayload
} else {
Build-IncrementalPayload
if ($script:NoChanges) {
return
}
}
Write-UpdateLog
$deployInfo = @(
"mode=$Mode",
"source_dir=$SourceDir",
"host=$HostName",
"remote_dir=$RemoteDir",
"built_at=$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
)
if ($Mode -eq "incremental") {
$deployInfo += @(
"auto_incremental=$([int]$AutoIncremental.IsPresent)",
"source_is_gitlink=$([int]$SourceIsGitLink)",
"from_commit=$FromCommit",
"to_commit=$ToCommit",
"changed_count=$($script:ChangedDisplayPaths.Count)",
"deleted_count=$($script:DeletedDisplayPaths.Count)"
)
}
Set-Content -LiteralPath $DeployInfoFile -Value $deployInfo -Encoding UTF8
Write-DeployLog "packing archive: $ArchivePath"
Invoke-Native "tar" @("-czf", $ArchivePath, "-C", $PackageRoot, ".")
$packageSizeKb = [Math]::Ceiling((Get-Item -LiteralPath $ArchivePath).Length / 1KB)
Write-DeployLog "package size: ${packageSizeKb}K"
if ($DryRun) {
Write-DeployLog "dry-run enabled, skip upload/install"
return
}
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$pidValue = $PID
$remoteWorkDir = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-deploy-$timestamp-$pidValue"
$remoteArchive = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-$Mode-$timestamp.tar.gz"
$remoteTmpQ = ConvertTo-RemoteSingleQuoted $RemoteTmp
$remoteArchiveQ = ConvertTo-RemoteSingleQuoted $remoteArchive
Write-DeployLog "uploading archive to ${HostName}:$remoteArchive"
$uploadCommand = "mkdir -p $remoteTmpQ && cat > $remoteArchiveQ"
Start-ProcessWithInputFile -FilePath $SshBin -Arguments @($HostName, $uploadCommand) -InputFile $ArchivePath
$postInstallB64 = ""
if ($PostInstall) {
$postInstallB64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($PostInstall))
}
$useSudoValue = if ($Sudo) { "1" } else { "0" }
$keepRemoteTempValue = if ($KeepRemoteTemp) { "1" } else { "0" }
$remoteCommand = @(
"REMOTE_DIR=$(ConvertTo-RemoteSingleQuoted $RemoteDir)",
"REMOTE_ARCHIVE=$(ConvertTo-RemoteSingleQuoted $remoteArchive)",
"REMOTE_WORK_DIR=$(ConvertTo-RemoteSingleQuoted $remoteWorkDir)",
"KEEP_REMOTE_TEMP='$keepRemoteTempValue'",
"POST_INSTALL_B64='$postInstallB64'",
"USE_SUDO='$useSudoValue'",
"bash -s"
) -join " "
$remoteScript = @'
set -euo pipefail
remote_now_ms() {
date +%s%3N
}
remote_format_duration() {
local ms="$1"
local seconds=$((ms / 1000))
local millis=$((ms % 1000))
local minutes=$((seconds / 60))
seconds=$((seconds % 60))
if [[ "$minutes" -gt 0 ]]; then
printf '%dm%02d.%03ds' "$minutes" "$seconds" "$millis"
else
printf '%d.%03ds' "$seconds" "$millis"
fi
}
REMOTE_START_MS="$(remote_now_ms)"
REMOTE_LAST_LOG_MS="$REMOTE_START_MS"
remote_log() {
local current_ms
local total_ms
local step_ms
current_ms="$(remote_now_ms)"
total_ms=$((current_ms - REMOTE_START_MS))
step_ms=$((current_ms - REMOTE_LAST_LOG_MS))
REMOTE_LAST_LOG_MS="$current_ms"
printf '[deploy][remote][+%s][total %s] %s\n' "$(remote_format_duration "$step_ms")" "$(remote_format_duration "$total_ms")" "$*"
}
run_priv() {
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo "$@"
else
"$@"
fi
}
tar_extract_flags=(--no-same-owner --no-same-permissions --no-overwrite-dir)
remote_log "prepare remote work dir: $REMOTE_WORK_DIR"
mkdir -p "$REMOTE_WORK_DIR"
remote_log "extract uploaded archive"
tar -xzf "$REMOTE_ARCHIVE" -C "$REMOTE_WORK_DIR"
remote_log "ensure remote dir: $REMOTE_DIR"
run_priv mkdir -p "$REMOTE_DIR"
if [[ -d "$REMOTE_WORK_DIR/payload" ]]; then
remote_log "install payload into remote dir"
tar -cf - -C "$REMOTE_WORK_DIR/payload" . | run_priv tar "${tar_extract_flags[@]}" -xf - -C "$REMOTE_DIR"
fi
if [[ -f "$REMOTE_WORK_DIR/.deleted-paths.txt" ]]; then
remote_log "apply deleted paths"
while IFS= read -r rel; do
[[ -n "$rel" ]] || continue
case "$rel" in
*".."*|/*)
echo "[deploy][remote][warn] skip unsafe delete path: $rel" >&2
continue
;;
esac
run_priv rm -rf "$REMOTE_DIR/$rel"
done < "$REMOTE_WORK_DIR/.deleted-paths.txt"
fi
if [[ -n "${POST_INSTALL_B64:-}" ]]; then
remote_log "run post-install command"
POST_INSTALL_CMD="$(printf '%s' "$POST_INSTALL_B64" | base64 -d)"
cd "$REMOTE_DIR"
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo bash -lc "$POST_INSTALL_CMD"
else
bash -lc "$POST_INSTALL_CMD"
fi
fi
if [[ "${KEEP_REMOTE_TEMP:-0}" != "1" ]]; then
remote_log "clean remote temp files"
rm -rf "$REMOTE_WORK_DIR" "$REMOTE_ARCHIVE"
fi
remote_log "remote install finished"
'@
Write-DeployLog "installing on server: $RemoteDir"
Start-ProcessWithInputText -FilePath $SshBin -Arguments @($HostName, $remoteCommand) -InputText $remoteScript
Write-DeployLog "deploy finished"
Write-DeployLog "mode: $Mode"
Write-DeployLog "source: $SourceDir"
Write-DeployLog "remote: ${HostName}:$RemoteDir"
} finally {
if ($WorkDir -and (Test-Path -LiteralPath $WorkDir)) {
Remove-Item -LiteralPath $WorkDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
+699
View File
@@ -0,0 +1,699 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
./scripts/deploy-server.sh --remote-dir <remote_dir> [options]
Modes:
1. Full deploy (no commit ids)
./scripts/deploy-server.sh --remote-dir /www/wwwroot/test-server.sbnews.net
2. Incremental deploy (compare two commits)
./scripts/deploy-server.sh \
--from <old_commit> \
--to <new_commit> \
--remote-dir /www/wwwroot/test-server.sbnews.net
3. Auto incremental deploy (compare latest two commits)
./scripts/deploy-server.sh \
--auto-incremental \
--remote-dir /www/wwwroot/test-server.sbnews.net
Options:
--source-dir <dir> Local source directory, default: server
--remote-dir <dir> Remote install directory, required
--host <ssh_alias> SSH host/alias, default: sbnews
--ssh-bin <cmd> SSH command, default: ssh. Use ssh.exe in WSL to reuse Windows SSH config
--auto-incremental Incremental deploy using HEAD~1 as --from and HEAD as --to
--from <commit> Base commit for incremental deploy
--to <commit> Target commit for incremental deploy
--remote-tmp <dir> Remote temp directory, default: /tmp
--post-install <cmd> Run command on server after extract/install
--sudo Use sudo on server when extracting/removing files
--keep-remote-temp Keep remote temp files after install
--include-vendor Include vendor directory in full package
--include-env Include .env in full package
--include-runtime Include runtime directory in full package
--include-uploads Include public/uploads directory in full package
--include-public-builds Include public/admin and public/mobile in full package
--include-crawler-data Include crawler data/logs/venv cache directories in full package
--dry-run Build package and print changed/deleted files, do not upload
-h, --help Show this help
Notes:
- Full deploy packages only these server paths by default:
app, config, extend, public/dongqiudi-crawler, route.
- Auto incremental deploy compares HEAD~1 and HEAD.
- Incremental deploy compares two commit ids and packages exact file contents from --to.
- If server is a root gitlink without server/.git metadata, incremental deploy falls back
to packaging the current working tree for the default server include paths.
- Deleted files between --from and --to are removed on the server.
- Upload uses ssh stdin instead of scp: ssh <host> "cat > archive" < local.tar.gz
EOF
}
now_ms() {
if command -v python3 >/dev/null 2>&1; then
python3 - <<'PY'
import time
print(int(time.time() * 1000))
PY
elif command -v python >/dev/null 2>&1; then
python - <<'PY'
import time
print(int(time.time() * 1000))
PY
else
printf '%s000\n' "$(date +%s)"
fi
}
format_duration() {
local ms="$1"
local seconds=$((ms / 1000))
local millis=$((ms % 1000))
local minutes=$((seconds / 60))
seconds=$((seconds % 60))
if [[ "$minutes" -gt 0 ]]; then
printf '%dm%02d.%03ds' "$minutes" "$seconds" "$millis"
else
printf '%d.%03ds' "$seconds" "$millis"
fi
}
DEPLOY_START_MS="$(now_ms)"
DEPLOY_LAST_LOG_MS="$DEPLOY_START_MS"
log() {
local current_ms
local total_ms
local step_ms
current_ms="$(now_ms)"
total_ms=$((current_ms - DEPLOY_START_MS))
step_ms=$((current_ms - DEPLOY_LAST_LOG_MS))
DEPLOY_LAST_LOG_MS="$current_ms"
printf '[deploy][+%s][total %s] %s\n' "$(format_duration "$step_ms")" "$(format_duration "$total_ms")" "$*"
}
fail() {
printf '[deploy][error] %s\n' "$*" >&2
exit 1
}
require_cmd() {
command -v "$1" >/dev/null 2>&1 || fail "missing command: $1"
}
normalize_dir() {
local value="$1"
value="${value%/}"
printf '%s' "$value"
}
safe_remote_single_quote() {
printf "%s" "$1" | sed "s/'/'\\\\''/g"
}
SOURCE_DIR="server"
REMOTE_DIR=""
HOST="sbnews"
SSH_BIN="ssh"
AUTO_INCREMENTAL=0
FROM_COMMIT=""
TO_COMMIT=""
REMOTE_TMP="/tmp"
POST_INSTALL=""
USE_SUDO=0
KEEP_REMOTE_TEMP=0
INCLUDE_VENDOR=0
INCLUDE_ENV=0
INCLUDE_RUNTIME=0
INCLUDE_UPLOADS=0
INCLUDE_PUBLIC_BUILDS=0
INCLUDE_CRAWLER_DATA=0
DRY_RUN=0
FULL_INCLUDE_PATHS=(
"app"
"config"
"extend"
"public/dongqiudi-crawler"
"route"
)
while [[ $# -gt 0 ]]; do
case "$1" in
--source-dir)
[[ $# -ge 2 ]] || fail "--source-dir requires a value"
SOURCE_DIR="$2"
shift 2
;;
--remote-dir)
[[ $# -ge 2 ]] || fail "--remote-dir requires a value"
REMOTE_DIR="$2"
shift 2
;;
--host)
[[ $# -ge 2 ]] || fail "--host requires a value"
HOST="$2"
shift 2
;;
--ssh-bin)
[[ $# -ge 2 ]] || fail "--ssh-bin requires a value"
SSH_BIN="$2"
shift 2
;;
--auto-incremental)
AUTO_INCREMENTAL=1
shift
;;
--from)
[[ $# -ge 2 ]] || fail "--from requires a value"
FROM_COMMIT="$2"
shift 2
;;
--to)
[[ $# -ge 2 ]] || fail "--to requires a value"
TO_COMMIT="$2"
shift 2
;;
--remote-tmp)
[[ $# -ge 2 ]] || fail "--remote-tmp requires a value"
REMOTE_TMP="$2"
shift 2
;;
--post-install)
[[ $# -ge 2 ]] || fail "--post-install requires a value"
POST_INSTALL="$2"
shift 2
;;
--sudo)
USE_SUDO=1
shift
;;
--keep-remote-temp)
KEEP_REMOTE_TEMP=1
shift
;;
--include-vendor)
INCLUDE_VENDOR=1
shift
;;
--include-env)
INCLUDE_ENV=1
shift
;;
--include-runtime)
INCLUDE_RUNTIME=1
shift
;;
--include-uploads)
INCLUDE_UPLOADS=1
shift
;;
--include-public-builds)
INCLUDE_PUBLIC_BUILDS=1
shift
;;
--include-crawler-data)
INCLUDE_CRAWLER_DATA=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
fail "unknown argument: $1"
;;
esac
done
[[ -n "$REMOTE_DIR" ]] || {
usage
fail "--remote-dir is required"
}
SOURCE_DIR="$(normalize_dir "$SOURCE_DIR")"
REMOTE_DIR="$(normalize_dir "$REMOTE_DIR")"
REMOTE_TMP="$(normalize_dir "$REMOTE_TMP")"
if [[ "$AUTO_INCREMENTAL" -eq 1 ]]; then
[[ -z "$FROM_COMMIT" && -z "$TO_COMMIT" ]] || fail "--auto-incremental cannot be used with --from/--to"
FROM_COMMIT="HEAD~1"
TO_COMMIT="HEAD"
MODE="incremental"
elif [[ -n "$FROM_COMMIT" || -n "$TO_COMMIT" ]]; then
[[ -n "$FROM_COMMIT" && -n "$TO_COMMIT" ]] || fail "incremental deploy requires both --from and --to"
MODE="incremental"
else
MODE="full"
fi
require_cmd git
require_cmd tar
require_cmd "$SSH_BIN"
if [[ -n "$POST_INSTALL" ]]; then
require_cmd base64
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
SOURCE_ABS="$REPO_ROOT/$SOURCE_DIR"
cd "$REPO_ROOT"
[[ -d "$SOURCE_ABS" ]] || fail "source directory not found: $SOURCE_DIR"
GIT_CWD="$REPO_ROOT"
GIT_PATH_PREFIX="$SOURCE_DIR"
SOURCE_IS_GIT_REPO=0
SOURCE_IS_GITLINK=0
if SOURCE_GIT_TOP="$(git -C "$SOURCE_ABS" rev-parse --show-toplevel 2>/dev/null)" && [[ "$(cd "$SOURCE_GIT_TOP" && pwd -P)" == "$SOURCE_ABS" ]]; then
GIT_CWD="$SOURCE_ABS"
GIT_PATH_PREFIX=""
SOURCE_IS_GIT_REPO=1
elif ! git -C "$REPO_ROOT" rev-parse --show-toplevel >/dev/null 2>&1; then
[[ "$MODE" == "full" ]] || fail "incremental deploy requires git metadata in $SOURCE_DIR or repo root"
fi
if [[ "$SOURCE_IS_GIT_REPO" -ne 1 ]] && git -C "$REPO_ROOT" ls-files -s -- "$SOURCE_DIR" | awk '{print $1}' | grep -qx '160000'; then
SOURCE_IS_GITLINK=1
fi
if [[ "$MODE" == "incremental" ]]; then
git -C "$GIT_CWD" rev-parse --verify "${FROM_COMMIT}^{commit}" >/dev/null 2>&1 || fail "invalid --from commit: $FROM_COMMIT"
git -C "$GIT_CWD" rev-parse --verify "${TO_COMMIT}^{commit}" >/dev/null 2>&1 || fail "invalid --to commit: $TO_COMMIT"
FROM_COMMIT="$(git -C "$GIT_CWD" rev-parse "$FROM_COMMIT")"
TO_COMMIT="$(git -C "$GIT_CWD" rev-parse "$TO_COMMIT")"
fi
mkdir -p "$REPO_ROOT/.tmp"
WORK_DIR="$(mktemp -d "$REPO_ROOT/.tmp/deploy-server.XXXXXX")"
PACKAGE_ROOT="$WORK_DIR/package"
PAYLOAD_DIR="$PACKAGE_ROOT/payload"
EXTRACT_DIR="$WORK_DIR/extract"
ARCHIVE_PATH="$WORK_DIR/${SOURCE_DIR//\//-}-${MODE}.tar.gz"
DELETED_PATHS_FILE="$PACKAGE_ROOT/.deleted-paths.txt"
DEPLOY_INFO_FILE="$PACKAGE_ROOT/.deploy-info.txt"
CHANGED_LOG="$WORK_DIR/changed-paths.txt"
DELETED_LOG="$WORK_DIR/deleted-paths.txt"
cleanup_local() {
if [[ -n "${WORK_DIR:-}" && -d "$WORK_DIR" ]]; then
chmod -R u+rwX "$WORK_DIR" 2>/dev/null || true
rm -rf "$WORK_DIR" || true
fi
}
trap cleanup_local EXIT
mkdir -p "$PAYLOAD_DIR" "$EXTRACT_DIR"
touch "$DELETED_PATHS_FILE" "$CHANGED_LOG" "$DELETED_LOG"
copy_full_payload() {
local tar_args=()
tar_args+=(--exclude=.git)
tar_args+=(--exclude=.idea)
tar_args+=(--exclude=.vscode)
tar_args+=(--exclude=.tmp)
tar_args+=(--exclude=.gitignore)
tar_args+=(--exclude='*.log')
tar_args+=(--exclude='release-*.zip')
tar_args+=(--exclude='*.zip')
tar_args+=(--exclude='__pycache__')
tar_args+=(--exclude='*.pyc')
if [[ "$INCLUDE_ENV" -ne 1 ]]; then
tar_args+=(--exclude=.env)
fi
if [[ "$INCLUDE_VENDOR" -ne 1 ]]; then
tar_args+=(--exclude=vendor)
fi
if [[ "$INCLUDE_RUNTIME" -ne 1 ]]; then
tar_args+=(--exclude=runtime)
fi
if [[ "$INCLUDE_UPLOADS" -ne 1 ]]; then
tar_args+=(--exclude=public/uploads)
fi
if [[ "$INCLUDE_PUBLIC_BUILDS" -ne 1 ]]; then
tar_args+=(--exclude=public/admin)
tar_args+=(--exclude=public/mobile)
fi
if [[ "$INCLUDE_CRAWLER_DATA" -ne 1 ]]; then
tar_args+=(--exclude=public/dongqiudi-crawler/data)
tar_args+=(--exclude=public/dongqiudi-crawler/logs)
tar_args+=(--exclude=public/dongqiudi-crawler/venv)
tar_args+=(--exclude=public/dongqiudi-crawler/__pycache__)
fi
log "building full payload from current working tree: $SOURCE_DIR"
log "full include paths: ${FULL_INCLUDE_PATHS[*]}"
(
cd "$SOURCE_ABS"
tar "${tar_args[@]}" -cf - "${FULL_INCLUDE_PATHS[@]}"
) | (
cd "$PAYLOAD_DIR"
tar -xf -
)
}
strip_source_prefix() {
local path="$1"
if [[ -z "$GIT_PATH_PREFIX" ]]; then
printf '%s' "$path"
else
printf '%s' "${path#"$GIT_PATH_PREFIX"/}"
fi
}
is_under_source_dir() {
local path="$1"
if [[ -z "$GIT_PATH_PREFIX" ]]; then
is_deploy_included_path "$path"
return $?
fi
[[ "$path" == "$GIT_PATH_PREFIX/"* ]] || return 1
is_deploy_included_path "$(strip_source_prefix "$path")"
}
is_deploy_included_path() {
local rel="$1"
local include
for include in "${FULL_INCLUDE_PATHS[@]}"; do
if [[ "$rel" == "$include" || "$rel" == "$include/"* ]]; then
return 0
fi
done
return 1
}
short_commit() {
git -C "$GIT_CWD" rev-parse --short "$1" 2>/dev/null || printf '%s' "$1"
}
print_incremental_file_list() {
local title="$1"
local prefix="$2"
local file="$3"
log "$title"
if [[ -s "$file" ]]; then
sort -u "$file" | sed '/^$/d' | sed "s/^/ $prefix /"
else
printf ' (none)\n'
fi
}
print_update_log() {
local from_short=""
local to_short=""
local commit_lines=""
if [[ "$MODE" == "incremental" ]]; then
from_short="$(short_commit "$FROM_COMMIT")"
to_short="$(short_commit "$TO_COMMIT")"
log "update log:"
log "commit range: $from_short -> $to_short"
if [[ "$SOURCE_IS_GITLINK" -eq 1 ]]; then
log "$SOURCE_DIR is a root gitlink, showing root repository commits for the selected range"
commit_lines="$(git -C "$GIT_CWD" log --no-merges --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:' * %h %ad %an %s' "$FROM_COMMIT..$TO_COMMIT" 2>/dev/null || true)"
elif [[ -n "$GIT_PATH_PREFIX" ]]; then
commit_lines="$(git -C "$GIT_CWD" log --no-merges --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:' * %h %ad %an %s' "$FROM_COMMIT..$TO_COMMIT" -- "$GIT_PATH_PREFIX" 2>/dev/null || true)"
else
commit_lines="$(git -C "$GIT_CWD" log --no-merges --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:' * %h %ad %an %s' "$FROM_COMMIT..$TO_COMMIT" 2>/dev/null || true)"
fi
log "commits:"
if [[ -n "$commit_lines" ]]; then
printf '%s\n' "$commit_lines"
else
printf ' (none)\n'
fi
print_incremental_file_list "changed files:" "+" "$CHANGED_LOG"
print_incremental_file_list "deleted files:" "-" "$DELETED_LOG"
else
log "update log:"
log "mode: full deploy from current working tree"
log "full include paths: ${FULL_INCLUDE_PATHS[*]}"
commit_lines="$(git -C "$GIT_CWD" log -1 --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:' * %h %ad %an %s' 2>/dev/null || true)"
log "latest commit:"
if [[ -n "$commit_lines" ]]; then
printf '%s\n' "$commit_lines"
else
printf ' (none)\n'
fi
fi
}
build_incremental_payload() {
local raw_diff="$WORK_DIR/diff-name-status.txt"
local archive_include="$WORK_DIR/incremental.tar"
local diff_args=()
if [[ "$SOURCE_IS_GITLINK" -eq 1 ]]; then
log "$SOURCE_DIR is tracked as a root gitlink; exact file-level diff is unavailable without $SOURCE_DIR/.git"
log "building fallback payload from current working tree include paths: ${FULL_INCLUDE_PATHS[*]}"
printf '%s\n' "${FULL_INCLUDE_PATHS[@]}" > "$CHANGED_LOG"
copy_full_payload
return
fi
if [[ -n "$GIT_PATH_PREFIX" ]]; then
diff_args+=(-- "$GIT_PATH_PREFIX")
fi
git -C "$GIT_CWD" diff --name-status --find-renames "$FROM_COMMIT" "$TO_COMMIT" "${diff_args[@]}" > "$raw_diff"
while IFS=$'\t' read -r status path1 path2; do
[[ -n "${status:-}" ]] || continue
case "$status" in
D)
is_under_source_dir "$path1" || continue
strip_source_prefix "$path1" >> "$DELETED_LOG"
;;
R*|C*)
[[ -n "${path2:-}" ]] || continue
is_under_source_dir "$path2" || continue
printf '%s\n' "$path2" >> "$CHANGED_LOG"
if [[ "$status" == R* ]] && is_under_source_dir "$path1"; then
strip_source_prefix "$path1" >> "$DELETED_LOG"
fi
;;
*)
is_under_source_dir "$path1" || continue
printf '%s\n' "$path1" >> "$CHANGED_LOG"
;;
esac
done < "$raw_diff"
mapfile -t changed_paths < <(sort -u "$CHANGED_LOG" | sed '/^$/d')
mapfile -t deleted_paths < <(sort -u "$DELETED_LOG" | sed '/^$/d')
if [[ "${#changed_paths[@]}" -eq 0 && "${#deleted_paths[@]}" -eq 0 ]]; then
log "no changed files detected between $FROM_COMMIT and $TO_COMMIT under $SOURCE_DIR"
exit 0
fi
if [[ "${#deleted_paths[@]}" -gt 0 ]]; then
printf '%s\n' "${deleted_paths[@]}" > "$DELETED_PATHS_FILE"
fi
if [[ "${#changed_paths[@]}" -gt 0 ]]; then
log "building incremental payload from commit $TO_COMMIT"
git -C "$GIT_CWD" archive --format=tar --output="$archive_include" "$TO_COMMIT" -- "${changed_paths[@]}"
tar -xf "$archive_include" -C "$EXTRACT_DIR"
if [[ "$SOURCE_IS_GIT_REPO" -eq 1 ]]; then
(
cd "$EXTRACT_DIR"
tar -cf - .
) | (
cd "$PAYLOAD_DIR"
tar -xf -
)
elif [[ -d "$EXTRACT_DIR/$SOURCE_DIR" ]]; then
(
cd "$EXTRACT_DIR/$SOURCE_DIR"
tar -cf - .
) | (
cd "$PAYLOAD_DIR"
tar -xf -
)
fi
fi
}
if [[ "$MODE" == "full" ]]; then
copy_full_payload
else
build_incremental_payload
fi
print_update_log
{
printf 'mode=%s\n' "$MODE"
printf 'source_dir=%s\n' "$SOURCE_DIR"
printf 'host=%s\n' "$HOST"
printf 'remote_dir=%s\n' "$REMOTE_DIR"
printf 'built_at=%s\n' "$(date '+%Y-%m-%d %H:%M:%S')"
if [[ "$MODE" == "incremental" ]]; then
printf 'auto_incremental=%s\n' "$AUTO_INCREMENTAL"
printf 'source_is_gitlink=%s\n' "$SOURCE_IS_GITLINK"
printf 'from_commit=%s\n' "$FROM_COMMIT"
printf 'to_commit=%s\n' "$TO_COMMIT"
printf 'changed_count=%s\n' "$(sort -u "$CHANGED_LOG" | sed '/^$/d' | wc -l | tr -d ' ')"
printf 'deleted_count=%s\n' "$(sort -u "$DELETED_LOG" | sed '/^$/d' | wc -l | tr -d ' ')"
fi
} > "$DEPLOY_INFO_FILE"
log "packing archive: $ARCHIVE_PATH"
(
cd "$PACKAGE_ROOT"
tar -czf "$ARCHIVE_PATH" .
)
log "package size: $(du -h "$ARCHIVE_PATH" | awk '{print $1}')"
if [[ "$DRY_RUN" -eq 1 ]]; then
log "dry-run enabled, skip upload/install"
exit 0
fi
TIMESTAMP="$(date '+%Y%m%d-%H%M%S')"
REMOTE_WORK_DIR="$REMOTE_TMP/${SOURCE_DIR//\//-}-deploy-$TIMESTAMP-$$"
REMOTE_ARCHIVE="$REMOTE_TMP/${SOURCE_DIR//\//-}-${MODE}-$TIMESTAMP.tar.gz"
REMOTE_TMP_Q="$(safe_remote_single_quote "$REMOTE_TMP")"
REMOTE_ARCHIVE_Q="$(safe_remote_single_quote "$REMOTE_ARCHIVE")"
log "uploading archive to $HOST:$REMOTE_ARCHIVE"
"$SSH_BIN" "$HOST" "mkdir -p '$REMOTE_TMP_Q' && cat > '$REMOTE_ARCHIVE_Q'" < "$ARCHIVE_PATH"
POST_INSTALL_B64=""
if [[ -n "$POST_INSTALL" ]]; then
POST_INSTALL_B64="$(printf '%s' "$POST_INSTALL" | base64 | tr -d '\r\n')"
fi
log "installing on server: $REMOTE_DIR"
"$SSH_BIN" "$HOST" \
"REMOTE_DIR='$(safe_remote_single_quote "$REMOTE_DIR")' REMOTE_ARCHIVE='$(safe_remote_single_quote "$REMOTE_ARCHIVE")' REMOTE_WORK_DIR='$(safe_remote_single_quote "$REMOTE_WORK_DIR")' KEEP_REMOTE_TEMP='$KEEP_REMOTE_TEMP' POST_INSTALL_B64='$POST_INSTALL_B64' USE_SUDO='$USE_SUDO' bash -s" <<'REMOTE_SCRIPT'
set -euo pipefail
remote_now_ms() {
if command -v python3 >/dev/null 2>&1; then
python3 - <<'PY'
import time
print(int(time.time() * 1000))
PY
elif command -v python >/dev/null 2>&1; then
python - <<'PY'
import time
print(int(time.time() * 1000))
PY
else
printf '%s000\n' "$(date +%s)"
fi
}
remote_format_duration() {
local ms="$1"
local seconds=$((ms / 1000))
local millis=$((ms % 1000))
local minutes=$((seconds / 60))
seconds=$((seconds % 60))
if [[ "$minutes" -gt 0 ]]; then
printf '%dm%02d.%03ds' "$minutes" "$seconds" "$millis"
else
printf '%d.%03ds' "$seconds" "$millis"
fi
}
REMOTE_START_MS="$(remote_now_ms)"
REMOTE_LAST_LOG_MS="$REMOTE_START_MS"
remote_log() {
local current_ms
local total_ms
local step_ms
current_ms="$(remote_now_ms)"
total_ms=$((current_ms - REMOTE_START_MS))
step_ms=$((current_ms - REMOTE_LAST_LOG_MS))
REMOTE_LAST_LOG_MS="$current_ms"
printf '[deploy][remote][+%s][total %s] %s\n' "$(remote_format_duration "$step_ms")" "$(remote_format_duration "$total_ms")" "$*"
}
run_priv() {
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo "$@"
else
"$@"
fi
}
tar_extract_flags=(--no-same-owner --no-same-permissions --no-overwrite-dir)
remote_log "prepare remote work dir: $REMOTE_WORK_DIR"
mkdir -p "$REMOTE_WORK_DIR"
remote_log "extract uploaded archive"
tar -xzf "$REMOTE_ARCHIVE" -C "$REMOTE_WORK_DIR"
remote_log "ensure remote dir: $REMOTE_DIR"
run_priv mkdir -p "$REMOTE_DIR"
if [[ -d "$REMOTE_WORK_DIR/payload" ]]; then
remote_log "install payload into remote dir"
tar -cf - -C "$REMOTE_WORK_DIR/payload" . | run_priv tar "${tar_extract_flags[@]}" -xf - -C "$REMOTE_DIR"
fi
if [[ -f "$REMOTE_WORK_DIR/.deleted-paths.txt" ]]; then
remote_log "apply deleted paths"
while IFS= read -r rel; do
[[ -n "$rel" ]] || continue
case "$rel" in
*".."*|/*)
echo "[deploy][remote][warn] skip unsafe delete path: $rel" >&2
continue
;;
esac
run_priv rm -rf "$REMOTE_DIR/$rel"
done < "$REMOTE_WORK_DIR/.deleted-paths.txt"
fi
if [[ -n "${POST_INSTALL_B64:-}" ]]; then
remote_log "run post-install command"
POST_INSTALL_CMD="$(printf '%s' "$POST_INSTALL_B64" | base64 -d)"
cd "$REMOTE_DIR"
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo bash -lc "$POST_INSTALL_CMD"
else
bash -lc "$POST_INSTALL_CMD"
fi
fi
if [[ "${KEEP_REMOTE_TEMP:-0}" != "1" ]]; then
remote_log "clean remote temp files"
rm -rf "$REMOTE_WORK_DIR" "$REMOTE_ARCHIVE"
fi
remote_log "remote install finished"
REMOTE_SCRIPT
log "deploy finished"
log "mode: $MODE"
log "source: $SOURCE_DIR"
log "remote: $HOST:$REMOTE_DIR"
Submodule server deleted from 187d583d21
+24
View File
@@ -0,0 +1,24 @@
APP_DEBUG = true
DASHSCOPE_API_KEY = your_dashscope_api_key
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = test
USERNAME = username
PASSWORD = password
HOSTPORT = 3306
CHARSET = utf8mb4
DEBUG = true
PREFIX = la_
[LANG]
default_lang = zh-cn
[PROJECT]
UNIQUE_IDENTIFICATION = likeadmin
# 演示环境
DEMO_ENV = false
+13
View File
@@ -0,0 +1,13 @@
### 该问题是怎么引起的?
### 重现步骤
### 报错信息
@@ -0,0 +1,12 @@
### 相关的Issue
### 原因(目的、解决的问题等)
### 描述(做了什么,变更了什么)
### 测试用例(新增、改动、可能影响的功能)
+43
View File
@@ -0,0 +1,43 @@
# 已停用:改由 la_dev_crontab 定时任务调用(params=crawl
# 原配置保留供参考,不删除以便回溯
#
# name: Truth Social Crawler
#
# on:
# schedule:
# # 每小时执行一次 (UTC 时间)
# - cron: '0 * * * *'
# workflow_dispatch: # 允许手动触发
#
# jobs:
# crawl:
# runs-on: ubuntu-latest
# permissions:
# contents: write
#
# steps:
# - name: Checkout
# uses: actions/checkout@v4
#
# - name: Setup Python
# uses: actions/setup-python@v5
# with:
# python-version: '3.12'
#
# - name: Install dependencies
# run: pip install -r public/truth-social/requirements.txt
#
# - name: Run crawler
# run: python public/truth-social/crawler.py
#
# - name: Commit & Push data
# run: |
# git config user.name "github-actions[bot]"
# git config user.email "github-actions[bot]@users.noreply.github.com"
# git add public/truth-social/data/
# if git diff --staged --quiet; then
# echo "No new data to commit"
# else
# git commit -m "data: update truth social posts $(date -u +%Y-%m-%dT%H:%M:%SZ)"
# git push
# fi
BIN
View File
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true
+116
View File
@@ -0,0 +1,116 @@
# Server Agent — Sport Era 后端
ThinkPHP / likeadmin 多应用后台系统。**本模块是项目核心,定义 adminapi、api、定时任务、数据库模型与业务逻辑,其他端依赖此模块。**
## 技术栈
- **PHP** 8.x
- **框架** ThinkPHP + likeadmin
- **数据库** MySQL(库名 `sbnews`,表前缀 `la_`
- **缓存** RedisThinkPHP Cache facade
- **Web 服务** Nginx + PHP-FPM
## 项目结构
```text
app/
├── adminapi/ # 后台管理 API → admin/ 消费
├── api/ # 前台公开 API → uniapp/ + pc/ 消费
├── common/ # 公共模型/服务/缓存/中间件/监听器/枚举
├── command/ # 控制台命令与定时任务
├── service/ # 公共服务封装
├── common.php # 全局函数
├── middleware.php # 全局中间件
└── event.php # 事件监听
config/ # 框架配置
route/ # 路由定义
public/ # Web 入口、上传目录、脚本与静态资源
```
## 模块职责
| 应用 | 路由前缀 | 消费方 | 控制器目录 |
| -------- | ------------- | --------------- | -------------------------- |
| adminapi | `/adminapi/*` | admin/ 管理后台 | `app/adminapi/controller/` |
| api | `/api/*` | uniapp/ + pc/ | `app/api/controller/` |
## 目录约定
- `controller/` — 控制器(类名后缀 `Controller`
- `logic/` — 业务逻辑层
- `service/` — 服务层
- `validate/` — 验证器层
- `lists/` — 列表查询封装
- `model/` — ORM 模型
- `cache/` — Redis 缓存
- `http/middleware/` — 中间件
## 运行命令
```bash
composer install
php think run
php think crontab
```
---
## 并行协作协议
### 新功能开发流程
```text
Step 1: 后端定义契约
1.1 确认是否已有数据表、模型、字典或配置可复用
1.2 创建或调整 Model / Logic / Validate / Lists / Controller
1.3 输出接口清单:
## 新功能: XXX
### adminapi 接口
| 方法 | 路径 | 说明 |
| GET | /adminapi/xxx/lists | 列表 |
| POST | /adminapi/xxx/add | 新增 |
| POST | /adminapi/xxx/edit | 编辑 |
| POST | /adminapi/xxx/del | 删除 |
### api 接口
| 方法 | 路径 | 说明 |
| GET | /api/xxx/lists | 前台列表 |
| GET | /api/xxx/detail | 前台详情 |
Step 2: 前端并行消费契约
┌─ server/ 实现 controller + logic + validate + lists
├─ admin/ 查看 adminapi controller → 写管理页面
├─ uniapp/ 查看 api controller → 写手机端页面
└─ pc/ 查看 api controller → 写 PC 页面
Step 3: 集成联调与文档同步
- 检查接口响应格式、权限、字段、字典
- 同步更新 `业务进度管理.md`
```
## 与前端 Agent 的协作方式
1. **API 契约即文档**:前端优先查看 controller、validate、logic 获取接口签名、请求参数、响应结构。
2. **Model 即数据结构**:前端查看 `app/common/model/` 了解字段与访问器。
3. **枚举共享**:业务枚举优先使用字典表或配置表,不在 PHP / TS 中重复硬编码。
4. **上传接口统一**:后台使用 adminapi 上传接口,前台使用 api 上传接口,沿用现有封装。
## 后端开发硬性规范
1. **字典/配置驱动枚举**:状态、类型、分类、开关等优先落入字典表或配置表。
2. **列表查询沿用 Lists 封装**:后台列表页继承 `BaseAdminDataLists`,实现 `lists()``count()`
3. **控制器沿用基类能力**:后台控制器继承 `BaseAdminController`,列表使用 `$this->dataLists()`
4. **菜单与权限**:新增管理后台模块必须同步菜单和按钮权限,SQL 初始化必须幂等。
5. **接口响应格式**:沿用 likeadmin 统一响应结构,不随意增减顶层字段。
6. **时间字段处理**BaseModel 自动转换 `create_time` / `update_time`,不要对已转字符串再次 `date()`
7. **SQL 保留字**:原生 SQL 中 `system``order``group``key` 等字段必须用反引号包裹。
8. **定时任务**:注册在 `la_dev_crontab`,通过 `php think crontab` 统一调度。
## 近期踩坑
- `Validate::only()` 只限制校验字段范围,不会自动过滤请求参数;新增字段要同时检查 validate、logic、model、保存白名单和数据库列。
- `adminapi/match.match/edit` 保存失败时,先确认测试库或线上库 `la_match` 是否真的已补上目标字段,测试库缺列会直接导致写入失败。
+32
View File
@@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1. 需要给代码的用户一份Apache Licence
2. 如果你修改了代码,需要在被修改的文件中说明;
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可,但不可以表现为对Apache Licence构成更改。
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+36
View File
@@ -0,0 +1,36 @@
# sport-era-service
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+40
View File
@@ -0,0 +1,40 @@
# sport-era-service
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
上传项目 通过 rsync + scp 将完整 dongqiudi-crawler/ 上传到服务器
安装 pip curl get-pip.py | python3 → pip 26.0.1
安装依赖 pip3 install aiohttp requests httpx ... 等核心依赖(跳过了 playwright/curl_cffi 等重量级浏览器包,API 通道足够用)
验证运行 python3 main.py test ✅ 全部通过(API通道、比赛菜单、数据库连接)
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme_XXX.md 来支持不同的语言,例如 Readme_en.md, Readme_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+1
View File
@@ -0,0 +1 @@
deny from all
+22
View File
@@ -0,0 +1,22 @@
<?php
declare (strict_types = 1);
namespace app;
use think\Service;
/**
* 应用服务类
*/
class AppService extends Service
{
public function register()
{
// 服务注册
}
public function boot()
{
// 服务启动
}
}
+95
View File
@@ -0,0 +1,95 @@
<?php
declare (strict_types = 1);
namespace app;
use think\App;
use think\exception\ValidateException;
use think\Validate;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\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, $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);
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
// 添加自定义异常处理机制
// 其他错误交给系统处理
return parent::render($request, $e);
}
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace app;
// 应用请求对象类
class Request extends \think\Request
{
// 全局过滤规则
protected $filter = ['trim'];
}
+28
View File
@@ -0,0 +1,28 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
return [
'middleware' => [
// 初始化
app\adminapi\http\middleware\InitMiddleware::class,
// 登录验证
app\adminapi\http\middleware\LoginMiddleware::class,
// 权限认证
app\adminapi\http\middleware\AuthMiddleware::class,
// 演示模式 - 禁止提交数据
app\adminapi\http\middleware\CheckDemoMiddleware::class,
// 演示模式 - 不返回敏感数据
app\adminapi\http\middleware\EncryDemoDataMiddleware::class,
],
];
@@ -0,0 +1,40 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\adminapi\controller;
use think\App;
use app\common\controller\BaseLikeAdminController;
/**
* 管理元控制器基类
* Class BaseAdminController
* @package app\adminapi\controller
*/
class BaseAdminController extends BaseLikeAdminController
{
protected int $adminId = 0;
protected array $adminInfo = [];
public function initialize()
{
if (isset($this->request->adminInfo) && $this->request->adminInfo) {
$this->adminInfo = $this->request->adminInfo;
$this->adminId = $this->request->adminInfo['admin_id'];
}
}
}
@@ -0,0 +1,61 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\ConfigLogic;
/**
* 配置控制器
* Class ConfigController
* @package app\adminapi\controller
*/
class ConfigController extends BaseAdminController
{
public array $notNeedLogin = ['getConfig', 'dict'];
/**
* @notes 基础配置
* @return \think\response\Json
* @author 段誉
* @date 2021/12/31 11:01
*/
public function getConfig()
{
$data = ConfigLogic::getConfig();
return $this->data($data);
}
/**
* @notes 根据类型获取字典数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/9/27 19:10
*/
public function dict()
{
$type = $this->request->get('type', '');
$data = ConfigLogic::getDictByType($type);
return $this->data($data);
}
}
@@ -0,0 +1,50 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\common\cache\ExportCache;
use app\common\service\JsonService;
class DownloadController extends BaseAdminController
{
public array $notNeedLogin = ['export'];
/**
* @notes 导出文件
* @return \think\response\File|\think\response\Json
* @author 段誉
* @date 2022/11/24 16:10
*/
public function export()
{
//获取文件缓存的key
$fileKey = request()->get('file');
//通过文件缓存的key获取文件储存的路径
$exportCache = new ExportCache();
$fileInfo = $exportCache->getFile($fileKey);
if (empty($fileInfo)) {
return JsonService::fail('下载文件不存在');
}
//下载前删除缓存
$exportCache->delete($fileKey);
return download($fileInfo['src'] . $fileInfo['name'], $fileInfo['name']);
}
}
@@ -0,0 +1,137 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\adminapi\lists\file\FileCateLists;
use app\adminapi\lists\file\FileLists;
use app\adminapi\logic\FileLogic;
use app\adminapi\validate\FileValidate;
use think\response\Json;
/**文件管理
* Class FileController
* @package app\adminapi\controller
*/
class FileController extends BaseAdminController
{
/**
* @notes 文件列表
* @return Json
* @author 段誉
* @date 2021/12/29 14:30
*/
public function lists()
{
return $this->dataLists(new FileLists());
}
/**
* @notes 文件移动成功
* @return Json
* @author 段誉
* @date 2021/12/29 14:30
*/
public function move()
{
$params = (new FileValidate())->post()->goCheck('move');
FileLogic::move($params);
return $this->success('移动成功', [], 1, 1);
}
/**
* @notes 重命名文件
* @return Json
* @author 段誉
* @date 2021/12/29 14:31
*/
public function rename()
{
$params = (new FileValidate())->post()->goCheck('rename');
FileLogic::rename($params);
return $this->success('重命名成功', [], 1, 1);
}
/**
* @notes 删除文件
* @return Json
* @author 段誉
* @date 2021/12/29 14:31
*/
public function delete()
{
$params = (new FileValidate())->post()->goCheck('delete');
FileLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 分类列表
* @return Json
* @author 段誉
* @date 2021/12/29 14:31
*/
public function listCate()
{
return $this->dataLists(new FileCateLists());
}
/**
* @notes 添加文件分类
* @return Json
* @author 段誉
* @date 2021/12/29 14:31
*/
public function addCate()
{
$params = (new FileValidate())->post()->goCheck('addCate');
FileLogic::addCate($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑文件分类
* @return Json
* @author 段誉
* @date 2021/12/29 14:31
*/
public function editCate()
{
$params = (new FileValidate())->post()->goCheck('editCate');
FileLogic::editCate($params);
return $this->success('编辑成功', [], 1, 1);
}
/**
* @notes 删除文件分类
* @return Json
* @author 段誉
* @date 2021/12/29 14:32
*/
public function delCate()
{
$params = (new FileValidate())->post()->goCheck('id');
FileLogic::delCate($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,59 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\adminapi\logic\LoginLogic;
use app\adminapi\validate\LoginValidate;
/**
* 管理员登录控制器
* Class LoginController
* @package app\adminapi\controller
*/
class LoginController extends BaseAdminController
{
public array $notNeedLogin = ['account'];
/**
* @notes 账号登录
* @date 2021/6/30 17:01
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 令狐冲
*/
public function account()
{
$params = (new LoginValidate())->post()->goCheck();
return $this->data((new LoginLogic())->login($params));
}
/**
* @notes 退出登录
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 令狐冲
* @date 2021/7/8 00:36
*/
public function logout()
{
//退出登录情况特殊,只有成功的情况,也不需要token验证
(new LoginLogic())->logout($this->adminInfo);
return $this->success();
}
}
@@ -0,0 +1,80 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\common\service\UploadService;
use Exception;
use think\response\Json;
/**
* 上传文件
* Class UploadController
* @package app\adminapi\controller
*/
class UploadController extends BaseAdminController
{
/**
* @notes 上传图片
* @return Json
* @author 段誉
* @date 2021/12/29 16:27
*/
public function image()
{
try {
$cid = $this->request->post('cid', 0);
$result = UploadService::image($cid);
return $this->success('上传成功', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 上传视频
* @return Json
* @author 段誉
* @date 2021/12/29 16:27
*/
public function video()
{
try {
$cid = $this->request->post('cid', 0);
$result = UploadService::video($cid);
return $this->success('上传成功', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 上传文件
* @return Json
* @author dw
* @date 2023/06/26
*/
public function file()
{
try {
$cid = $this->request->post('cid', 0);
$result = UploadService::file($cid);
return $this->success('上传成功', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
}
@@ -0,0 +1,38 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\adminapi\logic\WorkbenchLogic;
/**
* 工作台
* Class WorkbenchCotroller
* @package app\adminapi\controller
*/
class WorkbenchController extends BaseAdminController
{
/**
* @notes 工作台
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 17:01
*/
public function index()
{
$result = WorkbenchLogic::index();
return $this->data($result);
}
}
@@ -0,0 +1,14 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\AiAnalysisLists;
class AiAnalysisController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AiAnalysisLists());
}
}
@@ -0,0 +1,33 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\AiConfigLists;
use app\adminapi\logic\ai\AiConfigLogic;
use app\adminapi\validate\ai\AiConfigValidate;
class AiConfigController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AiConfigLists());
}
public function detail()
{
$params = (new AiConfigValidate())->goCheck('detail');
$result = AiConfigLogic::detail($params);
return $this->data($result);
}
public function edit()
{
$params = (new AiConfigValidate())->post()->goCheck('edit');
$result = AiConfigLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(AiConfigLogic::getError());
}
}
@@ -0,0 +1,14 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\AiLogLists;
class AiLogController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AiLogLists());
}
}
@@ -0,0 +1,32 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\KbConfigLists;
use app\adminapi\logic\ai\KbConfigLogic;
use app\adminapi\validate\ai\KbConfigValidate;
class KbConfigController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new KbConfigLists());
}
public function detail()
{
$params = (new KbConfigValidate())->goCheck('detail');
return $this->data(KbConfigLogic::detail($params));
}
public function edit()
{
$params = (new KbConfigValidate())->post()->goCheck();
$result = KbConfigLogic::edit($params);
if ($result === true) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(KbConfigLogic::getError());
}
}
@@ -0,0 +1,14 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\KbDocumentLists;
class KbDocumentController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new KbDocumentLists());
}
}
@@ -0,0 +1,14 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\KbQueryLogLists;
class KbQueryLogController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new KbQueryLogLists());
}
}
@@ -0,0 +1,23 @@
<?php
namespace app\adminapi\controller\ai;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\ai\KbSyncJobLists;
use app\adminapi\validate\ai\KbSyncJobValidate;
use think\facade\Console;
class KbSyncJobController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new KbSyncJobLists());
}
public function rebuild()
{
$params = (new KbSyncJobValidate())->post()->goCheck();
Console::call('kb:rebuild', ['--domain' => $params['domain']]);
return $this->success('已触发重建任务');
}
}
@@ -0,0 +1,65 @@
<?php
namespace app\adminapi\controller\app;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\app\AppVersionLists;
use app\adminapi\logic\app\AppVersionLogic;
use app\adminapi\validate\app\AppVersionValidate;
/**
* APP 版本管理控制器
* Class AppVersionController
* @package app\adminapi\controller\app
*/
class AppVersionController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AppVersionLists());
}
public function add()
{
$params = (new AppVersionValidate())->post()->goCheck('add');
$result = AppVersionLogic::add($params);
if ($result === true) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(AppVersionLogic::getError());
}
public function edit()
{
$params = (new AppVersionValidate())->post()->goCheck('edit');
$result = AppVersionLogic::edit($params);
if ($result === true) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(AppVersionLogic::getError());
}
public function delete()
{
$params = (new AppVersionValidate())->post()->goCheck('delete');
AppVersionLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new AppVersionValidate())->goCheck('detail');
$result = AppVersionLogic::detail($params);
return $this->data($result);
}
public function updateStatus()
{
$params = (new AppVersionValidate())->post()->goCheck('status');
$result = AppVersionLogic::updateStatus($params);
if ($result === true) {
return $this->success('修改成功', [], 1, 1);
}
return $this->fail(AppVersionLogic::getError());
}
}
@@ -0,0 +1,33 @@
<?php
namespace app\adminapi\controller\article;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\article\ArticleAiCommentTaskLists;
use app\adminapi\logic\article\ArticleAiCommentTaskLogic;
use app\adminapi\validate\article\ArticleAiCommentTaskValidate;
class ArticleAiCommentTaskController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new ArticleAiCommentTaskLists());
}
public function delete()
{
$params = (new ArticleAiCommentTaskValidate())->post()->goCheck('delete');
ArticleAiCommentTaskLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function retry()
{
$params = (new ArticleAiCommentTaskValidate())->post()->goCheck('retry');
$result = ArticleAiCommentTaskLogic::retry($params);
if (true === $result) {
return $this->success('重置成功', [], 1, 1);
}
return $this->fail(ArticleAiCommentTaskLogic::getError());
}
}
@@ -0,0 +1,134 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\article;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\article\ArticleCateLists;
use app\adminapi\logic\article\ArticleCateLogic;
use app\adminapi\validate\article\ArticleCateValidate;
/**
* 资讯分类管理控制器
* Class ArticleCateController
* @package app\adminapi\controller\article
*/
class ArticleCateController extends BaseAdminController
{
/**
* @notes 查看资讯分类列表
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 17:11
*/
public function lists()
{
return $this->dataLists(new ArticleCateLists());
}
/**
* @notes 添加资讯分类
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 17:31
*/
public function add()
{
$params = (new ArticleCateValidate())->post()->goCheck('add');
ArticleCateLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑资讯分类
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 17:49
*/
public function edit()
{
$params = (new ArticleCateValidate())->post()->goCheck('edit');
$result = ArticleCateLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(ArticleCateLogic::getError());
}
/**
* @notes 删除资讯分类
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 17:52
*/
public function delete()
{
$params = (new ArticleCateValidate())->post()->goCheck('delete');
ArticleCateLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 资讯分类详情
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 17:54
*/
public function detail()
{
$params = (new ArticleCateValidate())->goCheck('detail');
$result = ArticleCateLogic::detail($params);
return $this->data($result);
}
/**
* @notes 更改资讯分类状态
* @return \think\response\Json
* @author heshihu
* @date 2022/2/21 10:15
*/
public function updateStatus()
{
$params = (new ArticleCateValidate())->post()->goCheck('status');
$result = ArticleCateLogic::updateStatus($params);
if (true === $result) {
return $this->success('修改成功', [], 1, 1);
}
return $this->fail(ArticleCateLogic::getError());
}
/**
* @notes 获取文章分类
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 10:54
*/
public function all()
{
$result = ArticleCateLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,132 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\article;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\article\ArticleLists;
use app\adminapi\logic\article\ArticleLogic;
use app\adminapi\validate\article\ArticleValidate;
/**
* 资讯管理控制器
* Class ArticleController
* @package app\adminapi\controller\article
*/
class ArticleController extends BaseAdminController
{
/**
* @notes 查看资讯列表
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 9:47
*/
public function lists()
{
return $this->dataLists(new ArticleLists());
}
/**
* @notes 添加资讯
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 9:57
*/
public function add()
{
$params = (new ArticleValidate())->post()->goCheck('add');
$result = ArticleLogic::add($params);
if (true === $result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(ArticleLogic::getError());
}
/**
* @notes 编辑资讯
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 10:12
*/
public function edit()
{
$params = (new ArticleValidate())->post()->goCheck('edit');
$result = ArticleLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(ArticleLogic::getError());
}
/**
* @notes 删除资讯
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 10:17
*/
public function delete()
{
$params = (new ArticleValidate())->post()->goCheck('delete');
ArticleLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 资讯详情
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 10:15
*/
public function detail()
{
$params = (new ArticleValidate())->goCheck('detail');
$result = ArticleLogic::detail($params);
return $this->data($result);
}
/**
* @notes 更改资讯状态
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 10:18
*/
public function updateStatus()
{
$params = (new ArticleValidate())->post()->goCheck('status');
$result = ArticleLogic::updateStatus($params);
if (true === $result) {
return $this->success('修改成功', [], 1, 1);
}
return $this->fail(ArticleLogic::getError());
}
/**
* @notes 批量推荐
* @return \think\response\Json
* @author heshihu
* @date 2022/2/22 10:18
*/
public function batchRecommend()
{
$params = (new ArticleValidate())->post()->goCheck('batchRecommend');
$result = ArticleLogic::batchRecommend($params);
if (true === $result) {
return $this->success('设置成功', [], 1, 1);
}
return $this->fail(ArticleLogic::getError());
}
}
@@ -0,0 +1,134 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\auth;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\auth\AdminLists;
use app\adminapi\validate\auth\AdminValidate;
use app\adminapi\logic\auth\AdminLogic;
use app\adminapi\validate\auth\editSelfValidate;
/**
* 管理员控制器
* Class AdminController
* @package app\adminapi\controller\auth
*/
class AdminController extends BaseAdminController
{
/**
* @notes 查看管理员列表
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 9:55
*/
public function lists()
{
return $this->dataLists(new AdminLists());
}
/**
* @notes 添加管理员
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 10:21
*/
public function add()
{
$params = (new AdminValidate())->post()->goCheck('add');
$result = AdminLogic::add($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(AdminLogic::getError());
}
/**
* @notes 编辑管理员
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 11:03
*/
public function edit()
{
$params = (new AdminValidate())->post()->goCheck('edit');
$result = AdminLogic::edit($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(AdminLogic::getError());
}
/**
* @notes 删除管理员
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 11:03
*/
public function delete()
{
$params = (new AdminValidate())->post()->goCheck('delete');
$result = AdminLogic::delete($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(AdminLogic::getError());
}
/**
* @notes 查看管理员详情
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 11:07
*/
public function detail()
{
$params = (new AdminValidate())->goCheck('detail');
$result = AdminLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取当前管理员信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/31 10:53
*/
public function mySelf()
{
$result = AdminLogic::detail(['id' => $this->adminId], 'auth');
return $this->data($result);
}
/**
* @notes 编辑超级管理员信息
* @return \think\response\Json
* @author 段誉
* @date 2022/4/8 17:54
*/
public function editSelf()
{
$params = (new editSelfValidate())->post()->goCheck('', ['admin_id' => $this->adminId]);
$result = AdminLogic::editSelf($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,142 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\auth;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\auth\MenuLists;
use app\adminapi\logic\auth\MenuLogic;
use app\adminapi\validate\auth\MenuValidate;
/**
* 系统菜单权限
* Class MenuController
* @package app\adminapi\controller\setting\system
*/
class MenuController extends BaseAdminController
{
/**
* @notes 获取菜单路由
* @return \think\response\Json
* @author 段誉
* @date 2022/6/29 17:41
*/
public function route()
{
$result = MenuLogic::getMenuByAdminId($this->adminId);
return $this->data($result);
}
/**
* @notes 获取菜单列表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/29 17:23
*/
public function lists()
{
return $this->dataLists(new MenuLists());
}
/**
* @notes 菜单详情
* @return \think\response\Json
* @author 段誉
* @date 2022/6/30 10:07
*/
public function detail()
{
$params = (new MenuValidate())->goCheck('detail');
return $this->data(MenuLogic::detail($params));
}
/**
* @notes 添加菜单
* @return \think\response\Json
* @author 段誉
* @date 2022/6/30 10:07
*/
public function add()
{
$params = (new MenuValidate())->post()->goCheck('add');
MenuLogic::add($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 编辑菜单
* @return \think\response\Json
* @author 段誉
* @date 2022/6/30 10:07
*/
public function edit()
{
$params = (new MenuValidate())->post()->goCheck('edit');
MenuLogic::edit($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 删除菜单
* @return \think\response\Json
* @author 段誉
* @date 2022/6/30 10:07
*/
public function delete()
{
$params = (new MenuValidate())->post()->goCheck('delete');
MenuLogic::delete($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 更新状态
* @return \think\response\Json
* @author 段誉
* @date 2022/7/6 17:04
*/
public function updateStatus()
{
$params = (new MenuValidate())->post()->goCheck('status');
MenuLogic::updateStatus($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 获取菜单数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 11:03
*/
public function all()
{
$result = MenuLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,124 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\auth;
use app\adminapi\{
logic\auth\RoleLogic,
lists\auth\RoleLists,
validate\auth\RoleValidate,
controller\BaseAdminController
};
/**
* 角色控制器
* Class RoleController
* @package app\adminapi\controller\auth
*/
class RoleController extends BaseAdminController
{
/**
* @notes 查看角色列表
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 11:49
*/
public function lists()
{
return $this->dataLists(new RoleLists());
}
/**
* @notes 添加权限
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 11:49
*/
public function add()
{
$params = (new RoleValidate())->post()->goCheck('add');
$res = RoleLogic::add($params);
if (true === $res) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(RoleLogic::getError());
}
/**
* @notes 编辑角色
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 14:18
*/
public function edit()
{
$params = (new RoleValidate())->post()->goCheck('edit');
$res = RoleLogic::edit($params);
if (true === $res) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(RoleLogic::getError());
}
/**
* @notes 删除角色
* @return \think\response\Json
* @author 段誉
* @date 2021/12/29 14:18
*/
public function delete()
{
$params = (new RoleValidate())->post()->goCheck('del');
RoleLogic::delete($params['id']);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 查看角色详情
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2021/12/29 14:18
*/
public function detail()
{
$params = (new RoleValidate())->goCheck('detail');
$detail = RoleLogic::detail($params['id']);
return $this->data($detail);
}
/**
* @notes 获取角色数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 10:39
*/
public function all()
{
$result = RoleLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\AppSettingLogic;
/**
* APP设置控制器
* Class AppSettingController
* @package app\adminapi\controller\setting\app
*/
class AppSettingController extends BaseAdminController
{
/**
* @notes 获取App设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:24
*/
public function getConfig()
{
$result = AppSettingLogic::getConfig();
return $this->data($result);
}
/**
* @notes App设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:25
*/
public function setConfig()
{
$params = $this->request->post();
AppSettingLogic::setConfig($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\MnpSettingsLogic;
use app\adminapi\validate\channel\MnpSettingsValidate;
/**
* 小程序设置
* Class MnpSettingsController
* @package app\adminapi\controller\channel
*/
class MnpSettingsController extends BaseAdminController
{
/**
* @notes 获取小程序配置
* @return \think\response\Json
* @author ljj
* @date 2022/2/16 9:38 上午
*/
public function getConfig()
{
$result = (new MnpSettingsLogic())->getConfig();
return $this->data($result);
}
/**
* @notes 设置小程序配置
* @return \think\response\Json
* @author ljj
* @date 2022/2/16 9:51 上午
*/
public function setConfig()
{
$params = (new MnpSettingsValidate())->post()->goCheck();
(new MnpSettingsLogic())->setConfig($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,74 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\OfficialAccountMenuLogic;
/**
* 微信公众号菜单控制器
* Class OfficialAccountMenuController
* @package app\adminapi\controller\channel
*/
class OfficialAccountMenuController extends BaseAdminController
{
/**
* @notes 保存菜单
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:41
*/
public function save()
{
$params = $this->request->post();
$result = OfficialAccountMenuLogic::save($params);
if(false === $result) {
return $this->fail(OfficialAccountMenuLogic::getError());
}
return $this->success('保存成功',[],1,1);
}
/**
* @notes 保存发布菜单
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:42
*/
public function saveAndPublish()
{
$params = $this->request->post();
$result = OfficialAccountMenuLogic::saveAndPublish($params);
if($result) {
return $this->success('保存并发布成功',[],1,1);
}
return $this->fail(OfficialAccountMenuLogic::getError());
}
/**
* @notes 查看菜单详情
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:42
*/
public function detail()
{
$result = OfficialAccountMenuLogic::detail();
return $this->data($result);
}
}
@@ -0,0 +1,148 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\channel\OfficialAccountReplyLists;
use app\adminapi\logic\channel\OfficialAccountReplyLogic;
use app\adminapi\validate\channel\OfficialAccountReplyValidate;
/**
* 微信公众号回复控制器
* Class OfficialAccountReplyController
* @package app\adminapi\controller\channel
*/
class OfficialAccountReplyController extends BaseAdminController
{
public array $notNeedLogin = ['index'];
/**
* @notes 查看回复列表(关注/关键词/默认)
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:58
*/
public function lists()
{
return $this->dataLists(new OfficialAccountReplyLists());
}
/**
* @notes 添加回复(关注/关键词/默认)
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:58
*/
public function add()
{
$params = (new OfficialAccountReplyValidate())->post()->goCheck('add');
$result = OfficialAccountReplyLogic::add($params);
if ($result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(OfficialAccountReplyLogic::getError());
}
/**
* @notes 查看回复详情
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:58
*/
public function detail()
{
$params = (new OfficialAccountReplyValidate())->goCheck('detail');
$result = OfficialAccountReplyLogic::detail($params);
return $this->data($result);
}
/**
* @notes 编辑回复(关注/关键词/默认)
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:58
*/
public function edit()
{
$params = (new OfficialAccountReplyValidate())->post()->goCheck('edit');
$result = OfficialAccountReplyLogic::edit($params);
if ($result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(OfficialAccountReplyLogic::getError());
}
/**
* @notes 删除回复(关注/关键词/默认)
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:59
*/
public function delete()
{
$params = (new OfficialAccountReplyValidate())->post()->goCheck('delete');
OfficialAccountReplyLogic::delete($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 更新排序
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:59
*/
public function sort()
{
$params = (new OfficialAccountReplyValidate())->post()->goCheck('sort');
OfficialAccountReplyLogic::sort($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 更新状态
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:59
*/
public function status()
{
$params = (new OfficialAccountReplyValidate())->post()->goCheck('status');
OfficialAccountReplyLogic::status($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 微信公众号回调
* @throws \ReflectionException
* @author 段誉
* @date 2022/3/29 10:59
*/
public function index()
{
$result = OfficialAccountReplyLogic::index();
return response($result->getBody())->header([
'Content-Type' => 'text/plain;charset=utf-8'
]);
}
}
@@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\OfficialAccountSettingLogic;
use app\adminapi\validate\channel\OfficialAccountSettingValidate;
/**
* 公众号设置
* Class OfficialAccountSettingController
* @package app\adminapi\controller\channel
*/
class OfficialAccountSettingController extends BaseAdminController
{
/**
* @notes 获取公众号配置
* @return \think\response\Json
* @author ljj
* @date 2022/2/16 10:09 上午
*/
public function getConfig()
{
$result = (new OfficialAccountSettingLogic())->getConfig();
return $this->data($result);
}
/**
* @notes 设置公众号配置
* @return \think\response\Json
* @author ljj
* @date 2022/2/16 10:09 上午
*/
public function setConfig()
{
$params = (new OfficialAccountSettingValidate())->post()->goCheck();
(new OfficialAccountSettingLogic())->setConfig($params);
return $this->success('操作成功',[],1,1);
}
}
@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\OpenSettingLogic;
use app\adminapi\validate\channel\OpenSettingValidate;
/**
* 微信开放平台
* Class AppSettingController
* @package app\adminapi\controller\setting\app
*/
class OpenSettingController extends BaseAdminController
{
/**
* @notes 获取微信开放平台设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:03
*/
public function getConfig()
{
$result = OpenSettingLogic::getConfig();
return $this->data($result);
}
/**
* @notes 微信开放平台设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:03
*/
public function setConfig()
{
$params = (new OpenSettingValidate())->post()->goCheck();
OpenSettingLogic::setConfig($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\channel;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\channel\WebPageSettingLogic;
use app\adminapi\validate\channel\WebPageSettingValidate;
/**
* H5设置控制器
* Class HFiveSettingController
* @package app\adminapi\controller\setting\h5
*/
class WebPageSettingController extends BaseAdminController
{
/**
* @notes 获取H5设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:36
*/
public function getConfig()
{
$result = WebPageSettingLogic::getConfig();
return $this->data($result);
}
/**
* @notes H5设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:36
*/
public function setConfig()
{
$params = (new WebPageSettingValidate())->post()->goCheck();
WebPageSettingLogic::setConfig($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,33 @@
<?php
namespace app\adminapi\controller\community;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\community\CommunityCommentLists;
use app\adminapi\logic\community\CommunityCommentLogic;
use app\adminapi\validate\community\CommunityCommentValidate;
class CommunityCommentController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new CommunityCommentLists());
}
public function updateStatus()
{
$params = (new CommunityCommentValidate())->post()->goCheck('status');
$result = CommunityCommentLogic::updateStatus($params);
if (true === $result) {
return $this->success('修改成功', [], 1, 1);
}
return $this->fail(CommunityCommentLogic::getError());
}
public function delete()
{
$params = (new CommunityCommentValidate())->post()->goCheck('delete');
CommunityCommentLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,70 @@
<?php
namespace app\adminapi\controller\community;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\community\CommunityPostLists;
use app\adminapi\logic\community\CommunityPostLogic;
use app\adminapi\validate\community\CommunityPostValidate;
class CommunityPostController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new CommunityPostLists());
}
public function detail()
{
$params = (new CommunityPostValidate())->goCheck('detail');
$result = CommunityPostLogic::detail($params);
return $this->data($result);
}
public function updateStatus()
{
$params = (new CommunityPostValidate())->post()->goCheck('status');
$result = CommunityPostLogic::updateStatus($params);
if (true === $result) {
return $this->success('修改成功', [], 1, 1);
}
return $this->fail(CommunityPostLogic::getError());
}
public function setTop()
{
$params = (new CommunityPostValidate())->post()->goCheck('top');
$result = CommunityPostLogic::setTop($params);
if (true === $result) {
return $this->success('设置成功', [], 1, 1);
}
return $this->fail(CommunityPostLogic::getError());
}
public function setHot()
{
$params = (new CommunityPostValidate())->post()->goCheck('hot');
$result = CommunityPostLogic::setHot($params);
if (true === $result) {
return $this->success('设置成功', [], 1, 1);
}
return $this->fail(CommunityPostLogic::getError());
}
public function setRecommend()
{
$params = (new CommunityPostValidate())->post()->goCheck('recommend');
$result = CommunityPostLogic::setRecommend($params);
if (true === $result) {
return $this->success('设置成功', [], 1, 1);
}
return $this->fail(CommunityPostLogic::getError());
}
public function delete()
{
$params = (new CommunityPostValidate())->post()->goCheck('delete');
CommunityPostLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,53 @@
<?php
namespace app\adminapi\controller\community;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\community\CommunityTagLists;
use app\adminapi\logic\community\CommunityTagLogic;
use app\adminapi\validate\community\CommunityTagValidate;
class CommunityTagController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new CommunityTagLists());
}
public function all()
{
$result = CommunityTagLogic::all();
return $this->data($result);
}
public function add()
{
$params = (new CommunityTagValidate())->post()->goCheck('add');
CommunityTagLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new CommunityTagValidate())->post()->goCheck('edit');
$result = CommunityTagLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(CommunityTagLogic::getError());
}
public function delete()
{
$params = (new CommunityTagValidate())->post()->goCheck('delete');
CommunityTagLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new CommunityTagValidate())->goCheck('detail');
$result = CommunityTagLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,32 @@
<?php
namespace app\adminapi\controller\crawler;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\crawler\CrawlErrorLogLists;
use app\common\model\CrawlErrorLog;
class CrawlErrorLogController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new CrawlErrorLogLists());
}
public function detail()
{
$id = $this->request->get('id/d', 0);
$result = CrawlErrorLog::findOrEmpty($id)->toArray();
return $this->data($result);
}
public function delete()
{
$ids = $this->request->post('ids/a', []);
if (empty($ids)) {
return $this->fail('请选择要删除的记录');
}
CrawlErrorLog::destroy($ids);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,160 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\crontab;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\crontab\CrontabLists;
use app\adminapi\logic\crontab\CrontabLogic;
use app\adminapi\validate\crontab\CrontabValidate;
/**
* 定时任务控制器
* Class CrontabController
* @package app\adminapi\controller\crontab
*/
class CrontabController extends BaseAdminController
{
/**
* @notes 定时任务列表
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:27
*/
public function lists()
{
return $this->dataLists(new CrontabLists());
}
/**
* @notes 添加定时任务
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:27
*/
public function add()
{
$params = (new CrontabValidate())->post()->goCheck('add');
$result = CrontabLogic::add($params);
if ($result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(CrontabLogic::getError());
}
/**
* @notes 查看定时任务详情
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:27
*/
public function detail()
{
$params = (new CrontabValidate())->goCheck('detail');
$result = CrontabLogic::detail($params);
return $this->data($result);
}
/**
* @notes 编辑定时任务
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:27
*/
public function edit()
{
$params = (new CrontabValidate())->post()->goCheck('edit');
$result = CrontabLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(CrontabLogic::getError());
}
/**
* @notes 删除定时任务
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:27
*/
public function delete()
{
$params = (new CrontabValidate())->post()->goCheck('delete');
$result = CrontabLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail('删除失败');
}
/**
* @notes 操作定时任务
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:28
*/
public function operate()
{
$params = (new CrontabValidate())->post()->goCheck('operate');
$result = CrontabLogic::operate($params);
if ($result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(CrontabLogic::getError());
}
/**
* @notes 手动执行定时任务
*/
public function run()
{
$params = (new CrontabValidate())->post()->goCheck('detail');
$result = CrontabLogic::run($params);
if ($result) {
return $this->success('执行完成', $result);
}
return $this->fail(CrontabLogic::getError());
}
/**
* @notes 执行日志列表
*/
public function logs()
{
$params = $this->request->get();
$result = CrontabLogic::logs($params);
return $this->success('', $result);
}
/**
* @notes 获取规则执行时间
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 14:28
*/
public function expression()
{
$params = (new CrontabValidate())->goCheck('expression');
$result = CrontabLogic::expression($params);
return $this->data($result);
}
}
@@ -0,0 +1,55 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\decorate;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\decorate\DecorateDataLogic;
use think\response\Json;
/**
* 装修-数据
* Class DataController
* @package app\adminapi\controller\decorate
*/
class DataController extends BaseAdminController
{
/**
* @notes 文章列表
* @return Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author mjf
* @date 2024/3/14 18:13
*/
public function article(): Json
{
$limit = $this->request->get('limit/d', 10);
$result = DecorateDataLogic::getArticleLists($limit);
return $this->success('获取成功', $result);
}
/**
* @notes pc设置
* @return Json
* @author mjf
* @date 2024/3/14 18:13
*/
public function pc(): Json
{
$result = DecorateDataLogic::pc();
return $this->data($result);
}
}
@@ -0,0 +1,61 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\decorate;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\decorate\DecoratePageLogic;
use app\adminapi\validate\decorate\DecoratePageValidate;
/**
* 装修页面
* Class DecoratePageController
* @package app\adminapi\controller\decorate
*/
class PageController extends BaseAdminController
{
/**
* @notes 获取装修修页面详情
* @return \think\response\Json
* @author 段誉
* @date 2022/9/14 18:43
*/
public function detail()
{
$id = $this->request->get('id/d');
$result = DecoratePageLogic::getDetail($id);
return $this->success('获取成功', $result);
}
/**
* @notes 保存装修配置
* @return \think\response\Json
* @author 段誉
* @date 2022/9/15 9:57
*/
public function save()
{
$params = (new DecoratePageValidate())->post()->goCheck();
$result = DecoratePageLogic::save($params);
if (false === $result) {
return $this->fail(DecoratePageLogic::getError());
}
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,58 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\decorate;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\decorate\DecorateTabbarLogic;
/**
* 装修-底部导航
* Class DecorateTabbarController
* @package app\adminapi\controller\decorate
*/
class TabbarController extends BaseAdminController
{
/**
* @notes 底部导航详情
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/9/7 16:39
*/
public function detail()
{
$data = DecorateTabbarLogic::detail();
return $this->success('', $data);
}
/**
* @notes 底部导航保存
* @return \think\response\Json
* @author 段誉
* @date 2022/9/6 9:58
*/
public function save()
{
$params = $this->request->post();
DecorateTabbarLogic::save($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,134 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\dept;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\dept\DeptLogic;
use app\adminapi\validate\dept\DeptValidate;
/**
* 部门管理控制器
* Class DeptController
* @package app\adminapi\controller\dept
*/
class DeptController extends BaseAdminController
{
/**
* @notes 部门列表
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:07
*/
public function lists()
{
$params = $this->request->get();
$result = DeptLogic::lists($params);
return $this->success('',$result);
}
/**
* @notes 上级部门
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/5/26 18:36
*/
public function leaderDept()
{
$result = DeptLogic::leaderDept();
return $this->success('',$result);
}
/**
* @notes 添加部门
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:40
*/
public function add()
{
$params = (new DeptValidate())->post()->goCheck('add');
DeptLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑部门
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function edit()
{
$params = (new DeptValidate())->post()->goCheck('edit');
$result = DeptLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(DeptLogic::getError());
}
/**
* @notes 删除部门
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function delete()
{
$params = (new DeptValidate())->post()->goCheck('delete');
DeptLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 获取部门详情
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function detail()
{
$params = (new DeptValidate())->goCheck('detail');
$result = DeptLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取部门数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 10:28
*/
public function all()
{
$result = DeptLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,118 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\dept;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\dept\JobsLists;
use app\adminapi\logic\dept\JobsLogic;
use app\adminapi\validate\dept\JobsValidate;
/**
* 岗位管理控制器
* Class JobsController
* @package app\adminapi\controller\dept
*/
class JobsController extends BaseAdminController
{
/**
* @notes 岗位列表
* @return \think\response\Json
* @author 段誉
* @date 2022/5/26 10:00
*/
public function lists()
{
return $this->dataLists(new JobsLists());
}
/**
* @notes 添加岗位
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:40
*/
public function add()
{
$params = (new JobsValidate())->post()->goCheck('add');
JobsLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑岗位
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function edit()
{
$params = (new JobsValidate())->post()->goCheck('edit');
$result = JobsLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(JobsLogic::getError());
}
/**
* @notes 删除岗位
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function delete()
{
$params = (new JobsValidate())->post()->goCheck('delete');
JobsLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 获取岗位详情
* @return \think\response\Json
* @author 段誉
* @date 2022/5/25 18:41
*/
public function detail()
{
$params = (new JobsValidate())->goCheck('detail');
$result = JobsLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取岗位数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 10:31
*/
public function all()
{
$result = JobsLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,57 @@
<?php
namespace app\adminapi\controller\device;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\device\DeviceLists;
use app\common\model\device\UserDevice;
/**
* 设备管理(只读)
*/
class DeviceController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new DeviceLists());
}
public function detail()
{
$id = (int)$this->request->get('id', 0);
if ($id <= 0) return $this->fail('参数错误');
$info = UserDevice::findOrEmpty($id)->toArray();
return $this->data($info);
}
public function delete()
{
$id = (int)$this->request->post('id', 0);
if ($id <= 0) return $this->fail('参数错误');
UserDevice::destroy($id);
return $this->success('删除成功', [], 1, 1);
}
/**
* 设备统计概览
*/
public function stats()
{
$total = UserDevice::count();
$platforms = UserDevice::field('platform, COUNT(*) as count')
->group('platform')
->select()
->toArray();
$today = strtotime(date('Y-m-d'));
$todayActive = UserDevice::where('last_at', '>=', $today)->count();
$todayNew = UserDevice::where('first_at', '>=', $today)->count();
return $this->data([
'total' => $total,
'today_active' => $todayActive,
'today_new' => $todayNew,
'platforms' => $platforms,
]);
}
}
@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\finance;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\finance\AccountLogLists;
use app\common\enum\user\AccountLogEnum;
/***
* 账户流水控制器
* Class AccountLogController
* @package app\adminapi\controller
*/
class AccountLogController extends BaseAdminController
{
/**
* @notes 账户流水明细
* @return \think\response\Json
* @author 段誉
* @date 2023/2/24 15:25
*/
public function lists()
{
return $this->dataLists(new AccountLogLists());
}
/**
* @notes 用户余额变动类型
* @return \think\response\Json
* @author 段誉
* @date 2023/2/24 15:25
*/
public function getUmChangeType()
{
return $this->data(AccountLogEnum::getUserMoneyChangeTypeDesc());
}
}
@@ -0,0 +1,72 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\finance;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\finance\RefundLogLists;
use app\adminapi\lists\finance\RefundRecordLists;
use app\adminapi\logic\finance\RefundLogic;
/**
* 退款控制器
* Class RefundController
* @package app\adminapi\controller\finance
*/
class RefundController extends BaseAdminController
{
/**
* @notes 退还统计
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2023/3/3 12:10
*/
public function stat()
{
$result = RefundLogic::stat();
return $this->success('', $result);
}
/**
* @notes 退款记录
* @return \think\response\Json
* @author 段誉
* @date 2023/3/1 9:47
*/
public function record()
{
return $this->dataLists(new RefundRecordLists());
}
/**
* @notes 退款日志
* @return \think\response\Json
* @author 段誉
* @date 2023/3/1 9:47
*/
public function log()
{
$recordId = $this->request->get('record_id', 0);
$result = RefundLogic::refundLog($recordId);
return $this->success('', $result);
}
}
@@ -0,0 +1,47 @@
<?php
namespace app\adminapi\controller\lottery;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\lottery\LotteryCategoryLists;
use app\adminapi\logic\lottery\LotteryCategoryLogic;
use app\adminapi\validate\lottery\LotteryCategoryValidate;
class LotteryCategoryController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new LotteryCategoryLists());
}
public function add()
{
$params = (new LotteryCategoryValidate())->post()->goCheck('add');
LotteryCategoryLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new LotteryCategoryValidate())->post()->goCheck('edit');
$result = LotteryCategoryLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(LotteryCategoryLogic::getError());
}
public function delete()
{
$params = (new LotteryCategoryValidate())->post()->goCheck('delete');
LotteryCategoryLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new LotteryCategoryValidate())->goCheck('detail');
$result = LotteryCategoryLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,30 @@
<?php
namespace app\adminapi\controller\lottery;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\lottery\LotteryDrawLists;
use app\adminapi\logic\lottery\LotteryDrawLogic;
use app\adminapi\validate\lottery\LotteryDrawValidate;
class LotteryDrawController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new LotteryDrawLists());
}
public function detail()
{
$params = (new LotteryDrawValidate())->goCheck('detail');
$result = LotteryDrawLogic::detail($params);
return $this->data($result);
}
public function delete()
{
$params = (new LotteryDrawValidate())->post()->goCheck('delete');
LotteryDrawLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,47 @@
<?php
namespace app\adminapi\controller\lottery;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\lottery\LotteryRegionLists;
use app\adminapi\logic\lottery\LotteryRegionLogic;
use app\adminapi\validate\lottery\LotteryRegionValidate;
class LotteryRegionController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new LotteryRegionLists());
}
public function add()
{
$params = (new LotteryRegionValidate())->post()->goCheck('add');
LotteryRegionLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new LotteryRegionValidate())->post()->goCheck('edit');
$result = LotteryRegionLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(LotteryRegionLogic::getError());
}
public function delete()
{
$params = (new LotteryRegionValidate())->post()->goCheck('delete');
LotteryRegionLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new LotteryRegionValidate())->goCheck('detail');
$result = LotteryRegionLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,40 @@
<?php
namespace app\adminapi\controller\match;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\match\LeagueLists;
use app\adminapi\logic\match\LeagueLogic;
use app\adminapi\validate\match\LeagueValidate;
class LeagueController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new LeagueLists());
}
public function detail()
{
$params = (new LeagueValidate())->goCheck('detail');
$result = LeagueLogic::detail($params);
return $this->data($result);
}
public function edit()
{
$params = (new LeagueValidate())->post()->goCheck('edit');
$result = LeagueLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(LeagueLogic::getError());
}
public function delete()
{
$params = (new LeagueValidate())->post()->goCheck('delete');
LeagueLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,40 @@
<?php
namespace app\adminapi\controller\match;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\match\MatchLists;
use app\adminapi\logic\match\MatchLogic;
use app\adminapi\validate\match\MatchValidate;
class MatchController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new MatchLists());
}
public function detail()
{
$params = (new MatchValidate())->goCheck('detail');
$result = MatchLogic::detail($params);
return $this->data($result);
}
public function edit()
{
$params = (new MatchValidate())->post()->goCheck('edit');
$result = MatchLogic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(MatchLogic::getError());
}
public function delete()
{
$params = (new MatchValidate())->post()->goCheck('delete');
MatchLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,70 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\notice;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\notice\NoticeSettingLists;
use app\adminapi\logic\notice\NoticeLogic;
use app\adminapi\validate\notice\NoticeValidate;
/**
* 通知控制器
* Class NoticeController
* @package app\adminapi\controller\notice
*/
class NoticeController extends BaseAdminController
{
/**
* @notes 查看通知设置列表
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:18
*/
public function settingLists()
{
return $this->dataLists(new NoticeSettingLists());
}
/**
* @notes 查看通知设置详情
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:18
*/
public function detail()
{
$params = (new NoticeValidate())->goCheck('detail');
$result = NoticeLogic::detail($params);
return $this->data($result);
}
/**
* @notes 通知设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:18
*/
public function set()
{
$params = $this->request->post();
$result = NoticeLogic::set($params);
if ($result) {
return $this->success('设置成功');
}
return $this->fail(NoticeLogic::getError());
}
}
@@ -0,0 +1,69 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\notice;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\notice\SmsConfigLogic;
use app\adminapi\validate\notice\SmsConfigValidate;
/**
* 短信配置控制器
* Class SmsConfigController
* @package app\adminapi\controller\notice
*/
class SmsConfigController extends BaseAdminController
{
/**
* @notes 获取短信配置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:36
*/
public function getConfig()
{
$result = SmsConfigLogic::getConfig();
return $this->data($result);
}
/**
* @notes 短信配置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:36
*/
public function setConfig()
{
$params = (new SmsConfigValidate())->post()->goCheck('setConfig');
SmsConfigLogic::setConfig($params);
return $this->success('操作成功',[],1,1);
}
/**
* @notes 查看短信配置详情
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 11:36
*/
public function detail()
{
$params = (new SmsConfigValidate())->goCheck('detail');
$result = SmsConfigLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,43 @@
<?php
namespace app\adminapi\controller\points;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\points\PointsProductLogic;
use app\adminapi\lists\points\PointsProductLists;
use app\adminapi\validate\points\PointsProductValidate;
class PointsProductController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PointsProductLists());
}
public function add()
{
$params = (new PointsProductValidate())->post()->goCheck('add');
PointsProductLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new PointsProductValidate())->post()->goCheck();
PointsProductLogic::edit($params);
return $this->success('编辑成功', [], 1, 1);
}
public function delete()
{
$params = (new PointsProductValidate())->post()->goCheck('delete');
PointsProductLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new PointsProductValidate())->goCheck('detail');
return $this->data(PointsProductLogic::detail($params));
}
}
@@ -0,0 +1,57 @@
<?php
namespace app\adminapi\controller\popup;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\popup\PopupLists;
use app\adminapi\logic\popup\PopupLogic;
use app\adminapi\validate\popup\PopupValidate;
/**
* 页面弹窗管理
*/
class PopupController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PopupLists());
}
public function add()
{
$params = (new PopupValidate())->post()->goCheck('add');
PopupLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new PopupValidate())->post()->goCheck('edit');
$result = PopupLogic::edit($params);
if ($result === true) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(PopupLogic::getError());
}
public function delete()
{
$params = (new PopupValidate())->post()->goCheck('delete');
PopupLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new PopupValidate())->goCheck('detail');
$result = PopupLogic::detail($params);
return $this->data($result);
}
public function updateStatus()
{
$params = (new PopupValidate())->post()->goCheck('status');
PopupLogic::updateStatus($params);
return $this->success('修改成功', [], 1, 1);
}
}
@@ -0,0 +1,70 @@
<?php
namespace app\adminapi\controller\popup;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\popup\PopupLogLists;
use app\common\model\popup\PagePopup;
use app\common\model\popup\PagePopupLog;
/**
* 弹窗操作日志
*/
class PopupLogController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PopupLogLists());
}
/**
* 弹窗统计概览
* GET /popup.popup_log/stats?popup_id=xxx
* 返回:[show, click, close, ctr, days[]]
*/
public function stats()
{
$popupId = (int)$this->request->get('popup_id', 0);
$where = [];
if ($popupId > 0) $where[] = ['popup_id', '=', $popupId];
$show = PagePopupLog::where($where)->where('action', 1)->count();
$click = PagePopupLog::where($where)->where('action', 2)->count();
$close = PagePopupLog::where($where)->where('action', 3)->count();
$ctr = $show > 0 ? round($click / $show * 100, 2) : 0;
// 最近 7 天每日统计
$days = [];
for ($i = 6; $i >= 0; $i--) {
$start = strtotime(date('Y-m-d', strtotime("-{$i} day")));
$end = $start + 86400;
$dShow = PagePopupLog::where($where)->where('action', 1)
->where('create_time', '>=', $start)
->where('create_time', '<', $end)->count();
$dClick = PagePopupLog::where($where)->where('action', 2)
->where('create_time', '>=', $start)
->where('create_time', '<', $end)->count();
$days[] = [
'date' => date('m-d', $start),
'show' => $dShow,
'click' => $dClick,
];
}
$popupName = '';
if ($popupId > 0) {
$popup = PagePopup::find($popupId);
$popupName = $popup ? (string)$popup['name'] : '';
}
return $this->data([
'popup_id' => $popupId,
'popup_name' => $popupName,
'show' => $show,
'click' => $click,
'close' => $close,
'ctr' => $ctr,
'days' => $days,
]);
}
}
@@ -0,0 +1,107 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\recharge;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\recharge\RechargeLists;
use app\adminapi\logic\recharge\RechargeLogic;
use app\adminapi\validate\recharge\RechargeRefundValidate;
/**
* 充值控制器
* Class RechargeController
* @package app\adminapi\controller\recharge
*/
class RechargeController extends BaseAdminController
{
/**
* @notes 获取充值设置
* @return \think\response\Json
* @author 段誉
* @date 2023/2/22 16:48
*/
public function getConfig()
{
$result = RechargeLogic::getConfig();
return $this->data($result);
}
/**
* @notes 充值设置
* @return \think\response\Json
* @author 段誉
* @date 2023/2/22 16:48
*/
public function setConfig()
{
$params = $this->request->post();
$result = RechargeLogic::setConfig($params);
if($result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(RechargeLogic::getError());
}
/**
* @notes 充值记录
* @return \think\response\Json
* @author 段誉
* @date 2023/2/24 16:01
*/
public function lists()
{
return $this->dataLists(new RechargeLists());
}
/**
* @notes 退款
* @return \think\response\Json
* @author 段誉
* @date 2023/2/28 17:29
*/
public function refund()
{
$params = (new RechargeRefundValidate())->post()->goCheck('refund');
$result = RechargeLogic::refund($params, $this->adminId);
list($flag, $msg) = $result;
if(false === $flag) {
return $this->fail($msg);
}
return $this->success($msg, [], 1, 1);
}
/**
* @notes 重新退款
* @return \think\response\Json
* @author 段誉
* @date 2023/2/28 19:17
*/
public function refundAgain()
{
$params = (new RechargeRefundValidate())->post()->goCheck('again');
$result = RechargeLogic::refundAgain($params, $this->adminId);
list($flag, $msg) = $result;
if(false === $flag) {
return $this->fail($msg);
}
return $this->success($msg, [], 1, 1);
}
}
@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\CustomerServiceLogic;
/**
* 客服设置
* Class CustomerServiceController
* @package app\adminapi\controller\setting
*/
class CustomerServiceController extends BaseAdminController
{
/**
* @notes 获取客服设置
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 12:05 下午
*/
public function getConfig()
{
$result = CustomerServiceLogic::getConfig();
return $this->data($result);
}
/**
* @notes 设置客服设置
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 12:11 下午
*/
public function setConfig()
{
$params = $this->request->post();
CustomerServiceLogic::setConfig($params);
return $this->success('设置成功', [], 1, 1);
}
}
@@ -0,0 +1,56 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\HotSearchLogic;
/**
* 热门搜索设置
* Class HotSearchController
* @package app\adminapi\controller\setting
*/
class HotSearchController extends BaseAdminController
{
/**
* @notes 获取热门搜索
* @return \think\response\Json
* @author 段誉
* @date 2022/9/5 19:00
*/
public function getConfig()
{
$result = HotSearchLogic::getConfig();
return $this->data($result);
}
/**
* @notes 设置热门搜索
* @return \think\response\Json
* @author 段誉
* @date 2022/9/5 19:00
*/
public function setConfig()
{
$params = $this->request->post();
$result = HotSearchLogic::setConfig($params);
if (false === $result) {
return $this->fail(HotSearchLogic::getError() ?: '系统错误');
}
return $this->success('设置成功', [], 1, 1);
}
}
@@ -0,0 +1,14 @@
<?php
namespace app\adminapi\controller\setting;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\setting\SmsUploadLists;
class SmsUploadController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new SmsUploadLists());
}
}
@@ -0,0 +1,86 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\StorageLogic;
use app\adminapi\validate\setting\StorageValidate;
use think\response\Json;
/**
* 存储设置控制器
* Class StorageController
* @package app\adminapi\controller\setting\shop
*/
class StorageController extends BaseAdminController
{
/**
* @notes 获取存储引擎列表
* @return Json
* @author 段誉
* @date 2022/4/20 16:13
*/
public function lists()
{
return $this->success('获取成功', StorageLogic::lists());
}
/**
* @notes 存储配置信息
* @return Json
* @author 段誉
* @date 2022/4/20 16:19
*/
public function detail()
{
$param = (new StorageValidate())->get()->goCheck('detail');
return $this->success('获取成功', StorageLogic::detail($param));
}
/**
* @notes 设置存储参数
* @return Json
* @author 段誉
* @date 2022/4/20 16:19
*/
public function setup()
{
$params = (new StorageValidate())->post()->goCheck('setup');
$result = StorageLogic::setup($params);
if (true === $result) {
return $this->success('配置成功', [], 1, 1);
}
return $this->success($result, [], 1, 1);
}
/**
* @notes 切换存储引擎
* @return Json
* @author 段誉
* @date 2022/4/20 16:19
*/
public function change()
{
$params = (new StorageValidate())->post()->goCheck('change');
StorageLogic::change($params);
return $this->success('切换成功', [], 1, 1);
}
}
@@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\TransactionSettingsLogic;
use app\adminapi\validate\setting\TransactionSettingsValidate;
/**
* 交易设置
* Class TransactionSettingsController
* @package app\adminapi\controller\setting
*/
class TransactionSettingsController extends BaseAdminController
{
/**
* @notes 获取交易设置
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 11:40 上午
*/
public function getConfig()
{
$result = TransactionSettingsLogic::getConfig();
return $this->data($result);
}
/**
* @notes 设置交易设置
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 11:50 上午
*/
public function setConfig()
{
$params = (new TransactionSettingsValidate())->post()->goCheck('setConfig');
TransactionSettingsLogic::setConfig($params);
return $this->success('操作成功',[],1,1);
}
}
@@ -0,0 +1,99 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\dict;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\setting\dict\DictDataLists;
use app\adminapi\logic\setting\dict\DictDataLogic;
use app\adminapi\validate\dict\DictDataValidate;
/**
* 字典数据
* Class DictDataController
* @package app\adminapi\controller\dictionary
*/
class DictDataController extends BaseAdminController
{
/**
* @notes 获取字典数据列表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 16:35
*/
public function lists()
{
return $this->dataLists(new DictDataLists());
}
/**
* @notes 添加字典数据
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 17:13
*/
public function add()
{
$params = (new DictDataValidate())->post()->goCheck('add');
DictDataLogic::save($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑字典数据
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 17:13
*/
public function edit()
{
$params = (new DictDataValidate())->post()->goCheck('edit');
DictDataLogic::save($params);
return $this->success('编辑成功', [], 1, 1);
}
/**
* @notes 删除字典数据
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 17:13
*/
public function delete()
{
$params = (new DictDataValidate())->post()->goCheck('id');
DictDataLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 获取字典详情
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 17:14
*/
public function detail()
{
$params = (new DictDataValidate())->goCheck('id');
$result = DictDataLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,116 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\dict;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\setting\dict\DictTypeLists;
use app\adminapi\logic\setting\dict\DictTypeLogic;
use app\adminapi\validate\dict\DictTypeValidate;
/**
* 字典类型
* Class DictTypeController
* @package app\adminapi\controller\dict
*/
class DictTypeController extends BaseAdminController
{
/**
* @notes 获取字典类型列表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 15:50
*/
public function lists()
{
return $this->dataLists(new DictTypeLists());
}
/**
* @notes 添加字典类型
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 16:24
*/
public function add()
{
$params = (new DictTypeValidate())->post()->goCheck('add');
DictTypeLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @notes 编辑字典类型
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 16:25
*/
public function edit()
{
$params = (new DictTypeValidate())->post()->goCheck('edit');
DictTypeLogic::edit($params);
return $this->success('编辑成功', [], 1, 1);
}
/**
* @notes 删除字典类型
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 16:25
*/
public function delete()
{
$params = (new DictTypeValidate())->post()->goCheck('delete');
DictTypeLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 获取字典详情
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 16:25
*/
public function detail()
{
$params = (new DictTypeValidate())->goCheck('detail');
$result = DictTypeLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取字典类型数据
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/13 10:46
*/
public function all()
{
$result = DictTypeLogic::getAllData();
return $this->data($result);
}
}
@@ -0,0 +1,69 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\pay;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\setting\pay\PayConfigLists;
use app\adminapi\logic\setting\pay\PayConfigLogic;
use app\adminapi\validate\setting\PayConfigValidate;
use think\response\Json;
/**
* 支付配置
* Class PayConfigController
* @package app\adminapi\controller\setting\pay
*/
class PayConfigController extends BaseAdminController
{
/**
* @notes 设置支付配置
* @return Json
* @author 段誉
* @date 2023/2/23 16:14
*/
public function setConfig(): Json
{
$params = (new PayConfigValidate())->post()->goCheck();
PayConfigLogic::setConfig($params);
return $this->success('设置成功', [], 1, 1);
}
/**
* @notes 获取支付配置
* @return Json
* @author 段誉
* @date 2023/2/23 16:14
*/
public function getConfig(): Json
{
$id = (new PayConfigValidate())->goCheck('get');
$result = PayConfigLogic::getConfig($id);
return $this->success('获取成功', $result);
}
/**
* @notes
* @return Json
* @author 段誉
* @date 2023/2/23 16:15
*/
public function lists(): Json
{
return $this->dataLists(new PayConfigLists());
}
}
@@ -0,0 +1,61 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\pay;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\pay\PayWayLogic;
/**
* 支付方式
* Class PayWayController
* @package app\adminapi\controller\setting\pay
*/
class PayWayController extends BaseAdminController
{
/**
* @notes 获取支付方式
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2023/2/23 16:27
*/
public function getPayWay()
{
$result = PayWayLogic::getPayWay();
return $this->success('获取成功',$result);
}
/**
* @notes 设置支付方式
* @return \think\response\Json
* @throws \Exception
* @author 段誉
* @date 2023/2/23 16:27
*/
public function setPayWay()
{
$params = $this->request->post();
$result = (new PayWayLogic())->setPayWay($params);
if (true !== $result) {
return $this->fail($result);
}
return $this->success('操作成功',[],1, 1);
}
}
@@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\system;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\system\CacheLogic;
/**
* 系统缓存
* Class CacheController
* @package app\adminapi\controller\setting\system
*/
class CacheController extends BaseAdminController
{
/**
* @notes 清除系统缓存
* @return \think\response\Json
* @author 段誉
* @date 2022/4/8 16:34
*/
public function clear()
{
CacheLogic::clear();
return $this->success('清除成功', [], 1, 1);
}
}
@@ -0,0 +1,38 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\system;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\setting\system\LogLists;
/**
* 系统日志
* Class LogController
* @package app\adminapi\controller\setting\system
*/
class LogController extends BaseAdminController
{
/**
* @notes 查看系统日志列表
* @return \think\response\Json
* @author ljj
* @date 2021/8/3 4:25 下午
*/
public function lists()
{
return $this->dataLists(new LogLists());
}
}
@@ -0,0 +1,42 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\system;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\system\SystemLogic;
/**
* 系统维护
* Class SystemController
* @package app\adminapi\controller\setting\system
*/
class SystemController extends BaseAdminController
{
/**
* @notes 获取系统环境信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/28 18:36
*/
public function info()
{
$result = SystemLogic::getInfo();
return $this->data($result);
}
}
@@ -0,0 +1,84 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\user;
use app\adminapi\{
controller\BaseAdminController,
logic\setting\user\UserLogic,
validate\setting\UserConfigValidate
};
/**
* 设置-用户设置控制器
* Class UserController
* @package app\adminapi\controller\config
*/
class UserController extends BaseAdminController
{
/**
* @notes 获取用户设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:08
*/
public function getConfig()
{
$result = (new UserLogic())->getConfig();
return $this->data($result);
}
/**
* @notes 设置用户设置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:08
*/
public function setConfig()
{
$params = (new UserConfigValidate())->post()->goCheck('user');
(new UserLogic())->setConfig($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 获取注册配置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:08
*/
public function getRegisterConfig()
{
$result = (new UserLogic())->getRegisterConfig();
return $this->data($result);
}
/**
* @notes 设置注册配置
* @return \think\response\Json
* @author 段誉
* @date 2022/3/29 10:08
*/
public function setRegisterConfig()
{
$params = (new UserConfigValidate())->post()->goCheck('register');
(new UserLogic())->setRegisterConfig($params);
return $this->success('操作成功', [], 1, 1);
}
}
@@ -0,0 +1,137 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\setting\web;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\setting\web\WebSettingLogic;
use app\adminapi\validate\setting\WebSettingValidate;
/**
* 网站设置
* Class WebSettingController
* @package app\adminapi\controller\setting
*/
class WebSettingController extends BaseAdminController
{
/**
* @notes 获取网站信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/28 15:44
*/
public function getWebsite()
{
$result = WebSettingLogic::getWebsiteInfo();
return $this->data($result);
}
/**
* @notes 设置网站信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/28 15:45
*/
public function setWebsite()
{
$params = (new WebSettingValidate())->post()->goCheck('website');
WebSettingLogic::setWebsiteInfo($params);
return $this->success('设置成功', [], 1, 1);
}
/**
* @notes 获取备案信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/28 16:10
*/
public function getCopyright()
{
$result = WebSettingLogic::getCopyright();
return $this->data($result);
}
/**
* @notes 设置备案信息
* @return \think\response\Json
* @author 段誉
* @date 2021/12/28 16:10
*/
public function setCopyright()
{
$params = $this->request->post();
$result = WebSettingLogic::setCopyright($params);
if (false === $result) {
return $this->fail(WebSettingLogic::getError() ?: '操作失败');
}
return $this->success('设置成功', [], 1, 1);
}
/**
* @notes 设置政策协议
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 11:00 上午
*/
public function setAgreement()
{
$params = $this->request->post();
WebSettingLogic::setAgreement($params);
return $this->success('设置成功', [], 1, 1);
}
/**
* @notes 获取政策协议
* @return \think\response\Json
* @author ljj
* @date 2022/2/15 11:16 上午
*/
public function getAgreement()
{
$result = WebSettingLogic::getAgreement();
return $this->data($result);
}
/**
* @notes 获取站点统计配置
* @return \think\response\Json
* @author yfdong
* @date 2024/09/20 22:24
*/
public function getSiteStatistics()
{
$result = WebSettingLogic::getSiteStatistics();
return $this->data($result);
}
/**
* @notes 获取站点统计配置
* @return \think\response\Json
* @author yfdong
* @date 2024/09/20 22:51
*/
public function setSiteStatistics()
{
$params = (new WebSettingValidate())->post()->goCheck('siteStatistics');
WebSettingLogic::setSiteStatistics($params);
return $this->success('设置成功', [], 1, 1);
}
}
@@ -0,0 +1,91 @@
<?php
namespace app\adminapi\controller\shortlink;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\shortlink\ShortLinkLists;
use app\adminapi\lists\shortlink\ShortLinkLogLists;
use app\common\model\ShortLink;
use app\common\service\ShortLinkPosterDataService;
use app\common\service\ShortLinkQrCodeService;
class ShortLinkController extends BaseAdminController
{
/**
* @notes 短链接列表
*/
public function lists()
{
return $this->dataLists(new ShortLinkLists());
}
/**
* @notes 短链接点击日志
*/
public function logLists()
{
return $this->dataLists(new ShortLinkLogLists());
}
/**
* @notes 删除短链接
*/
public function delete()
{
$id = $this->request->post('id/d', 0);
if (empty($id)) {
return $this->fail('参数错误');
}
ShortLink::destroy($id);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 重新生成二维码
*/
public function regenerateQrcode()
{
$id = $this->request->post('id/d', 0);
if (empty($id)) {
return $this->fail('参数错误');
}
$link = ShortLink::findOrEmpty($id);
if ($link->isEmpty()) {
return $this->fail('短链接不存在');
}
// 删除旧二维码与海报合成文件
$oldUri = (string) $link->getData('qrcode');
$candidates = [];
if ($oldUri !== '') {
$candidates[] = $oldUri;
}
// 同时清理可能的同名残留文件(海报版与纯二维码版)
$candidates[] = 'uploads/qrcode/shortlink/' . $link->code . '.png';
$candidates[] = 'uploads/qrcode/shortlink/' . $link->code . '_poster.png';
$candidates[] = 'uploads/qrcode/shortlink/' . $link->code . '.svg';
foreach (array_unique($candidates) as $uri) {
$abs = public_path() . $uri;
if (is_file($abs)) {
@unlink($abs);
}
}
$shortUrl = request()->domain() . '/s/' . $link->code;
$posterData = ShortLinkPosterDataService::build(
(string) $link->page_type,
$link->page_id,
(int) $link->user_id
);
$qrcode = ShortLinkQrCodeService::create($shortUrl, $link->code, $posterData['poster_image_uri'], $posterData);
$link->qrcode = $qrcode['uri'];
$link->save();
return $this->success('重新生成成功', [
'qrcode' => $qrcode['uri'],
'qrcode_url' => $qrcode['url'],
], 1, 1);
}
}
@@ -0,0 +1,206 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\tools;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\tools\DataTableLists;
use app\adminapi\lists\tools\GenerateTableLists;
use app\adminapi\logic\tools\GeneratorLogic;
use app\adminapi\validate\tools\EditTableValidate;
use app\adminapi\validate\tools\GenerateTableValidate;
/**
* 代码生成器控制器
* Class GeneratorController
* @package app\adminapi\controller\article
*/
class GeneratorController extends BaseAdminController
{
public array $notNeedLogin = ['download'];
/**
* @notes 获取数据库中所有数据表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/14 10:57
*/
public function dataTable()
{
return $this->dataLists(new DataTableLists());
}
/**
* @notes 获取已选择的数据表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/14 10:57
*/
public function generateTable()
{
return $this->dataLists(new GenerateTableLists());
}
/**
* @notes 选择数据表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 10:09
*/
public function selectTable()
{
$params = (new GenerateTableValidate())->post()->goCheck('select');
$result = GeneratorLogic::selectTable($params, $this->adminId);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 生成代码
* @return \think\response\Json
* @author 段誉
* @date 2022/6/23 19:08
*/
public function generate()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::generate($params);
if (false === $result) {
return $this->fail(GeneratorLogic::getError());
}
return $this->success('操作成功', $result, 1, 1);
}
/**
* @notes 下载文件
* @return \think\response\File|\think\response\Json
* @author 段誉
* @date 2022/6/24 9:51
*/
public function download()
{
$params = (new GenerateTableValidate())->goCheck('download');
$result = GeneratorLogic::download($params['file']);
if (false === $result) {
return $this->fail(GeneratorLogic::getError() ?: '下载失败');
}
return download($result, 'likeadmin-curd.zip');
}
/**
* @notes 预览代码
* @return \think\response\Json
* @author 段誉
* @date 2022/6/23 19:07
*/
public function preview()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::preview($params);
if (false === $result) {
return $this->fail(GeneratorLogic::getError());
}
return $this->data($result);
}
/**
* @notes 同步字段
* @return \think\response\Json
* @author 段誉
* @date 2022/6/17 15:22
*/
public function syncColumn()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::syncColumn($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 编辑表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 10:44
*/
public function edit()
{
$params = (new EditTableValidate())->post()->goCheck();
$result = GeneratorLogic::editTable($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 获取已选择的数据表详情
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 19:00
*/
public function detail()
{
$params = (new GenerateTableValidate())->goCheck('id');
$result = GeneratorLogic::getTableDetail($params);
return $this->success('', $result);
}
/**
* @notes 删除已选择的数据表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 19:00
*/
public function delete()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::deleteTable($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 获取模型
* @return \think\response\Json
* @author 段誉
* @date 2022/12/14 11:07
*/
public function getModels()
{
$result = GeneratorLogic::getAllModels();
return $this->success('', $result, 1, 1);
}
}
@@ -0,0 +1,112 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller\user;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\user\UserLists;
use app\adminapi\logic\user\UserLogic;
use app\adminapi\validate\user\AdjustUserMoney;
use app\adminapi\validate\user\UserValidate;
/**
* 用户控制器
* Class UserController
* @package app\adminapi\controller\user
*/
class UserController extends BaseAdminController
{
/**
* @notes 用户列表
* @return \think\response\Json
* @author 段誉
* @date 2022/9/22 16:16
*/
public function lists()
{
return $this->dataLists(new UserLists());
}
/**
* @notes 获取用户详情
* @return \think\response\Json
* @author 段誉
* @date 2022/9/22 16:34
*/
public function detail()
{
$params = (new UserValidate())->goCheck('detail');
$detail = UserLogic::detail($params['id']);
return $this->success('', $detail);
}
/**
* @notes 编辑用户信息
* @return \think\response\Json
* @author 段誉
* @date 2022/9/22 16:34
*/
public function edit()
{
$params = (new UserValidate())->post()->goCheck('setInfo');
UserLogic::setUserInfo($params);
return $this->success('操作成功', [], 1, 1);
}
/**
* @notes 调整用户余额
* @return \think\response\Json
* @author 段誉
* @date 2023/2/23 14:33
*/
public function adjustMoney()
{
$params = (new AdjustUserMoney())->post()->goCheck();
$res = UserLogic::adjustUserMoney($params);
if (true === $res) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail($res);
}
/**
* @notes 调整用户账户(余额/积分)
*/
public function adjustAccount()
{
$params = $this->request->post();
if (empty($params['user_id']) || empty($params['type']) || empty($params['action']) || empty($params['num'])) {
return $this->fail('参数不完整');
}
if (!in_array($params['type'], ['money', 'points'])) {
return $this->fail('调整类型错误');
}
if (!in_array($params['action'], [1, 2])) {
return $this->fail('操作类型错误');
}
if ($params['num'] <= 0) {
return $this->fail('调整数量必须大于零');
}
$res = UserLogic::adjustUserAccount($params);
if (true === $res) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail($res);
}
}
@@ -0,0 +1,43 @@
<?php
namespace app\adminapi\controller\vip;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\vip\VipLevelLogic;
use app\adminapi\lists\vip\VipLevelLists;
use app\adminapi\validate\vip\VipLevelValidate;
class VipLevelController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new VipLevelLists());
}
public function add()
{
$params = (new VipLevelValidate())->post()->goCheck('add');
VipLevelLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new VipLevelValidate())->post()->goCheck();
VipLevelLogic::edit($params);
return $this->success('编辑成功', [], 1, 1);
}
public function delete()
{
$params = (new VipLevelValidate())->post()->goCheck('delete');
VipLevelLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
public function detail()
{
$params = (new VipLevelValidate())->goCheck('detail');
return $this->data(VipLevelLogic::detail($params));
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
return [
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => ['app\adminapi\listener\OperationLog'],
'LogLevel' => [],
'LogWrite' => [],
]
];
@@ -0,0 +1,93 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\adminapi\http\middleware;
use app\common\{
cache\AdminAuthCache,
service\JsonService
};
use think\helper\Str;
/**
* 权限验证中间件
* Class AuthMiddleware
* @package app\adminapi\http\middleware
*/
class AuthMiddleware
{
/**
* @notes 权限验证
* @param $request
* @param \Closure $next
* @return mixed
* @author 令狐冲
* @date 2021/7/2 19:29
*/
public function handle($request, \Closure $next)
{
//不登录访问,无需权限验证
if ($request->controllerObject->isNotNeedLogin()) {
return $next($request);
}
if ($request->adminInfo['login_ip'] != request()->ip()) {
return JsonService::fail('ip地址发生变化,请重新登录', [], -1);
}
//系统默认超级管理员,无需权限验证
if (1 === $request->adminInfo['root']) {
return $next($request);
}
$adminAuthCache = new AdminAuthCache($request->adminInfo['admin_id']);
// 当前访问路径
$accessUri = strtolower($request->controller() . '/' . $request->action());
// 全部路由
$allUri = $this->formatUrl($adminAuthCache->getAllUri());
// 判断该当前访问的uri是否存在,不存在无需验证
if (!in_array($accessUri, $allUri)) {
return $next($request);
}
// 当前管理员拥有的路由权限
$AdminUris = $adminAuthCache->getAdminUri() ?? [];
$AdminUris = $this->formatUrl($AdminUris);
if (in_array($accessUri, $AdminUris)) {
return $next($request);
}
return JsonService::fail('权限不足,无法访问或操作');
}
/**
* @notes 格式化URL
* @param array $data
* @return array|string[]
* @author 段誉
* @date 2022/7/7 15:39
*/
public function formatUrl(array $data)
{
return array_map(function ($item) {
return strtolower(Str::camel($item));
}, $data);
}
}
@@ -0,0 +1,50 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\adminapi\http\middleware;
use app\common\service\JsonService;
/**
* 校验演示环境
* Class CheckDemoMiddleware
* @package app\adminapi\http\middleware
*/
class CheckDemoMiddleware
{
// 允许post的接口
protected $ablePost = [
'login/account',
'login/logout',
];
public function handle($request, \Closure $next)
{
if ($request->method() != 'POST') {
return $next($request);
}
$accessUri = strtolower($request->controller() . '/' . $request->action());
if (!in_array($accessUri, $this->ablePost) && env('project.demo_env')) {
return JsonService::fail('演示环境不支持修改数据,请下载源码本地部署体验');
}
return $next($request);
}
}
@@ -0,0 +1,114 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用,可去除界面版权logo
// | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
// | github下载:https://github.com/likeshop-github/likeadmin
// | 访问官网:https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\adminapi\http\middleware;
/**
* 演示环境数据加密
* Class DemoDataMiddleware
* @package app\adminapi\http\middleware
*/
class EncryDemoDataMiddleware
{
// 需要过滤的接口
protected $needCheck = [
// 存储配置
'setting.storage/detail',
// 短信配置
'notice.smsConfig/detail',
// 公众号配置
'channel.official_account_setting/getConfig',
// 小程序配置
'channel.mnp_settings/getConfig',
// 开放平台配置
'channel.open_setting/getConfig',
// 支付配置
'setting.pay.pay_config/getConfig',
];
// 可以排除字段
protected $excludeParams = [
'name',
'icon',
'image',
'qr_code',
'interface_version',
'merchant_type',
];
public function handle($request, \Closure $next)
{
$response = $next($request);
// 非需校验的接口 或者 未开启演示模式
$accessUri = strtolower($request->controller() . '/' . $request->action());
if (!in_array($accessUri, lower_uri($this->needCheck)) || !env('project.demo_env')) {
return $response;
}
// 非json数据
if (!method_exists($response, 'header') || !in_array('application/json; charset=utf-8', $response->getHeader())) {
return $response;
}
$data = $response->getData();
if (!is_array($data) || empty($data)) {
return $response;
}
foreach ($data['data'] as $key => $item) {
// 字符串
if (is_string($item)) {
$data['data'][$key] = $this->getEncryData($key, $item);
continue;
}
// 数组
if (is_array($item)) {
foreach ($item as $itemKey => $itemValue) {
$data['data'][$key][$itemKey] = $this->getEncryData($itemKey, $itemValue);
}
}
}
return $response->data($data);
}
/**
* @notes 加密配置
* @param $key
* @param $value
* @return mixed|string
* @author 段誉
* @date 2023/3/6 11:49
*/
protected function getEncryData($key, $value)
{
// 非隐藏字段
if (in_array($key, $this->excludeParams)) {
return $value;
}
// 隐藏字段
if (is_string($value)) {
return '******';
}
return $value;
}
}

Some files were not shown because too many files have changed in this diff Show More