first commit

This commit is contained in:
Your Name
2026-09-08 11:40:15 +08:00
commit a5353f7eb5
9568 changed files with 1646214 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
# ============================================
# 物流查询配置示例
# ============================================
#
# 快递100 API 配置(推荐)
# 注册地址:https://www.kuaidi100.com/
#
# 使用说明:
# 1. 注册快递100企业账号
# 2. 申请API接口权限
# 3. 获取 CUSTOMER 和 KEY
# 4. 将以下配置复制到 .env 文件中
# 5. 填写你的 CUSTOMER 和 KEY
# 6. 重启服务器
# ============================================
# 快递100 Customer(必填)
LOGISTICS_KUAIDI100_CUSTOMER=你的customer
# 快递100 Key(必填)
LOGISTICS_KUAIDI100_KEY=你的key
# 快递100 查询接口地址(可选,默认值如下)
LOGISTICS_KUAIDI100_QUERY_URL=https://poll.kuaidi100.com/poll/query.do
# 临时关闭快递100查询(可选,保留密钥但不使用)
# LOGISTICS_KUAIDI100_DISABLE=false
# ============================================
# 注意事项
# ============================================
#
# 1. 顺丰查询需要收件人手机号后4位验证
# 系统会自动从订单中获取手机号
#
# 2. 如果未配置快递100,系统会提供官网查询链接
# - 顺丰:https://www.sf-express.com/
# - 京东:https://www.jdl.com/
#
# 3. 支持的快递公司:
# - sf / shunfeng (顺丰速运)
# - jd (京东快递)
# - auto (自动识别)
#
# 4. 查询失败排查:
# - 检查运单号是否正确
# - 确认快递已揽收
# - 检查快递100账户余额
# - 顺丰需确认手机号正确
# ============================================
+6
View File
@@ -0,0 +1,6 @@
[prescription_ai]
ENABLE = true
BASE_URL = "https://ai.example.com/v1"
QWEN_API_KEY = "replace-on-server"
OPENAI_API_KEY = "replace-on-server"
TIMEOUT = 90
+23
View File
@@ -0,0 +1,23 @@
# 复制为 .env 中 [TRTC] 段落使用,或与现有 [TRTC] 合并(勿提交真实密钥到 Git)
#
# 云端合流录制 CreateCloudRecording 必填 CAM 密钥(与 SECRET_KEY 不是同一个):
# 腾讯云控制台 → 访问管理 → 访问密钥 → API 密钥管理
# https://console.cloud.tencent.com/cam/capi
# 子账号需具备 TRTC 云 API 权限(如 QcloudTRTCFullAccess
[TRTC]
SDK_APP_ID=
SECRET_KEY=
ENABLE=false
# 以下为 CAM(云 API)密钥,用于服务端发起/停止云端录制
# 注意:必须写 API_SECRET_ID / API_SECRET_KEY,不要写成 TRTC_API_SECRET_ID(在 [TRTC] 内会拼成 TRTC_TRTC_… 导致读不到)
API_SECRET_ID=
API_SECRET_KEY=
RECORDING_API_REGION=ap-guangzhou
# CreateCloudRecording.RoomIdType:留空或 auto=TUICall 纯数字房用 1、字符串房用 0;勿填 0 除非确定全为字符串房间(填错会导致录制一直 Idle)
# RECORDING_ROOM_ID_TYPE=
# cURL error 60SSL):从 https://curl.se/ca/cacert.pem 下载后填绝对路径,例如 D:\php\extras\ssl\cacert.pem;或放到 server 根目录命名为 cacert.pem
RECORDING_SSL_CAFILE=
+83
View File
@@ -0,0 +1,83 @@
APP_DEBUG = true
# 恩济药房 ERP:必须写在第一个 INI 分区之前
# 在 ej 后台创建商户后,将一次性返回的 app_key、app_secret、webhook_secret 填入下方
EJ_PHARMACY_ENABLED = false
EJ_PHARMACY_CATALOG_SYNC_ENABLED = false
EJ_PHARMACY_BASE_URL = "https://ej.example.com"
EJ_PHARMACY_APP_KEY = ""
EJ_PHARMACY_APP_SECRET = ""
EJ_PHARMACY_CALLBACK_SECRET = ""
# autoNSS cURL 自动使用 PHP OpenSSL;也可显式填写 openssl 或 curl。
EJ_PHARMACY_HTTP_TRANSPORT = "auto"
# CentOS/RHEL 7 可填写 /etc/pki/tls/certs/ca-bundle.crt;留空使用 PHP 默认 CA。
EJ_PHARMACY_CA_FILE = ""
EJ_PHARMACY_SUBMISSION_LEASE_SECONDS = 300
EJ_PHARMACY_CONNECT_TIMEOUT = 5
EJ_PHARMACY_REQUEST_TIMEOUT = 30
[APP]
DEFAULT_TIMEZONE = "Asia/Shanghai"
[DATABASE]
TYPE = "mysql"
HOSTNAME = "39.97.232.35"
DATABASE = "cs_zyt"
USERNAME = "cs_zyt"
PASSWORD = "3e64R8XcfJpbBhEf"
HOSTPORT = "3306"
CHARSET = "utf8mb4"
DEBUG = "1"
PREFIX = "zyt_"
[LANG]
default_lang = "zh-cn"
[PROJECT]
UNIQUE_IDENTIFICATION = "5687"
DEMO_ENV = ""
[WORK_WECHAT]
CORP_ID = "ww8623e34e60d48bec"
AGENT_ID = "1000031"
SECRET = "bLD-1HtnimxLuF1A-24-DeD0nBri0T_Dc1BzE6zbZb4"
CONTACT_SECRET = "aEvXpVIVoXWaFAYM-YCCMRGSO3l931PTcdPSTrAEgg8"
# true=强制非 root 绑定企微;false=关闭;也可在根级写 WORK_WECHAT_FORCE_BIND_LOGIN
FORCE_BIND_LOGIN = false
[TRTC]
SDK_APP_ID = "1600132918"
SECRET_KEY = "d93e9195b247e42e1cd707e450b678a90115c93877df91b1f2649778ca442c37"
ENABLE = "true"
[LANG]
default_lang = zh-cn
[PROJECT]
UNIQUE_IDENTIFICATION = likeadmin
# 演示环境
DEMO_ENV = false
; 处方业务订单:关联收款每笔金额须大于等于该值(元),业务订单金额也须大于等于该值;0=不校验
PRESCRIPTION_ORDER_LINK_PAY_MIN_AMOUNT = 0
# 物流轨迹(快递100):https://api.kuaidi100.com
; ThinkPHP .env 为 INI:下列建议写在分区声明之前;若误写在 trtc 分区内,config 已兼容
# 同时填 CUSTOMER、KEY 即启用;临时关闭设 LOGISTICS_KUAIDI100_DISABLE = true
LOGISTICS_KUAIDI100_CUSTOMER =
LOGISTICS_KUAIDI100_KEY =
# LOGISTICS_KUAIDI100_DISABLE = false
# LOGISTICS_KUAIDI100_QUERY_URL = https://poll.kuaidi100.com/poll/query.do
; 甘草药管家 SCM(须写在任意 [APP][trtc] 等分区之前;误放在 [trtc] 下会变成 TRTC_GANCAO_SCM_*,框架已兼容读取)
; 也可使用独立分区:[GANCAO_SCM] 下写 ENABLED=、GATEWAY_AK= 等(见 server/config/gancao_scm.php
; GANCAO_SCM_ENABLED = true
; GANCAO_SCM_GATEWAY_URL = https://oapi.igancao.com
; GANCAO_SCM_GATEWAY_AK =
; GANCAO_SCM_GATEWAY_SK =
; 业务层(MAKE_TOKEN);常与 GANCAO_SCM_GATEWAY_* 不同,勿默认留空复用错误 sk
; GANCAO_SCM_BIZ_AK =
; GANCAO_SCM_BIZ_SK =
; GANCAO_SCM_CALLBACK_URL = https://你的公网域名/gancao/recipel-notify
; GANCAO_SCM_CRADLE_STORE = 甄养堂互联网医院
; GANCAO_SCM_DF_ID = 101
; GANCAO_SCM_EXPRESS_TYPE = general
+10
View File
@@ -0,0 +1,10 @@
/.idea
/.vscode
*.log
/.env
/cacert.pem
/public/uploads/*
!/public/uploads/index.html
/runtime/*
!/runtime/index.html
/config/install.lock
+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
+1
View File
@@ -0,0 +1 @@
open_basedir=/www/wwwroot/zyt/server/:/tmp/
+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.
+56
View File
@@ -0,0 +1,56 @@
ThinkPHP 6.0
===============
> 运行环境要求PHP7.1+,兼容PHP8.0。
[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
## 安装
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 文档
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)
+1
View File
@@ -0,0 +1 @@
deny from all
+23
View File
@@ -0,0 +1,23 @@
<?php
declare (strict_types = 1);
namespace app;
use app\common\service\TrtcCloudRecordingService;
use think\Service;
/**
* 应用服务类
*/
class AppService extends Service
{
public function register()
{
// 服务注册
}
public function boot()
{
TrtcCloudRecordingService::applyRecordingSslCaBundleEarly();
}
}
+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,25 @@
<?php
namespace app\adminapi\controller;
use app\api\logic\ChatNotifyLogic;
/**
* 聊天通知接口(管理端-医生)
*/
class ChatController extends BaseAdminController
{
/**
* 获取当前医生的患者打开会话通知
* 轮询接口,获取后即消费
*/
public function notifications()
{
$doctorId = $this->adminId;
if ($doctorId <= 0) {
return $this->success('', []);
}
$list = ChatNotifyLogic::getNotifies($doctorId, true);
return $this->success('', $list);
}
}
@@ -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,122 @@
<?php
namespace app\adminapi\controller;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\FanLists;
use app\adminapi\logic\FanLogic;
use app\adminapi\validate\FanValidate;
use app\adminapi\validate\FanVisitRecordValidate;
class FanController extends BaseAdminController
{
/**
* @notes 粉丝列表
*/
public function lists()
{
return $this->dataLists(new FanLists());
}
/**
* @notes 添加粉丝
*/
public function add()
{
$params = (new FanValidate())->post()->goCheck('add');
$params['creator_id'] = $this->adminId;
$params['creator_name'] = $this->adminInfo['name'] ?? '';
$result = FanLogic::add($params);
if ($result) {
return $this->success('添加成功', ['id' => $result], 1, 1);
}
return $this->fail(FanLogic::getError());
}
/**
* @notes 编辑粉丝
*/
public function edit()
{
$params = (new FanValidate())->post()->goCheck('edit');
$result = FanLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(FanLogic::getError());
}
/**
* @notes 删除粉丝
*/
public function delete()
{
$params = (new FanValidate())->post()->goCheck('id');
$result = FanLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(FanLogic::getError());
}
/**
* @notes 粉丝详情
*/
public function detail()
{
$params = (new FanValidate())->goCheck('id');
$result = FanLogic::detail($params);
return $this->data($result);
}
/**
* @notes 回访记录列表
*/
public function visitRecordLists()
{
$params = $this->request->get();
$result = FanLogic::visitRecordLists($params);
return $this->success('', $result);
}
/**
* @notes 添加回访记录
*/
public function addVisitRecord()
{
$params = (new FanVisitRecordValidate())->post()->goCheck('add');
$params['operator_id'] = $this->adminId;
$params['operator_name'] = $this->adminInfo['name'] ?? '';
$result = FanLogic::addVisitRecord($params);
if ($result) {
return $this->success('添加成功', ['id' => $result], 1, 1);
}
return $this->fail(FanLogic::getError());
}
/**
* @notes 编辑回访记录
*/
public function editVisitRecord()
{
$params = (new FanVisitRecordValidate())->post()->goCheck('edit');
$result = FanLogic::editVisitRecord($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(FanLogic::getError());
}
/**
* @notes 删除回访记录
*/
public function deleteVisitRecord()
{
$params = (new FanVisitRecordValidate())->post()->goCheck('id');
$result = FanLogic::deleteVisitRecord($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(FanLogic::getError());
}
}
@@ -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,164 @@
<?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', 'workWechatConfig', 'workWechatLogin', 'checkDbColumn', 'changeFirstPassword'];
/**
* @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 获取企业微信登录配置(前端构造OAuth URL/扫码用)
*/
public function workWechatConfig()
{
$corpId = env('work_wechat.corp_id', '');
$agentId = env('work_wechat.agent_id', '');
if (empty($corpId) || empty($agentId)) {
return $this->data([
'enabled' => false,
'require_bind_nonroot' => false,
'force_bind_login' => LoginLogic::isForceBindWorkWechatFromEnv(),
]);
}
$oauthOk = LoginLogic::isWorkWechatOAuthConfigured();
$forceBind = LoginLogic::isForceBindWorkWechatFromEnv();
return $this->data([
'enabled' => true,
'corp_id' => $corpId,
'agent_id' => $agentId,
/** 与 .env FORCE_BIND_LOGIN 一致:为 true 且 OAuth 配全时非 root 须先绑定 */
'require_bind_nonroot' => $forceBind && $oauthOk,
'force_bind_login' => $forceBind,
]);
}
/**
* @notes 企业微信授权登录(用 code 换 token
*/
public function workWechatLogin()
{
$code = $this->request->post('code', '');
if (empty($code)) {
return $this->fail('缺少授权code');
}
$terminal = $this->request->post('terminal', 1);
$result = (new LoginLogic())->workWechatLogin([
'code' => $code,
'terminal' => $terminal,
]);
if ($result === false) {
return $this->fail(LoginLogic::getError());
}
return $this->data($result);
}
/**
* @notes 临时调试:检查 admin 表是否有 work_wechat_userid 列(确认后请删除此方法)
*/
public function checkDbColumn()
{
$dbName = env('database.database', '');
$prefix = env('database.prefix', '');
$tableName = $prefix . 'admin';
$columns = \think\facade\Db::query("SHOW COLUMNS FROM `{$tableName}` LIKE 'work_wechat_userid'");
return $this->data([
'database' => $dbName,
'table' => $tableName,
'column_exists' => !empty($columns),
'columns_result' => $columns,
]);
}
/**
* @notes 首次登录修改密码
* @return \think\response\Json
*/
public function changeFirstPassword()
{
$password = $this->request->post('password', '');
$passwordConfirm = $this->request->post('password_confirm', '');
if (empty($password)) {
return $this->fail('请输入新密码');
}
if (strlen($password) < 6) {
return $this->fail('密码长度不能少于6位');
}
if ($password !== $passwordConfirm) {
return $this->fail('两次输入的密码不一致');
}
$token = $this->request->header('token');
if (empty($token)) {
return $this->fail('请先登录');
}
$result = (new LoginLogic())->changeFirstPassword($token, $password);
if ($result === false) {
return $this->fail(LoginLogic::getError());
}
return $this->success('密码修改成功');
}
/**
* @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,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;
use app\common\service\DirectUploadService;
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, $this->adminId);
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, $this->adminId);
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, $this->adminId);
return $this->success('上传成功', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 浏览器直传 OSS - 签发 STS 临时凭证
* @return Json
*/
public function ossCredentials()
{
$type = trim((string)$this->request->post('type', 'video'));
try {
$result = DirectUploadService::issueCredentials($type);
return $this->success('ok', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 浏览器直传 OSS - 上传完成回执(写 file 表 + HEAD 校验)
* @return Json
*/
public function ossConfirm()
{
try {
$result = DirectUploadService::confirm([
'type' => trim((string)$this->request->post('type', 'video')),
'key' => trim((string)$this->request->post('key', '')),
'name' => trim((string)$this->request->post('name', '')),
'size' => (int)$this->request->post('size', 0),
'content_type' => trim((string)$this->request->post('content_type', '')),
'cid' => (int)$this->request->post('cid', 0),
'admin_id' => $this->adminId,
]);
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,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,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
// +----------------------------------------------------------------------
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');
ArticleLogic::add($params);
return $this->success('添加成功', [], 1, 1);
}
/**
* @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());
}
}
@@ -0,0 +1,192 @@
<?php
namespace app\adminapi\controller\asset;
use app\adminapi\controller\BaseAdminController;
use app\common\model\AssetResource;
use app\common\model\AssetUserResource;
use think\facade\Db;
class AssetResourceController extends BaseAdminController
{
/**
* @notes 资源列表
*/
public function lists()
{
$pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15);
$type = $this->request->get('type');
$title = $this->request->get('title', '');
$startTime = $this->request->get('start_time');
$endTime = $this->request->get('end_time');
$where = [];
if ($type) {
$where[] = ['type', '=', $type];
}
if ($title) {
$where[] = ['title', 'like', '%' . $title . '%'];
}
if ($startTime) {
$where[] = ['create_time', '>=', strtotime($startTime)];
}
if ($endTime) {
$where[] = ['create_time', '<=', strtotime($endTime) + 86399];
}
$count = AssetResource::where($where)->count();
$lists = AssetResource::with('users')
->where($where)
->order('id', 'desc')
->page($pageNo, $pageSize)
->select();
return $this->data([
'count' => $count,
'lists' => $lists,
'page_no' => $pageNo,
'page_size' => $pageSize,
]);
}
/**
* @notes 添加资源及分配账号
*/
public function add()
{
$params = $this->request->post();
$type = $params['type'] ?? 0;
$title = trim((string)($params['title'] ?? ''));
// 兼容单图(字符串)与多图批量上传(数组)
$fileUrl = $params['file_url'] ?? '';
if (is_array($fileUrl)) {
$fileUrls = array_values(array_filter($fileUrl, fn($v) => trim((string)$v) !== ''));
} else {
$fileUrls = trim((string)$fileUrl) !== '' ? [$fileUrl] : [];
}
if (empty($type) || $title === '' || empty($fileUrls)) {
return $this->fail('请填写完整的资源信息');
}
// 仅图片支持批量;视频/语音只取首个
if ($type != 1) {
$fileUrls = [$fileUrls[0]];
}
$multi = count($fileUrls) > 1;
Db::startTrans();
try {
$createdIds = [];
$index = 0;
foreach ($fileUrls as $url) {
$index++;
$resource = AssetResource::create([
'type' => $type,
'title' => $multi ? $title . '_' . $index : $title,
'file_url' => $url,
'cover_url' => $params['cover_url'] ?? '',
]);
// 绑定用户
if (!empty($params['user_ids']) && is_array($params['user_ids'])) {
$userResources = [];
foreach ($params['user_ids'] as $userId) {
$userResources[] = [
'user_id' => $userId,
'resource_id' => $resource->id,
'create_time' => time(),
];
}
(new AssetUserResource())->saveAll($userResources);
}
$createdIds[] = $resource->id;
}
Db::commit();
return $this->success('添加并分配成功', ['ids' => $createdIds]);
} catch (\Exception $e) {
Db::rollback();
return $this->fail('操作失败: ' . $e->getMessage());
}
}
/**
* @notes 编辑资源(修改标题、关联账号)
*/
public function edit()
{
$params = $this->request->post();
$id = $params['id'] ?? 0;
if (empty($id)) {
return $this->fail('缺少参数');
}
$resource = AssetResource::find($id);
if (!$resource) {
return $this->fail('资源不存在');
}
Db::startTrans();
try {
// 更新标题
if (!empty($params['title'])) {
$resource->title = $params['title'];
$resource->save();
}
// 重新绑定用户(先删后加)
if (isset($params['user_ids'])) {
AssetUserResource::where('resource_id', $id)->delete();
$userIds = is_array($params['user_ids']) ? $params['user_ids'] : [];
if (!empty($userIds)) {
$userResources = [];
foreach ($userIds as $userId) {
$userResources[] = [
'user_id' => $userId,
'resource_id' => $id,
'create_time' => time(),
];
}
(new AssetUserResource())->saveAll($userResources);
}
}
Db::commit();
return $this->success('编辑成功');
} catch (\Exception $e) {
Db::rollback();
return $this->fail('操作失败: ' . $e->getMessage());
}
}
/**
* @notes 删除资源
*/
public function delete()
{
$id = $this->request->post('id');
$ids = is_array($id) ? $id : [$id];
$ids = array_values(array_unique(array_filter(array_map('intval', $ids), static function (int $item): bool {
return $item > 0;
})));
if (empty($ids)) {
return $this->fail('缺少参数');
}
Db::startTrans();
try {
AssetResource::destroy($ids);
AssetUserResource::whereIn('resource_id', $ids)->delete();
Db::commit();
return $this->success('删除成功');
} catch (\Exception $e) {
Db::rollback();
return $this->fail('删除失败');
}
}
}
@@ -0,0 +1,121 @@
<?php
namespace app\adminapi\controller\asset;
use app\adminapi\controller\BaseAdminController;
use app\common\model\AssetUser;
class AssetUserController extends BaseAdminController
{
/**
* @notes 账号列表
*/
public function lists()
{
$pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15);
$phone = $this->request->get('phone', '');
$where = [];
if ($phone) {
$where[] = ['phone', 'like', '%' . $phone . '%'];
}
$count = AssetUser::where($where)->count();
$lists = AssetUser::where($where)
->order('id', 'desc')
->page($pageNo, $pageSize)
->select();
return $this->data([
'count' => $count,
'lists' => $lists,
'page_no' => $pageNo,
'page_size' => $pageSize,
]);
}
/**
* @notes 添加账号
*/
public function add()
{
$params = $this->request->post();
if (empty($params['phone'])) {
return $this->fail('手机号不能为空');
}
$exist = AssetUser::where('phone', $params['phone'])->find();
if ($exist) {
return $this->fail('手机号已存在');
}
// Default password 123456
$password = empty($params['password']) ? '123456' : $params['password'];
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$user = AssetUser::create([
'phone' => $params['phone'],
'password' => $passwordHash,
'status' => $params['status'] ?? 1,
'remark' => trim((string)($params['remark'] ?? '')),
]);
return $this->success('添加成功', ['id' => $user->id]);
}
/**
* @notes 编辑账号
*/
public function edit()
{
$params = $this->request->post();
if (empty($params['id'])) {
return $this->fail('缺少参数');
}
$user = AssetUser::find($params['id']);
if (!$user) {
return $this->fail('账号不存在');
}
if (!empty($params['phone']) && $params['phone'] != $user->phone) {
$exist = AssetUser::where('phone', $params['phone'])->find();
if ($exist) {
return $this->fail('手机号已存在');
}
$user->phone = $params['phone'];
}
if (!empty($params['password'])) {
$user->password = password_hash($params['password'], PASSWORD_DEFAULT);
}
if (isset($params['status'])) {
$user->status = $params['status'];
}
if (array_key_exists('remark', $params)) {
$user->remark = trim((string)$params['remark']);
}
$user->save();
return $this->success('修改成功');
}
/**
* @notes 删除账号
*/
public function delete()
{
$id = $this->request->post('id');
if (empty($id)) {
return $this->fail('缺少参数');
}
AssetUser::destroy($id);
// 也需要删除关联的资源记录
\app\common\model\AssetUserResource::where('user_id', $id)->delete();
return $this->success('删除成功');
}
}
@@ -0,0 +1,214 @@
<?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\logic\LoginLogic;
use app\adminapi\validate\auth\editSelfValidate;
use app\common\cache\AdminTokenCache;
use app\common\model\auth\Admin;
/**
* 管理员控制器
* 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);
}
/**
* @notes 企业微信扫码绑定(用 code 换取 userid 并保存到当前管理员)
*/
public function bindWorkWechat()
{
$code = $this->request->post('code', '');
if (empty($code)) {
return $this->fail('缺少授权code');
}
$corpId = env('work_wechat.corp_id', '');
$secret = env('work_wechat.secret', '');
if (empty($corpId) || empty($secret)) {
return $this->fail('企业微信未配置');
}
$accessToken = LoginLogic::getWorkWechatAccessTokenStatic($corpId, $secret);
if (!$accessToken) {
return $this->fail('获取企业微信凭证失败');
}
$url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token={$accessToken}&code={$code}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$result = curl_exec($ch);
curl_close($ch);
$response = json_decode($result, true);
if (!$response || ($response['errcode'] ?? -1) != 0) {
return $this->fail('企业微信授权失败: ' . ($response['errmsg'] ?? '未知错误'));
}
$wxUserId = LoginLogic::workWechatUserIdFromAuthResponse($response);
if ($wxUserId === '') {
$hasOpenId = trim((string) ($response['openid'] ?? $response['OpenId'] ?? '')) !== '';
return $this->fail(
$hasOpenId
? '当前扫码账号非企业通讯录成员(或尚未同步到通讯录),无法绑定。请使用已在企业微信通讯录中的成员扫码,或联系管理员将你加入企业后再试'
: '未获取到企业微信成员 userid。请确认 .env 中 work_wechat.secret 为「该自建应用」的 Secret(与 agent_id 对应),且绑定页完整 URL 已加入应用可信域名'
);
}
// 检查是否已被其他管理员绑定
$exists = Admin::where('work_wechat_userid', $wxUserId)
->where('id', '<>', $this->adminId)
->find();
if ($exists) {
return $this->fail('该企业微信账号已被其他管理员绑定');
}
$affected = Admin::where('id', $this->adminId)->update(['work_wechat_userid' => $wxUserId]);
if ($affected === 0) {
return $this->fail('保存绑定失败,请确认账号有效后重试');
}
$token = $this->request->header('token');
if ($token) {
(new AdminTokenCache())->deleteAdminInfo($token);
}
return $this->success('绑定成功', ['work_wechat_userid' => $wxUserId]);
}
/**
* @notes 解绑企业微信
*/
public function unbindWorkWechat()
{
Admin::where('id', $this->adminId)->update(['work_wechat_userid' => '']);
return $this->success('解绑成功');
}
}
@@ -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,135 @@
<?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 获取规则执行时间
* @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,138 @@
<?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()
{
$apply = (int) ($this->request->get('apply_data_scope', 0));
$result = $apply === 1
? DeptLogic::getAllDataScoped($this->adminId, $this->adminInfo)
: 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,198 @@
<?php
namespace app\adminapi\controller\doctor;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\doctor\AppointmentLists;
use app\adminapi\logic\doctor\AppointmentLogic;
use app\adminapi\logic\doctor\DoctorNoteLogic;
use app\adminapi\validate\doctor\AppointmentValidate;
/**
* 医生预约控制器
* Class AppointmentController
* @package app\adminapi\controller\doctor
*/
class AppointmentController extends BaseAdminController
{
/**
* @notes 获取可用时间段
* @return \think\response\Json
*/
public function availableSlots()
{
$params = (new AppointmentValidate())->goCheck('availableSlots');
$result = AppointmentLogic::getAvailableSlots($params);
return $this->data($result);
}
/**
* @notes 创建预约
* @return \think\response\Json
*/
public function create()
{
$params = (new AppointmentValidate())->post()->goCheck('create');
$params['assistant_id'] = $this->adminId;
$result = AppointmentLogic::create($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('预约成功', $result);
}
/**
* @notes 取消预约
* @return \think\response\Json
*/
public function cancel()
{
$params = (new AppointmentValidate())->post()->goCheck('cancel');
$result = AppointmentLogic::cancel($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('取消成功');
}
/**
* @notes 预约列表
* @return \think\response\Json
*/
public function lists()
{
return $this->dataLists(new AppointmentLists());
}
/**
* 后台编辑挂号记录(消费者处方-挂号列表等,perms: doctor.appointment/edit
*/
public function edit()
{
$params = (new AppointmentValidate())->post()->goCheck('adminEdit');
$post = $this->request->post();
if (array_key_exists('assistant_id', $post)) {
$params['assistant_id'] = $post['assistant_id'];
}
$result = AppointmentLogic::adminEdit($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('保存成功');
}
/** 批量修改挂号渠道来源(消费者处方-挂号列表) */
public function batchEditChannel()
{
$params = (new AppointmentValidate())->post()->goCheck('batchEditChannel');
$post = $this->request->post();
if (\array_key_exists('channel_source_detail', $post)) {
$params['channel_source_detail'] = $post['channel_source_detail'];
}
$result = AppointmentLogic::adminBatchEditChannel($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success((string) ($result['msg'] ?? '操作成功'), $result);
}
/**
* @notes 预约详情
* @return \think\response\Json
*/
public function detail()
{
$params = (new AppointmentValidate())->goCheck('detail');
$result = AppointmentLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取医生可用号源数
* @return \think\response\Json
*/
public function doctorAvailability()
{
$doctorId = $this->request->get('doctor_id');
$date = $this->request->get('date');
if (!$doctorId || !$date) {
return $this->fail('参数错误');
}
$availableCount = AppointmentLogic::getDoctorAvailability($doctorId, $date);
return $this->data(['available_count' => $availableCount]);
}
/**
* @notes 完成预约
* @return \think\response\Json
*/
public function complete()
{
$params = (new AppointmentValidate())->post()->goCheck('complete');
$result = AppointmentLogic::complete($params);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('操作成功');
}
/**
* @notes 接诊台聚合详情(患者信息 + 诊单病例 + 血糖血压记录)
* @return \think\response\Json
*/
public function reception()
{
$params = (new AppointmentValidate())->goCheck('reception');
$result = AppointmentLogic::reception($params);
return $this->data($result);
}
/**
* @notes 通知接诊医助(发企业微信)
* @return \think\response\Json
*/
public function notifyAssistant()
{
$params = (new AppointmentValidate())->post()->goCheck('notifyAssistant');
$result = AppointmentLogic::notifyAssistant((int) $params['id']);
if (empty($result['ok'])) {
return $this->fail($result['message'] ?? '通知失败');
}
return $this->success('通知已发送');
}
public function addDoctorNote()
{
$params = (new AppointmentValidate())->post()->goCheck('addDoctorNote');
$params['doctor_id'] = $this->adminId;
$result = DoctorNoteLogic::addOrAppend($params);
if ($result === false) {
return $this->fail(DoctorNoteLogic::getError());
}
return $this->success('保存成功');
}
public function doctorNotes()
{
$params = (new AppointmentValidate())->goCheck('doctorNotes');
return $this->data(DoctorNoteLogic::getByDiagnosis((int) $params['diagnosis_id']));
}
public function deleteDoctorNoteImage()
{
$params = (new AppointmentValidate())->post()->goCheck('deleteDoctorNoteImage');
$result = DoctorNoteLogic::deleteImage(
(int) $params['note_id'],
$params['image_type'],
$params['image_path']
);
if ($result === false) {
return $this->fail(DoctorNoteLogic::getError());
}
return $this->success('删除成功');
}
}
@@ -0,0 +1,68 @@
<?php
namespace app\adminapi\controller\doctor;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\doctor\MedicineLists;
use app\adminapi\logic\doctor\MedicineLogic;
use app\adminapi\validate\doctor\MedicineValidate;
/**
* 药品库控制器
*/
class MedicineController extends BaseAdminController
{
/**
* 药品列表
*/
public function lists()
{
return $this->dataLists(new MedicineLists());
}
/**
* 添加药品
*/
public function add()
{
$params = (new MedicineValidate())->post()->goCheck('add');
$result = MedicineLogic::add($params);
if ($result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(MedicineLogic::getError());
}
/**
* 编辑药品
*/
public function edit()
{
$params = (new MedicineValidate())->post()->goCheck('edit');
$result = MedicineLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(MedicineLogic::getError());
}
/**
* 删除药品
*/
public function delete()
{
$params = (new MedicineValidate())->post()->goCheck('delete');
MedicineLogic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* 药品详情
*/
public function detail()
{
$params = (new MedicineValidate())->goCheck('detail');
$result = MedicineLogic::detail($params);
return $this->data($result);
}
}
@@ -0,0 +1,95 @@
<?php
namespace app\adminapi\controller\doctor;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\doctor\RosterLists;
use app\adminapi\logic\doctor\RosterLogic;
use app\adminapi\validate\doctor\RosterValidate;
/**
* 医生排班控制器
* Class RosterController
* @package app\adminapi\controller\doctor
*/
class RosterController extends BaseAdminController
{
/**
* @notes 排班列表
* @return \think\response\Json
*/
public function lists()
{
return $this->dataLists(new RosterLists());
}
/**
* @notes 保存排班(新增或更新)
* @return \think\response\Json
*/
public function save()
{
$post = request()->post();
$defaults = [];
if (empty($post['period'])) {
$defaults['period'] = 'segment';
}
$params = (new RosterValidate())->post()->goCheck('save', $defaults);
$result = RosterLogic::save($params);
if ($result === false) {
return $this->fail(RosterLogic::getError());
}
return $this->success('保存成功', $result);
}
/**
* @notes 删除排班
* @return \think\response\Json
*/
public function delete()
{
$params = (new RosterValidate())->post()->goCheck('delete');
RosterLogic::delete($params);
return $this->success('删除成功');
}
/**
* @notes 排班详情
* @return \think\response\Json
*/
public function detail()
{
$params = (new RosterValidate())->goCheck('detail');
$result = RosterLogic::detail($params);
return $this->data($result);
}
/**
* @notes 批量保存排班
* @return \think\response\Json
*/
public function batchSave()
{
$params = (new RosterValidate())->post()->goCheck('batchSave');
$result = RosterLogic::batchSave($params);
if ($result === false) {
return $this->fail(RosterLogic::getError());
}
return $this->success('批量保存成功', $result);
}
/**
* @notes 复制排班
* @return \think\response\Json
*/
public function copy()
{
$params = (new RosterValidate())->post()->goCheck('copy');
$result = RosterLogic::copy($params);
if ($result === false) {
return $this->fail(RosterLogic::getError());
}
return $this->success('复制成功', []);
}
}
@@ -0,0 +1,32 @@
<?php
namespace app\adminapi\controller\doctor;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\doctor\StatisticsLists;
/**
* 医生统计控制器
* Class StatisticsController
* @package app\adminapi\controller\doctor
*/
class StatisticsController extends BaseAdminController
{
/**
* @notes 医生诊单统计列表
* @return \think\response\Json
*/
public function lists()
{
return $this->dataLists(new StatisticsLists());
}
/**
* @notes 部门统计列表
* @return \think\response\Json
*/
public function deptLists()
{
return $this->dataLists(new StatisticsLists('dept'));
}
}
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\finance;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\finance\AccountCostLists;
use app\adminapi\logic\finance\AccountCostLogic;
use app\adminapi\validate\finance\AccountCostValidate;
class AccountCostController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AccountCostLists());
}
public function add()
{
$params = (new AccountCostValidate())->post()->goCheck('add');
$result = AccountCostLogic::add($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''));
if ($result === false) {
return $this->fail(AccountCostLogic::getError());
}
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new AccountCostValidate())->post()->goCheck('edit');
$result = AccountCostLogic::edit($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''));
if ($result === false) {
return $this->fail(AccountCostLogic::getError());
}
return $this->success('编辑成功', [], 1, 1);
}
public function detail()
{
$params = (new AccountCostValidate())->goCheck('detail');
return $this->data(AccountCostLogic::detail((int) $params['id']));
}
public function delete()
{
$params = (new AccountCostValidate())->post()->goCheck('delete');
$result = AccountCostLogic::delete((int) $params['id']);
if ($result === false) {
return $this->fail(AccountCostLogic::getError());
}
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\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,54 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\finance;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\finance\DeptPerformanceTargetLogic;
use app\adminapi\validate\finance\DeptPerformanceTargetValidate;
/**
* 制定业绩:按部门、按自然月维护目标金额(元)
*
* - GET finance.dept_performance_target/monthMatrix
* - POST finance.dept_performance_target/batchSave
*/
class DeptPerformanceTargetController extends BaseAdminController
{
public function monthMatrix()
{
$params = (new DeptPerformanceTargetValidate())->goCheck('monthMatrix');
$ym = (string) $params['year_month'];
return $this->data(DeptPerformanceTargetLogic::monthMatrix($ym, $this->adminId, $this->adminInfo));
}
public function batchSave()
{
$params = (new DeptPerformanceTargetValidate())->post()->goCheck('batchSave');
$ym = (string) $params['year_month'];
$items = $params['items'] ?? [];
if (!is_array($items)) {
return $this->fail('目标数据格式错误');
}
$result = DeptPerformanceTargetLogic::batchSave(
$ym,
$items,
$this->adminId,
$this->adminInfo,
(string) ($this->adminInfo['name'] ?? '')
);
if ($result === false) {
return $this->fail(DeptPerformanceTargetLogic::getError());
}
return $this->success(
'保存成功',
DeptPerformanceTargetLogic::monthMatrix($ym, $this->adminId, $this->adminInfo),
1,
1
);
}
}
@@ -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,38 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\firstvisit;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\firstvisit\FirstVisitConversionLogic;
class ConversionController extends BaseAdminController
{
private const PAGE_PERMISSION = 'firstvisit.conversion/overview';
public function overview()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法查看综合数据转化');
}
@set_time_limit(120);
return $this->data(FirstVisitConversionLogic::overview(
$this->request->get(),
$this->adminId,
$this->adminInfo
));
}
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
}
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\firstvisit;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\firstvisit\FirstVisitDoctorDashboardLogic;
class DoctorDashboardController extends BaseAdminController
{
private const PAGE_PERMISSION = 'firstvisit.doctorDashboard/overview';
public function overview()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法查看医生看板');
}
@set_time_limit(120);
return $this->data(FirstVisitDoctorDashboardLogic::overview(
$this->request->get(),
$this->adminId,
$this->adminInfo
));
}
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
}
@@ -0,0 +1,473 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\firstvisit;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\firstvisit\MyPatientLists;
use app\adminapi\lists\firstvisit\MyPatientOrderLists;
use app\adminapi\lists\firstvisit\MyPatientProgressLists;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\doctor\AppointmentLogic;
use app\adminapi\logic\firstvisit\MyPatientLogic;
use app\adminapi\logic\tcm\DiagnosisLogic;
use app\adminapi\logic\tcm\PrescriptionOrderLogic;
use app\adminapi\validate\doctor\AppointmentValidate;
use app\adminapi\validate\tcm\DiagnosisValidate;
use app\adminapi\validate\tcm\PrescriptionOrderValidate;
use app\common\model\doctor\Appointment;
use app\common\model\tcm\PrescriptionOrder;
class MyPatientController extends BaseAdminController
{
private const LIST_PERMISSION = 'firstvisit.myPatient/lists';
private string $orderGuardError = '订单不存在或无权操作';
public function lists()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法访问我的患者');
}
return $this->dataLists(new MyPatientLists());
}
/** 当前角色/部门患者范围内的处方业务订单。 */
public function orders()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法查看患者订单');
}
return $this->dataLists(new MyPatientOrderLists());
}
/** 当前角色/部门患者范围内的挂号面诊进度。 */
public function progress()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法查看面诊进度');
}
return $this->dataLists(new MyPatientProgressLists());
}
/** 当前账号数据范围内可被指派的医助。 */
public function assistants()
{
if (!$this->hasPagePermission() || !$this->hasOriginalPermission('tcm.diagnosis/assign')) {
return $this->fail('权限不足,无法获取医助列表');
}
return $this->data(DiagnosisLogic::getAssistants($this->adminId, $this->adminInfo));
}
/** 从“我的患者”指派医助,先校验患者行级数据范围和目标医助范围。 */
public function assign()
{
if (!$this->hasPagePermission() || !$this->hasOriginalPermission('tcm.diagnosis/assign')) {
return $this->fail('权限不足,无法指派患者');
}
$params = $this->request->post();
$diagnosisId = (int) ($params['id'] ?? 0);
$assistantId = (int) ($params['assistant_id'] ?? 0);
if (!MyPatientLogic::canAccessDiagnosis($diagnosisId, $this->adminId, $this->adminInfo)) {
return $this->fail('患者不存在或无权操作');
}
if ($assistantId <= 0 || !$this->canAssignToAssistant($assistantId)) {
return $this->fail('所选医助不在当前可指派范围内');
}
$result = DiagnosisLogic::assign([
'id' => $diagnosisId,
'assistant_id' => $assistantId,
'is_inherit' => (int) ($params['is_inherit'] ?? 0) === 1 ? 1 : 0,
]);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->success('指派成功');
}
/** 从“我的患者”补全身份证,复用诊单身份证校验和年龄计算。 */
public function fillIdCard()
{
if (!$this->hasPagePermission() || !$this->hasOriginalPermission('tcm.diagnosis/edit')) {
return $this->fail('权限不足,无法补全身份证');
}
$params = (new DiagnosisValidate())->post()->goCheck('fillIdCard');
$diagnosisId = (int) ($params['id'] ?? 0);
if (!MyPatientLogic::canAccessDiagnosis($diagnosisId, $this->adminId, $this->adminInfo)) {
return $this->fail('患者不存在或无权操作');
}
$duplicate = DiagnosisLogic::checkIdCard([
'id' => $diagnosisId,
'id_card' => trim((string) ($params['id_card'] ?? '')),
]);
if (!empty($duplicate['exists'])) {
return $this->fail((string) ($duplicate['message'] ?? '该身份证号已存在'));
}
$result = DiagnosisLogic::fillIdCard($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->success('补全成功,年龄已自动更新');
}
/** 当前患者范围内的订单详情;仍要求原订单详情权限。 */
public function orderDetail()
{
$params = (new PrescriptionOrderValidate())->get()->goCheck('detail');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/detail') === null) {
return $this->fail($this->orderGuardError);
}
$detail = PrescriptionOrderLogic::detail((int) $params['id'], $this->adminId, $this->adminInfo);
if ($detail === null) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->data($detail);
}
/** 编辑当前患者范围内的订单,参数只允许原编辑表单支持的字段。 */
public function orderEdit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('edit');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/edit') === null) {
return $this->fail($this->orderGuardError);
}
if ((float) ($params['amount'] ?? 0) < 0) {
return $this->fail('订单金额不能为负数');
}
$params = $this->onlyParams($params, [
'id', 'recipient_name', 'recipient_phone', 'shipping_province', 'shipping_city',
'shipping_district', 'shipping_address', 'is_follow_up', 'medication_days',
'dose_unit', 'dose_count', 'prev_staff', 'service_channel', 'service_package',
'tracking_number', 'express_company', 'fee_type', 'amount', 'remark_extra',
'remark_assistant', 'pay_order_ids', 'internal_cost',
]);
$result = PrescriptionOrderLogic::edit($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('保存成功', $result);
}
public function orderAuditPrescription()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPrescription');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/auditPrescription') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::auditPrescription(
(int) $params['id'],
(string) $params['action'],
(string) ($params['remark'] ?? ''),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
public function orderRevokeRxAudit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/auditPrescription') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::revokeRxAudit((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('处方审核已撤回', $result);
}
public function orderAuditPayment()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPayment');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/auditPayment') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::auditPaymentSlip(
(int) $params['id'],
(string) $params['action'],
(string) ($params['remark'] ?? ''),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
public function orderRevokePayAudit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/auditPayment') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::revokePayAudit((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('支付单审核已撤回', $result);
}
public function orderDdcode()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('ddcode');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/ddcode') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::ddcode(
(int) $params['id'],
(string) ($params['express_company'] ?? 'auto'),
(string) $params['tracking_number'],
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('快递单号已保存', $result);
}
public function orderShip()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('ship');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/ship') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::ship(
(int) $params['id'],
(string) ($params['express_company'] ?? 'auto'),
(string) ($params['tracking_number'] ?? ''),
(string) ($params['ship_mode'] ?? 'gancao'),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('发货成功', $result);
}
public function orderAddPayOrder()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('addPayOrder');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/addPayOrder') === null) {
return $this->fail($this->orderGuardError);
}
$params = $this->onlyParams($params, [
'id', 'order_type', 'pay_amount', 'pay_remark', 'completion_request', 'pay_create_type',
]);
$result = PrescriptionOrderLogic::addPayOrder($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('新增支付单成功', $result);
}
public function orderComplete()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('complete');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/complete') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::complete(
(int) $params['id'],
$this->adminId,
$this->adminInfo,
(int) $params['fulfillment_status']
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
public function orderRefund()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('refund');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/refund') === null) {
return $this->fail($this->orderGuardError);
}
$rawRefundAmount = $params['refund_amount'] ?? null;
$refundAmount = ($rawRefundAmount === null || $rawRefundAmount === '')
? null
: round((float) $rawRefundAmount, 2);
$result = PrescriptionOrderLogic::refund(
(int) $params['id'],
(string) ($params['reason'] ?? ''),
$this->adminId,
$this->adminInfo,
$refundAmount
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('退款成功', $result);
}
public function orderWithdraw()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('withdraw');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/withdraw') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::withdraw((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('已撤回', $result);
}
public function orderUploadToPharmacy()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('uploadToPharmacy');
if ($this->guardOrder((int) $params['id'], 'tcm.prescriptionOrder/uploadToPharmacy') === null) {
return $this->fail($this->orderGuardError);
}
$result = PrescriptionOrderLogic::uploadToPharmacy((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('药方上传成功', $result);
}
/** 从“我的患者”页面创建挂号,写操作复用原逻辑但先做患者行级校验。 */
public function createAppointment()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法创建挂号');
}
$params = (new AppointmentValidate())->post()->goCheck('create');
$diagnosisId = (int) ($params['patient_id'] ?? 0);
if (!MyPatientLogic::canAccessDiagnosis($diagnosisId, $this->adminId, $this->adminInfo)) {
return $this->fail('患者不存在或无权操作');
}
$params['assistant_id'] = $this->adminId;
$result = AppointmentLogic::create($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('挂号成功', $result);
}
/** 从“我的患者”页面取消挂号,按挂号所属诊单再次校验数据范围。 */
public function cancelAppointment()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法取消挂号');
}
$params = (new AppointmentValidate())->post()->goCheck('cancel');
$appointment = Appointment::findOrEmpty((int) ($params['id'] ?? 0));
if ($appointment->isEmpty()) {
return $this->fail('挂号记录不存在');
}
if (!MyPatientLogic::canAccessDiagnosis((int) $appointment->patient_id, $this->adminId, $this->adminInfo)) {
return $this->fail('患者不存在或无权操作');
}
$result = AppointmentLogic::cancel($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AppointmentLogic::getError());
}
return $this->success('取消挂号成功');
}
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::LIST_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
private function hasOriginalPermission(string $permission): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array($permission, AuthLogic::getAuthByAdminId($this->adminId), true);
}
private function guardOrder(int $orderId, string $permission): ?PrescriptionOrder
{
$this->orderGuardError = '订单不存在或无权操作';
if (!$this->hasPagePermission() || !$this->hasOriginalPermission($permission) || $orderId <= 0) {
return null;
}
$order = PrescriptionOrder::where('id', $orderId)->whereNull('delete_time')->find();
if ($order === null) {
return null;
}
if (!MyPatientLogic::canAccessDiagnosis((int) $order->diagnosis_id, $this->adminId, $this->adminInfo)) {
return null;
}
return $order;
}
private function canAssignToAssistant(int $assistantId): bool
{
foreach (DiagnosisLogic::getAssistants($this->adminId, $this->adminInfo) as $assistant) {
if ((int) ($assistant['id'] ?? 0) === $assistantId) {
return true;
}
}
return false;
}
/** @param array<string,mixed> $params @param array<int,string> $keys */
private function onlyParams(array $params, array $keys): array
{
return array_intersect_key($params, array_flip($keys));
}
}
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\firstvisit;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\firstvisit\FirstVisitRegistrationStatsLogic;
class RegistrationStatsController extends BaseAdminController
{
private const PAGE_PERMISSION = 'firstvisit.registrationStats/overview';
public function overview()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法查看挂号统计');
}
@set_time_limit(120);
return $this->data(FirstVisitRegistrationStatsLogic::overview(
$this->request->get(),
$this->adminId,
$this->adminInfo
));
}
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
}
@@ -0,0 +1,205 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\firstvisit;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\firstvisit\WecomAcquisitionCustomerLogic;
use app\adminapi\logic\firstvisit\WecomPromotionLogic;
class WecomPromotionController extends BaseAdminController
{
private const PAGE_PERMISSION = 'firstvisit.wecomPromotion/overview';
public function overview()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足,无法访问企业微信获客助手');
}
return $this->run(fn () => $this->data(WecomPromotionLogic::overview(
$this->adminId,
$this->adminInfo,
$this->request->domain()
)));
}
public function savePool()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('分流方案已保存', WecomPromotionLogic::savePool(
$this->request->post(),
$this->adminId,
$this->adminInfo
)));
}
public function saveWidget()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('浮窗配置已保存', WecomPromotionLogic::saveWidget(
$this->request->post(),
$this->adminId,
$this->adminInfo
)));
}
public function deletePool()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
return $this->run(function () use ($id) {
WecomPromotionLogic::deletePool($id, $this->adminId, $this->adminInfo);
return $this->success('分流方案已删除');
});
}
public function saveLink()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('获客助手链接已保存', WecomPromotionLogic::saveLink(
$this->request->post(),
$this->adminId,
$this->adminInfo
)));
}
public function checkApiPermission()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('获客助手 API 权限验证通过', WecomPromotionLogic::checkApiPermission()));
}
public function syncRemoteLinks()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$poolId = (int) $this->request->post('pool_id', 0);
return $this->run(fn () => $this->success('企业微信获客链接同步完成', WecomPromotionLogic::syncRemoteLinks(
$poolId,
$this->adminId,
$this->adminInfo
)));
}
public function remoteLinkDetail()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->get('id', 0);
return $this->run(fn () => $this->data(WecomPromotionLogic::remoteLinkDetail(
$id,
$this->adminId,
$this->adminInfo
)));
}
public function deleteRemoteLink()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
return $this->run(function () use ($id) {
WecomPromotionLogic::deleteRemoteLink($id, $this->adminId, $this->adminInfo);
return $this->success('企业微信获客链接已永久删除,本地审计记录已保留');
});
}
public function syncCustomers()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('获客客户同步完成', WecomAcquisitionCustomerLogic::sync(
$this->request->post(),
$this->adminId,
$this->adminInfo
)));
}
public function customerStatistics()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->data(WecomAcquisitionCustomerLogic::statistics(
$this->request->get(),
$this->adminId,
$this->adminInfo
)));
}
public function toggleLink()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
$status = (int) $this->request->post('status', 0);
return $this->run(function () use ($id, $status) {
WecomPromotionLogic::toggleLink($id, $status, $this->adminId, $this->adminInfo);
return $this->success('状态已更新');
});
}
public function deleteLink()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
return $this->run(function () use ($id) {
WecomPromotionLogic::deleteLink($id, $this->adminId, $this->adminInfo);
return $this->success('获客助手链接已删除');
});
}
private function run(callable $callback)
{
try {
return $callback();
} catch (\Throwable $e) {
return $this->fail($e->getMessage());
}
}
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
}
@@ -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,99 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\order;
use app\common\model\Order;
use think\response\Json;
/**
* 支付宝支付回调控制器
* Class AlipayNotifyController
* @package app\adminapi\controller\order
*/
class AlipayNotifyController
{
/**
* @notes 支付宝异步通知
* @return string
*/
public function notify()
{
try {
// 获取支付宝配置
$alipayConfig = config('pay.alipay');
// 获取POST数据
$data = request()->post();
// 验证签名
if (!$this->verifyAlipaySign($data, $alipayConfig['alipay_public_key'])) {
return 'fail';
}
// 验证金额
$order = Order::where('order_no', $data['out_trade_no'])->find();
if (!$order) {
return 'fail';
}
if ((float)$data['total_amount'] != (float)$order->amount) {
return 'fail';
}
// 验证交易状态
if ($data['trade_status'] == 'TRADE_SUCCESS' || $data['trade_status'] == 'TRADE_FINISHED') {
// 更新订单状态
if ($order->status == 1) { // 只有待支付的订单才能更新
$order->status = 2; // 已支付
$order->payment_method = 'alipay';
$order->payment_time = date('Y-m-d H:i:s');
$order->trade_no = $data['trade_no'];
$order->save();
}
}
return 'success';
} catch (\Exception $e) {
return 'fail';
}
}
/**
* @notes 验证支付宝签名
* @param array $data
* @param string $publicKey
* @return bool
*/
private function verifyAlipaySign(array $data, string $publicKey): bool
{
try {
// 获取签名
$sign = $data['sign'] ?? '';
unset($data['sign']);
unset($data['sign_type']);
// 按键排序
ksort($data);
// 构建签名字符串
$signStr = '';
foreach ($data as $key => $value) {
if ($value !== '' && $value !== null) {
$signStr .= $key . '=' . $value . '&';
}
}
$signStr = rtrim($signStr, '&');
// 验证签名
$publicKeyResource = openssl_pkey_get_public($publicKey);
$result = openssl_verify($signStr, base64_decode($sign), $publicKeyResource, OPENSSL_ALGO_SHA256);
openssl_free_key($publicKeyResource);
return $result === 1;
} catch (\Exception $e) {
return false;
}
}
}
@@ -0,0 +1,594 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\order;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\order\OrderLists;
use app\adminapi\logic\order\OrderActionLogLogic;
use app\adminapi\logic\order\OrderLogic;
use app\adminapi\validate\order\OrderValidate;
/**
* 订单管理控制器
* Class OrderController
* @package app\adminapi\controller\order
*/
class OrderController extends BaseAdminController
{
/**
* @notes 订单列表
* @return \think\response\Json
*/
public function lists()
{
return $this->dataLists(new OrderLists());
}
/**
* @notes 指定诊单下已支付支付单列表(创建/编辑处方业务订单时多选关联)
* @return \think\response\Json
*/
public function paidOrdersForDiagnosis()
{
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
if ($diagnosisId <= 0) {
return $this->fail('诊单ID必填');
}
$exceptPo = (int) $this->request->get('prescription_order_id', 0);
$lists = OrderLogic::listPaidOrdersForDiagnosis(
$diagnosisId,
$this->adminId,
$this->adminInfo,
$exceptPo > 0 ? $exceptPo : null
);
return $this->success('', ['lists' => $lists]);
}
/**
* @notes 同步企业微信对外收款账单到订单
* 员工直接在企业微信发起收款(未经过后台创建)时,通过此接口拉取并创建订单
* @return \think\response\Json
*/
public function syncWechatWorkBills()
{
$beginStr = $this->request->get('begin_time', date('Y-m-d', strtotime('-7 days')));
$endStr = $this->request->get('end_time', date('Y-m-d'));
$beginTime = strtotime($beginStr . ' 00:00:00');
$endTime = strtotime($endStr . ' 23:59:59');
if ($beginTime >= $endTime) {
return $this->fail('开始时间必须早于结束时间');
}
if ($endTime - $beginTime > 31 * 86400) {
return $this->fail('企业微信接口限制:时间范围不能超过31天');
}
$result = OrderLogic::syncFromWechatWorkBills($beginTime, $endTime);
if (!empty($result['errors']) && $result['created'] === 0 && $result['updated'] === 0) {
return $this->fail(implode('', $result['errors']));
}
return $this->success('同步完成', $result);
}
/**
* @notes 调试:测试企业微信对外收款 API 连接(返回原始响应,用于排查同步为0的问题)
* @return \think\response\Json
*/
public function syncWechatWorkBillsDebug()
{
$beginStr = $this->request->get('begin_time', date('Y-m-d'));
$endStr = $this->request->get('end_time', date('Y-m-d'));
$payeeUserid = trim((string)$this->request->get('payee_userid', ''));
$beginTime = strtotime($beginStr . ' 00:00:00');
$endTime = strtotime($endStr . ' 23:59:59');
$service = new \app\common\service\wechat\WechatWorkExternalPayService();
$config = config('pay.wechat_work', []);
$debug = [
'config_ok' => !empty($config['corp_id']) && !empty($config['external_pay_secret']),
'corp_id' => $config['corp_id'] ? substr($config['corp_id'], 0, 8) . '***' : '(空)',
'time_range' => [$beginStr, $endStr],
'payee_userid' => $payeeUserid ?: '(未指定,查全部)',
'access_token' => $service->getAccessToken() ? '已获取' : '获取失败',
];
$resp = $service->getBillList($beginTime, $endTime, $payeeUserid, '', 100);
$debug['api_errcode'] = $resp['errcode'] ?? -999;
$debug['api_errmsg'] = $resp['errmsg'] ?? '';
$debug['bill_count'] = count($resp['bill_list'] ?? []);
$debug['next_cursor'] = !empty($resp['next_cursor']) ? '有' : '无';
$debug['page1'] = $resp;
if (!empty($resp['next_cursor']) && $debug['bill_count'] === 0) {
$resp2 = $service->getBillList($beginTime, $endTime, $payeeUserid, $resp['next_cursor'], 100);
$debug['page2_errcode'] = $resp2['errcode'] ?? -999;
$debug['page2_bill_count'] = count($resp2['bill_list'] ?? []);
$debug['page2_sample'] = isset($resp2['bill_list'][0]) ? $resp2['bill_list'][0] : null;
}
if ($debug['bill_count'] === 0 && empty($payeeUserid)) {
$admins = \app\common\model\auth\Admin::where('work_wechat_userid', '<>', '')
->whereNull('delete_time')->column('work_wechat_userid', 'id');
$debug['try_payee_userids'] = array_values(array_filter(array_unique($admins)));
$debug['tip'] = '若 try_payee_userids 有值,可传 payee_userid=xxx 重试(如 ?payee_userid=GaoXingLiang';
}
return $this->success('调试信息', $debug);
}
/**
* @notes 今日收益(按角色权限)
* @return \think\response\Json
*/
public function todayRevenue()
{
$result = OrderLogic::todayRevenue($this->adminId, $this->adminInfo);
return $this->data($result);
}
/**
* @notes 订单统计(挂号费/药品费用)
* @return \think\response\Json
*/
public function orderStats()
{
$params = $this->request->get();
$result = OrderLogic::orderStats($params, (int) $this->adminId, $this->adminInfo);
return $this->data($result);
}
/**
* @notes 订单详情
* @return \think\response\Json
*/
public function detail()
{
$params = (new OrderValidate())->post()->goCheck('detail');
$orderId = (int)$params['id'];
$detail = OrderLogic::detail($orderId);
if (!$detail) {
return $this->fail('订单不存在');
}
$this->logOrderAction($orderId, 'view_detail', '查看订单详情');
return $this->data($detail);
}
/**
* @notes 支付单操作日志(单条订单,分页)
*/
public function actionLogs()
{
$orderId = (int)$this->request->get('order_id', 0);
if ($orderId <= 0) {
return $this->fail('order_id 必填');
}
$pageNo = (int)$this->request->get('page_no', 1);
$pageSize = (int)$this->request->get('page_size', 20);
$data = OrderActionLogLogic::listByOrderId($orderId, $pageNo, $pageSize);
return $this->success('', $data);
}
/**
* @notes 按人统计操作次数(时间范围内)
* @return \think\response\Json
*/
public function actionLogStats()
{
$start = trim((string)$this->request->get('start_time', ''));
$end = trim((string)$this->request->get('end_time', ''));
if ($start === '' || $end === '') {
$endTime = time();
$startTime = $endTime - 7 * 86400;
} else {
$startTime = strtotime($start . ' 00:00:00') ?: 0;
$endTime = strtotime($end . ' 23:59:59') ?: 0;
}
if ($startTime <= 0 || $endTime < $startTime) {
return $this->fail('时间范围无效');
}
$limit = (int)$this->request->get('limit', 50);
$rows = OrderActionLogLogic::statsByAdmin($startTime, $endTime, $limit);
return $this->success('', [
'list' => $rows,
'start_time' => date('Y-m-d H:i:s', $startTime),
'end_time' => date('Y-m-d H:i:s', $endTime),
]);
}
/**
* @notes 创建订单
* @return \think\response\Json
*/
public function create()
{
$params = (new OrderValidate())->post()->goCheck('create');
$params['creator_id'] = $this->adminId;
$params['payment_channel'] = (string)$this->request->post('payment_channel', 'normal');
$params['require_payment_slip_audit'] = (int)$this->request->post('require_payment_slip_audit', 0);
// 创建方式:优先取前端透传的 create_type,否则按 payment_channel 派生(fubei→fubeiexpress_cod→express_cod,其余 normal
$createTypeReq = (string)$this->request->post('create_type', '');
if (in_array($createTypeReq, ['normal', 'wechat_work', 'fubei', 'express_cod'], true)) {
$params['create_type'] = $createTypeReq;
} elseif ($params['payment_channel'] === 'fubei') {
$params['create_type'] = 'fubei';
} elseif ($params['payment_channel'] === 'express_cod') {
$params['create_type'] = 'express_cod';
} else {
$params['create_type'] = 'normal';
}
$result = OrderLogic::create($params);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction((int)$result->id, 'create', '创建支付单(普通/付呗等)');
return $this->success('创建成功', $result->toArray());
}
/**
* @notes 创建企业微信对外收款订单
* 返回 order_no,供员工在企业微信发起收款时作为商户订单号(out_trade_no)使用
* 收款成功后,微信支付回调会自动更新订单为已支付
* @return \think\response\Json
*/
public function createForWechatWork()
{
$params = (new OrderValidate())->post()->goCheck('create');
$params['creator_id'] = $this->adminId;
$params['create_type'] = 'wechat_work';
$result = OrderLogic::createForWechatWork($params);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$ord = $result['order'] ?? null;
if (is_array($ord) && !empty($ord['id'])) {
$this->logOrderAction((int)$ord['id'], 'create_wechat_work', '创建支付单(企业微信对外收款)');
}
return $this->success('创建成功,请在企业微信收款时使用以下订单号', [
'order_no' => $result['order_no'],
'order' => $result['order'],
'tip' => '在企业微信发起对外收款时,将上述订单号填写为「商户订单号」',
]);
}
/**
* @notes 批量指派医助(写入 order.assistant_id,并记操作日志)
*/
public function assignAssistant()
{
$params = (new OrderValidate())->post()->goCheck('assign_assistant');
$rawIds = $params['order_ids'] ?? [];
if (!\is_array($rawIds) || $rawIds === []) {
return $this->fail('请选择订单');
}
$orderIds = array_map('intval', $rawIds);
$orderIds = array_values(array_unique(array_filter($orderIds, static fn (int $id) => $id > 0)));
if ($orderIds === []) {
return $this->fail('请选择有效订单');
}
$allowed = [];
foreach ($orderIds as $id) {
$order = \app\common\model\Order::find($id);
if (!$order) {
continue;
}
if (!$this->canEditOrder($order)) {
return $this->fail('无权限操作订单:' . (string) ($order->order_no ?? $id));
}
$allowed[] = $id;
}
if ($allowed === []) {
return $this->fail('没有可指派的订单');
}
$assistantId = (int) $params['assistant_id'];
$result = OrderLogic::batchAssignAssistant($allowed, $assistantId);
if ($result === false) {
return $this->fail(OrderLogic::getError());
}
foreach ($result['per_log'] as $row) {
$this->logOrderAction((int) $row['order_id'], 'assign_assistant', (string) ($row['summary'] ?? ''));
}
$msg = '已变更「创建人」' . (int) $result['success'] . ' 单';
if (!empty($result['errors'])) {
$msg .= ',说明:' . implode('', $result['errors']);
}
return $this->success($msg, $result);
}
/**
* @notes 拆分订单:生成多笔子单(待支付/待审核/已支付继承支付信息),金额合计须等于原单;原单软删除;业务订单关联自动迁移
* @return \think\response\Json
*/
public function split()
{
$params = (new OrderValidate())->post()->goCheck('split');
$orderId = (int) $params['id'];
$amounts = $params['amounts'] ?? [];
if (! is_array($amounts)) {
return $this->fail('子单金额格式错误');
}
$orderTypes = $params['order_types'] ?? [];
if (! is_array($orderTypes)) {
return $this->fail('子单订单类型格式错误');
}
$order = \app\common\model\Order::find($orderId);
if (! $order) {
return $this->fail('订单不存在');
}
if (! $this->canEditOrder($order)) {
return $this->fail('无权限拆分此订单');
}
$result = OrderLogic::split($orderId, $amounts, $orderTypes);
if ($result === false) {
return $this->fail(OrderLogic::getError());
}
$summary = '拆分为子单 id=' . implode(',', $result['new_order_ids'] ?? []);
$this->logOrderAction($orderId, 'split', $summary);
foreach ($result['new_order_ids'] ?? [] as $nid) {
$this->logOrderAction((int) $nid, 'split_child', '来源原单 id=' . $orderId . ' ' . (string) ($order->order_no ?? ''));
}
return $this->success('拆分成功', $result);
}
/**
* @notes 编辑订单(关联患者、订单类型)
* 权限:超管或指定角色组可修改任意订单;其他用户只能修改自己创建的订单
* @return \think\response\Json
*/
public function edit()
{
$params = (new OrderValidate())->post()->goCheck('edit');
$orderId = (int)$params['id'];
$order = \app\common\model\Order::find($orderId);
if (!$order) {
return $this->fail('订单不存在');
}
if (!$this->canEditOrder($order)) {
return $this->fail('无权限修改此订单');
}
$result = OrderLogic::edit($orderId, $params);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($orderId, 'edit', '编辑患者/订单类型等');
return $this->success('编辑成功');
}
/**
* @notes 是否可编辑指定订单(超管或指定角色可编辑任意,否则只能编辑自己创建的)
*/
private function canEditOrder($order): bool
{
if (!empty($this->adminInfo['root']) && $this->adminInfo['root'] == 1) {
return true;
}
$editAllRoles = config('project.order_edit_all_roles', [0, 3]);
$roleIds = \app\common\model\auth\AdminRole::where('admin_id', $this->adminId)->column('role_id');
if (count(array_intersect($roleIds, $editAllRoles)) > 0) {
return true;
}
return (int)$order->creator_id === $this->adminId;
}
/**
* @notes 支付订单
* @return \think\response\Json
*/
public function pay()
{
$params = (new OrderValidate())->post()->goCheck('pay');
// 判断是否是补单支付
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:通过订单号查找订单
if (empty($params['order_no'])) {
return $this->fail('补单支付需要提供订单号');
}
$order = \app\common\model\Order::where('order_no', $params['order_no'])->find();
if (!$order) {
return $this->fail('订单不存在');
}
$orderId = $order->id;
} else {
// 正常支付:通过订单ID
if (empty($params['id'])) {
return $this->fail('订单ID不能为空');
}
$orderId = (int)$params['id'];
}
$result = OrderLogic::pay($orderId, $params['payment_method']);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($orderId, 'pay', '确认支付/标记已付,方式:' . (string)($params['payment_method'] ?? ''));
return $this->success('支付成功');
}
/**
* @notes 取消订单
* @return \think\response\Json
*/
public function cancel()
{
$params = (new OrderValidate())->post()->goCheck('cancel');
$oid = (int)$params['id'];
$result = OrderLogic::cancel($oid);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($oid, 'cancel', '取消订单');
return $this->success('取消成功');
}
/**
* @notes 退款订单
* @return \think\response\Json
*/
public function refund()
{
$params = (new OrderValidate())->post()->goCheck('refund');
$oid = (int)$params['id'];
$result = OrderLogic::refund($oid);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($oid, 'refund', '退款');
return $this->success('退款成功');
}
/**
* @notes 删除订单
* @return \think\response\Json
*/
public function delete()
{
$params = (new OrderValidate())->post()->goCheck('delete');
$oid = (int)$params['id'];
$result = OrderLogic::delete($oid);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($oid, 'delete', '删除订单(软删)');
return $this->success('删除成功');
}
/**
* @notes 导出订单
* @return \think\response\Json
*/
public function export()
{
return $this->dataLists(new OrderLists());
}
/**
* @notes 支付宝支付
* @return \think\response\Json
*/
public function alipay()
{
$params = (new OrderValidate())->post()->goCheck('pay');
// 补单支付不需要校验订单是否存在
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:直接返回支付URL,不校验订单
$payUrl = OrderLogic::alipayPay(['order_no' => $params['order_no']]);
if (!$payUrl) {
return $this->fail(OrderLogic::getError());
}
return $this->data(['pay_url' => $payUrl]);
}
// 正常支付需要校验订单
$order = $this->getOrderByParams($params);
if (!$order) {
return $this->fail('订单不存在');
}
// 调用支付宝支付接口
$payUrl = OrderLogic::alipayPay($order);
if (!$payUrl) {
return $this->fail(OrderLogic::getError());
}
return $this->data(['pay_url' => $payUrl]);
}
/**
* @notes 微信支付
* @return \think\response\Json
*/
public function wechat()
{
$params = (new OrderValidate())->post()->goCheck('pay');
// 补单支付不需要校验订单是否存在
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:直接返回支付数据,不校验订单
$payData = OrderLogic::wechatPay(['order_no' => $params['order_no']]);
if (!$payData) {
return $this->fail(OrderLogic::getError());
}
return $this->data($payData);
}
// 正常支付需要校验订单
$order = $this->getOrderByParams($params);
if (!$order) {
return $this->fail('订单不存在');
}
// 调用微信支付接口
$payData = OrderLogic::wechatPay($order);
if (!$payData) {
return $this->fail(OrderLogic::getError());
}
return $this->data($payData);
}
/**
* @notes 根据参数获取订单
* @param array $params
* @return mixed
*/
private function getOrderByParams(array $params)
{
if (!empty($params['is_supplement']) && $params['is_supplement'] == 1) {
// 补单支付:通过订单号查找
if (empty($params['order_no'])) {
return null;
}
return \app\common\model\Order::where('order_no', $params['order_no'])->find();
} else {
// 正常支付:通过订单ID
if (empty($params['id'])) {
return null;
}
return \app\common\model\Order::find((int)$params['id']);
}
}
public function setExempt()
{
$id = (int) $this->request->post('id', 0);
$isExempt = (int) $this->request->post('is_exempt', 0);
if ($id <= 0) {
return $this->fail('参数错误');
}
if (!in_array($isExempt, [0, 1], true)) {
return $this->fail('is_exempt 值无效');
}
$result = OrderLogic::setExempt($id, $isExempt);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($id, 'set_exempt', $isExempt === 1 ? '设置豁免权' : '取消豁免权');
return $this->success($isExempt === 1 ? '已设置豁免权' : '已取消豁免权');
}
private function logOrderAction(int $orderId, string $action, string $summary = ''): void
{
OrderActionLogLogic::record($orderId, (int) $this->adminId, $this->adminInfo, $action, $summary);
}
}
@@ -0,0 +1,142 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\order;
use app\adminapi\logic\order\OrderLogic;
use app\common\model\Order;
use think\response\Xml;
/**
* 微信支付回调控制器
* 支持:1) 预创建订单的支付 2) 员工直接在企业微信发起对外收款(自动创建订单)
* Class WechatNotifyController
* @package app\adminapi\controller\order
*/
class WechatNotifyController
{
/**
* @notes 微信异步通知
* @return Xml
*/
public function notify()
{
try {
// 获取微信配置
$wechatConfig = config('pay.wechat');
// 获取XML数据
$xmlData = file_get_contents('php://input');
$data = $this->xmlToArray($xmlData);
// 验证签名
if (!$this->verifyWechatSign($data, $wechatConfig['api_key'])) {
return $this->xmlResponse('FAIL', '签名验证失败');
}
$outTradeNo = $data['out_trade_no'] ?? '';
$totalFee = (int)($data['total_fee'] ?? 0);
$amount = $totalFee / 100;
$transactionId = $data['transaction_id'] ?? '';
$order = Order::where('order_no', $outTradeNo)->find();
if (!$order) {
// 订单不存在:员工直接在企业微信发起收款,自动创建订单并标记已支付
if ($data['result_code'] == 'SUCCESS' && $totalFee > 0) {
$newOrder = OrderLogic::createFromCallback($outTradeNo, $amount, $transactionId);
if ($newOrder) {
return $this->xmlResponse('SUCCESS', '支付成功');
}
}
return $this->xmlResponse('FAIL', '订单不存在');
}
if ($totalFee != (int)($order->amount * 100)) {
return $this->xmlResponse('FAIL', '金额不匹配');
}
// 验证交易状态
if ($data['result_code'] == 'SUCCESS') {
// 更新订单状态(支持普通微信支付及企业微信对外收款)
if ($order->status == 1) { // 只有待支付的订单才能更新
$order->status = 2; // 已支付
$order->payment_method = 'wechat';
$order->payment_time = date('Y-m-d H:i:s');
$order->trade_no = $transactionId;
$order->save();
}
}
return $this->xmlResponse('SUCCESS', '支付成功');
} catch (\Exception $e) {
return $this->xmlResponse('FAIL', $e->getMessage());
}
}
/**
* @notes 验证微信签名
* @param array $data
* @param string $apiKey
* @return bool
*/
private function verifyWechatSign(array $data, string $apiKey): bool
{
try {
// 获取签名
$sign = $data['sign'] ?? '';
unset($data['sign']);
// 按键排序
ksort($data);
// 构建签名字符串
$signStr = '';
foreach ($data as $key => $value) {
if ($value !== '' && $value !== null) {
$signStr .= $key . '=' . $value . '&';
}
}
$signStr .= 'key=' . $apiKey;
// MD5签名
$computedSign = strtoupper(md5($signStr));
return $computedSign === $sign;
} catch (\Exception $e) {
return false;
}
}
/**
* @notes XML转数组
* @param string $xml
* @return array
*/
private function xmlToArray(string $xml): array
{
try {
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return is_array($data) ? $data : [];
} catch (\Exception $e) {
return [];
}
}
/**
* @notes 返回XML响应
* @param string $returnCode
* @param string $returnMsg
* @return Xml
*/
private function xmlResponse(string $returnCode, string $returnMsg): Xml
{
$xml = '<xml>';
$xml .= '<return_code><![CDATA[' . $returnCode . ']]></return_code>';
$xml .= '<return_msg><![CDATA[' . $returnMsg . ']]></return_msg>';
$xml .= '</xml>';
return response($xml, 200, ['Content-Type' => 'application/xml']);
}
}
@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\pharmacy;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\pharmacy\MedicineMappingLists;
use app\adminapi\logic\pharmacy\MedicineMappingLogic;
use app\adminapi\validate\pharmacy\MedicineMappingValidate;
class MedicineMappingController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new MedicineMappingLists());
}
public function status()
{
return $this->data(MedicineMappingLogic::status());
}
public function catalogOptions()
{
return $this->data(MedicineMappingLogic::catalogOptions(
(string) $this->request->get('keyword', ''),
(int) $this->request->get('limit', 30)
));
}
public function save()
{
$params = (new MedicineMappingValidate())->post()->goCheck('save');
$name = (string) ($this->adminInfo['name'] ?? $this->adminInfo['nickname'] ?? '');
if (!MedicineMappingLogic::save($params, $this->adminId, $name)) {
return $this->fail(MedicineMappingLogic::getError());
}
return $this->success('映射已保存', [], 1, 1);
}
public function unlink()
{
$params = (new MedicineMappingValidate())->post()->goCheck('unlink');
$name = (string) ($this->adminInfo['name'] ?? $this->adminInfo['nickname'] ?? '');
if (!MedicineMappingLogic::unlink((int) $params['local_medicine_id'], $this->adminId, $name)) {
return $this->fail(MedicineMappingLogic::getError());
}
return $this->success('映射已解除', [], 1, 1);
}
public function sync()
{
$result = MedicineMappingLogic::sync();
if ($result === false) {
return $this->fail(MedicineMappingLogic::getError());
}
return $this->success('目录同步完成', $result);
}
}
@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\qywx;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\qywx\CustomerLists;
use app\adminapi\logic\qywx\CustomerLogic;
use app\adminapi\validate\qywx\CustomerValidate;
/**
* 企业微信客户管理控制器
*/
class CustomerController extends BaseAdminController
{
/**
* @notes 客户列表
*/
public function lists()
{
return $this->dataLists(new CustomerLists());
}
/**
* @notes 同步企业微信客户
*/
public function sync()
{
$result = CustomerLogic::triggerBackgroundSync();
if ($result === false) {
return $this->fail(CustomerLogic::getError());
}
$msg = is_array($result) && isset($result['message']) ? (string) $result['message'] : '已提交同步';
return $this->success($msg, $result);
}
/**
* @notes 获取统计信息
*/
public function stats()
{
$stats = CustomerLogic::getStats();
return $this->data($stats);
}
/**
* @notes 获取标签维度统计(按 group 分组、按客户数倒序,供前端筛选下拉 + 标签面板共用)
*/
public function tagStats()
{
return $this->data(CustomerLogic::getTagStats());
}
/**
* @notes 今日进入分布(用于页面"今日新增"卡片的迷你柱/最近进入时间/渠道 Top5)
*/
public function todayArrival()
{
return $this->data(CustomerLogic::getTodayArrivalStats());
}
/**
* @notes 今日进入明细流水(每一次 add_external_contact 推送 = 一行,按时间倒序分页)
*/
public function todayArrivalList()
{
$pageNo = (int) $this->request->get('page_no', 1);
$pageSize = (int) $this->request->get('page_size', 20);
return $this->data(CustomerLogic::getTodayArrivalList($pageNo, $pageSize));
}
/**
* @notes 获取同步设置
*/
public function getSyncSettings()
{
$settings = CustomerLogic::getSyncSettings();
return $this->data($settings);
}
/**
* @notes 保存同步设置
*/
public function saveSyncSettings()
{
$params = (new CustomerValidate())->post()->goCheck('syncSettings');
$result = CustomerLogic::saveSyncSettings($params);
if ($result === false) {
return $this->fail(CustomerLogic::getError());
}
return $this->success('保存成功');
}
}
@@ -0,0 +1,171 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\qywx;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\qywx\MsgArchiveLists;
use app\adminapi\lists\qywx\MsgSendTaskLists;
use app\adminapi\lists\qywx\MsgSessionLists;
use app\adminapi\logic\qywx\MessageLogic;
use app\adminapi\validate\qywx\MessageValidate;
use app\common\service\wechat\QywxMsgArchiveService;
use app\common\service\wechat\WechatWorkService;
use think\facade\Log;
/**
* 企业微信 员工↔客户 消息收发
*
* 接口一览:
* GET qywx.message/session_list 会话列表(左侧)
* GET qywx.message/archive_list 会话消息历史(中间)
* POST qywx.message/mark_read 清零会话未读
* POST qywx.message/send 创建企业群发(员工代发)任务
* GET qywx.message/send_task_list 群发任务列表
* GET qywx.message/send_task_detail 任务送达详情(会回调企微查询)
* GET qywx.message/staff_list 可代发员工(admin 表 work_wechat_userid 不空者)
* GET qywx.message/customer_of_staff 某员工已添加的客户
* POST qywx.message/upload_to_qywx 上传媒体文件到企微,返回 media_id(供附件使用)
* POST qywx.message/pull_archive 手动触发一次存档拉取(便于调试;cron 正常也会跑)
* GET qywx.message/archive_status 会话存档模块状态(SDK/私钥诊断)
*/
class MessageController extends BaseAdminController
{
public function session_list()
{
return $this->dataLists(new MsgSessionLists());
}
public function archive_list()
{
return $this->dataLists(new MsgArchiveLists());
}
public function mark_read()
{
$sessionId = (int) $this->request->post('session_id', 0);
if ($sessionId <= 0) {
return $this->fail('session_id 无效');
}
MessageLogic::markSessionRead($sessionId);
return $this->success('ok');
}
public function send()
{
$params = (new MessageValidate())->post()->goCheck('send');
$result = MessageLogic::createSendTask($params, $this->adminId);
if ($result === false) {
return $this->fail(MessageLogic::getError());
}
return $this->success('已提交,员工手机端确认后将发出', $result);
}
public function send_task_list()
{
return $this->dataLists(new MsgSendTaskLists());
}
public function send_task_detail()
{
$taskId = (int) $this->request->get('task_id', 0);
$cursor = (string) $this->request->get('cursor', '');
if ($taskId <= 0) {
return $this->fail('task_id 无效');
}
return $this->data(MessageLogic::querySendTaskResult($taskId, $cursor));
}
public function staff_list()
{
$keyword = trim((string) $this->request->get('keyword', ''));
return $this->data(MessageLogic::staffList($keyword));
}
public function customer_of_staff()
{
$staff = trim((string) $this->request->get('staff_userid', ''));
$keyword = trim((string) $this->request->get('keyword', ''));
$limit = (int) $this->request->get('limit', 200);
return $this->data(MessageLogic::customerOfStaff($staff, $keyword, $limit));
}
/**
* 上传素材到企业微信,返回 media_id(3 天有效)
*
* 入参:multipart 文件字段 filequery / form 字段 type = image|voice|video|file
*
* 使用场景:前端先上传本地文件到自家服务器(/upload/image 等)得到本地 URL 用于预览;
* 确认发送时再调本接口上传到企微拿 media_id,填入 add_msg_template 的 attachments。
*/
public function upload_to_qywx()
{
$type = (string) $this->request->param('type', 'image');
if (!in_array($type, ['image', 'voice', 'video', 'file'], true)) {
return $this->fail('不支持的媒体类型');
}
$file = $this->request->file('file');
if (!$file) {
return $this->fail('未上传文件');
}
try {
$tempDir = runtime_path() . 'qywx_upload_tmp' . DIRECTORY_SEPARATOR;
if (!is_dir($tempDir)) {
@mkdir($tempDir, 0755, true);
}
$savePath = $tempDir . uniqid('qywx_', true) . '_' . $file->getOriginalName();
// @phpstan-ignore-next-line move returns File
move_uploaded_file($file->getPathname(), $savePath);
$service = new WechatWorkService('customer_contact');
$resp = $service->uploadMedia($type, $savePath, $file->getOriginalName());
@unlink($savePath);
$errcode = isset($resp['errcode']) ? (int) $resp['errcode'] : -1;
if ($errcode !== 0 || empty($resp['media_id'])) {
Log::warning('企微上传素材失败: ' . json_encode($resp, JSON_UNESCAPED_UNICODE));
return $this->fail('企微上传失败: ' . ($resp['errmsg'] ?? '未知错误'));
}
return $this->success('ok', [
'media_id' => (string) $resp['media_id'],
'type' => $resp['type'] ?? $type,
'created_at' => $resp['created_at'] ?? time(),
]);
} catch (\Throwable $e) {
Log::error('upload_to_qywx 异常: ' . $e->getMessage());
return $this->fail($e->getMessage());
}
}
public function pull_archive()
{
$maxBatches = (int) $this->request->param('max_batches', 5);
$download = (bool) $this->request->param('download', false);
$pull = QywxMsgArchiveService::pullLoop(max(1, $maxBatches));
$media = null;
if ($download && $pull['enabled']) {
$media = QywxMsgArchiveService::downloadPendingMedia(200);
}
return $this->data([
'pull' => $pull,
'media' => $media,
]);
}
public function archive_status()
{
return $this->data(MessageLogic::archiveStatus());
}
}
@@ -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,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,21 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\AssistantPerformanceLogic;
/**
* 医助个人业绩
*
* - GET stats.assistantPerformance/overview 个人业绩概览
*/
class AssistantPerformanceController extends BaseAdminController
{
public function overview()
{
$params = $this->request->get();
return $this->data(AssistantPerformanceLogic::overview($params, $this->adminId, $this->adminInfo));
}
}
@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\stats\AutoAssignLogLists;
use app\adminapi\logic\stats\AutoAssignLogLogic;
/**
* 待分配诊单自动指派日志
*
* - GET stats.autoAssignLog/lists 日志列表
* - POST stats.autoAssignLog/rollback 批量回退已自动分配的医助
*/
class AutoAssignLogController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new AutoAssignLogLists());
}
public function rollback()
{
$ids = $this->request->post('ids', []);
if (!is_array($ids)) {
$ids = [$ids];
}
$result = AutoAssignLogLogic::rollback($ids, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(AutoAssignLogLogic::getError());
}
$msg = sprintf('回退成功 %d 条', (int) ($result['success'] ?? 0));
$failed = (int) ($result['failed'] ?? 0);
if ($failed > 0) {
$msg .= sprintf(',跳过/失败 %d 条', $failed);
}
// show=0:由前端按 success/failed 明细提示,避免与部分失败警告重复
return $this->success($msg, $result, 1, 0);
}
}
@@ -0,0 +1,141 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\YejiStatsLogic;
/**
* 提成结算业绩(独立于业绩看板 yejiStats 接口)
*
* - GET stats.commissionSettlement/overview
* - GET stats.commissionSettlement/orderLines
* - GET stats.commissionSettlement/confirmStatus
* - POST stats.commissionSettlement/saveReconcile
* - POST stats.commissionSettlement/confirmFinalize
* - POST stats.commissionSettlement/confirmRevoke
* - GET stats.commissionSettlement/deptOptions
* - GET stats.commissionSettlement/channelOptions
*/
class CommissionSettlementController extends BaseAdminController
{
public function overview()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::commissionSettlementOverview($params, $this->adminId, $this->adminInfo));
}
public function orderLines()
{
@set_time_limit(120);
return $this->data(YejiStatsLogic::commissionSettlementOrderLines($this->request->get(), $this->adminId, $this->adminInfo));
}
public function confirmStatus()
{
return $this->data(YejiStatsLogic::commissionSettlementConfirmStatus($this->request->get(), $this->adminId, $this->adminInfo));
}
public function saveReconcile()
{
return $this->data(YejiStatsLogic::commissionSettlementSaveReconcile($this->request->post(), $this->adminId, $this->adminInfo));
}
public function confirmFinalize()
{
@set_time_limit(120);
return $this->data(YejiStatsLogic::commissionSettlementConfirmFinalize($this->request->post(), $this->adminId, $this->adminInfo));
}
public function confirmRevoke()
{
return $this->data(YejiStatsLogic::commissionSettlementConfirmRevoke($this->request->post(), $this->adminId, $this->adminInfo));
}
public function deptOptions()
{
return $this->data(YejiStatsLogic::deptOptions($this->adminId, $this->adminInfo));
}
public function channelOptions()
{
return $this->data(YejiStatsLogic::channelOptions(false));
}
}
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\ConversionLogic;
class ConversionController extends BaseAdminController
{
public function overview()
{
$result = ConversionLogic::overview($this->request->get(), $this->adminId, $this->adminInfo);
return $this->data($result);
}
}
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\DoctorDailyStatsLogic;
/**
* 医生日统计(系统/手动开方、成交、挂号状态、总挂号、挂号率)
*
* - GET stats.doctorDailyStats/overview
* ?start_date=&end_date=&channel_code=&dept_ids=
* dept_ids 可传逗号串或数组;选中父级会自动展开全部子级(与业绩看板部门树同口径)。
* 筛选口径:部门 → admin_dept 命中的医助集合 → 该医助经手的挂号(COALESCE(a.assistant_id,u.assistant_id)/
* 订单(o.creator_id/ 处方(tcm_diagnosis.assistant_id),再按医生(rx.creator_id / a.doctor_id)汇总;
* 显式选部门时隐藏全 0 医生行。未传日期时由后端默认当日。
*/
class DoctorDailyStatsController extends BaseAdminController
{
public function overview()
{
$params = $this->request->get();
return $this->data(DoctorDailyStatsLogic::overview($params, $this->adminId, $this->adminInfo));
}
}
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\PerformanceDashboardLogic;
/**
* 角色数据驾驶舱。
*
* 所有数据在服务端按当前管理员的数据范围聚合,前端不参与权限裁剪。
*/
class PerformanceDashboardController extends BaseAdminController
{
public function overview()
{
@set_time_limit(120);
$response = $this->data(PerformanceDashboardLogic::overview(
$this->adminId,
$this->adminInfo,
$this->request->get()
));
// 驾驶舱包含分钟级实时数据,禁止浏览器和中间代理缓存旧统计结果。
return $response->header([
'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
'Pragma' => 'no-cache',
'Expires' => '0',
]);
}
}
@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\stats\PersonalAccountCostLists;
use app\adminapi\logic\stats\PersonalAccountCostLogic;
use app\adminapi\validate\stats\PersonalAccountCostValidate;
class PersonalAccountCostController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PersonalAccountCostLists());
}
public function add()
{
$params = (new PersonalAccountCostValidate())->post()->goCheck('add');
$result = PersonalAccountCostLogic::add($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''));
if ($result === false) {
return $this->fail(PersonalAccountCostLogic::getError());
}
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new PersonalAccountCostValidate())->post()->goCheck('edit');
$result = PersonalAccountCostLogic::edit($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''), $this->adminInfo);
if ($result === false) {
return $this->fail(PersonalAccountCostLogic::getError());
}
return $this->success('编辑成功', [], 1, 1);
}
public function detail()
{
$params = (new PersonalAccountCostValidate())->goCheck('detail');
$detail = PersonalAccountCostLogic::detail((int) $params['id'], $this->adminId, $this->adminInfo);
if ($detail === []) {
return $this->fail('记录不存在或无权查看');
}
return $this->data($detail);
}
public function delete()
{
$params = (new PersonalAccountCostValidate())->post()->goCheck('delete');
$result = PersonalAccountCostLogic::delete((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PersonalAccountCostLogic::getError());
}
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\stats\PersonalYejiLists;
use app\adminapi\logic\stats\PersonalYejiLogic;
use app\adminapi\validate\stats\PersonalYejiValidate;
class PersonalYejiController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PersonalYejiLists());
}
public function add()
{
$params = (new PersonalYejiValidate())->post()->goCheck('add');
$result = PersonalYejiLogic::add($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''));
if ($result === false) {
return $this->fail(PersonalYejiLogic::getError());
}
return $this->success('添加成功', [], 1, 1);
}
public function edit()
{
$params = (new PersonalYejiValidate())->post()->goCheck('edit');
$result = PersonalYejiLogic::edit($params, $this->adminId, (string) ($this->adminInfo['name'] ?? ''), $this->adminInfo);
if ($result === false) {
return $this->fail(PersonalYejiLogic::getError());
}
return $this->success('编辑成功', [], 1, 1);
}
public function detail()
{
$params = (new PersonalYejiValidate())->goCheck('detail');
$detail = PersonalYejiLogic::detail((int) $params['id'], $this->adminId, $this->adminInfo);
if ($detail === []) {
return $this->fail('记录不存在或无权查看');
}
return $this->data($detail);
}
public function delete()
{
$params = (new PersonalYejiValidate())->post()->goCheck('delete');
$result = PersonalYejiLogic::delete((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PersonalYejiLogic::getError());
}
return $this->success('删除成功', [], 1, 1);
}
}
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\RevisitRateLogic;
/**
* 复诊接诊率统计(按月)
*
* - GET stats.revisitRate/overview 当月 N 诊接诊率(部门 → 医助分组 + 合计)
* - GET stats.revisitRate/deptOptions 部门下拉(前端组树)
* - GET stats.revisitRate/assignLines 「被指派数」明细(按诊单聚合)
* - GET stats.revisitRate/visitOrderLines 「N 诊单数」订单明细
*/
class RevisitRateController extends BaseAdminController
{
public function overview()
{
// 涉及指派日志 + 全量订单序列扫描,放宽执行时间兜底
@set_time_limit(120);
$params = $this->request->get();
return $this->data(RevisitRateLogic::overview($params));
}
public function deptOptions()
{
return $this->data(RevisitRateLogic::deptOptions());
}
/** 「被指派数」点击下钻:诊单维度明细 */
public function assignLines()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(RevisitRateLogic::assignLines($params));
}
/** 「N 诊单数」点击下钻:具体订单明细 */
public function visitOrderLines()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(RevisitRateLogic::visitOrderLines($params));
}
}
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\SelfInputLogic;
class SelfInputController extends BaseAdminController
{
public function overview()
{
$result = SelfInputLogic::overview($this->request->get(), $this->adminId, $this->adminInfo);
return $this->data($result);
}
/**
* 自媒体来源下拉:从已录入业绩/账户消耗去重提取(随录入动态变化)
*/
public function mediaSourceOptions()
{
$list = SelfInputLogic::mediaSourceOptions($this->adminId, $this->adminInfo);
return $this->data($list);
}
}
@@ -0,0 +1,154 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\stats;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\stats\YejiStatsLogic;
/**
* 业绩看板(部门 × 时间区间)控制器
*
* - GET stats.yejiStats/overview 单区间
* - GET stats.yejiStats/multi 多区间一次返回(默认 月/周/今日/昨日 四张表)
* - GET stats.yejiStats/deptOptions 部门下拉
* - GET stats.yejiStats/leaderboard 医助排行榜(按展示部门分表)
* - GET stats.yejiStats/leadLines 进线数据明细(add_external_contact 逐条)
* - GET stats.yejiStats/appointmentLines 医助排行榜「预约诊单」挂号逐条明细
* - GET stats.yejiStats/revisitBreakdown 二中心复诊下钻:医助 × 业务订单笔数
* - GET stats.yejiStats/assignLines 被指派数明细(医助×诊单去重,与看板同口径)
*/
class YejiStatsController extends BaseAdminController
{
public function overview()
{
// 业绩看板涉及多张大表 + 标签穿透计算,单 30s 上限不够;放宽到 120s 兜底
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::overview($params, $this->adminId, $this->adminInfo));
}
/**
* 一次返回 4 个时间区间的数据,对应前端 4 张表。
* 默认区间(不传 ranges 时):当月、当周(周一→今天)、今日、昨日。
* ranges 也可由前端自定义传入:[{label:..., start_date:..., end_date:...}]
*/
public function multi()
{
// 4 个区间叠加,30s 上限对部分线上数据量来说过紧,放宽到 120s
@set_time_limit(120);
$params = $this->request->get();
$rangesRaw = $params['ranges'] ?? null;
$today = date('Y-m-d');
$monthStart = date('Y-m-01');
// 周一为起点(PHP date('N') 1=周一)
$weekStart = date('Y-m-d', strtotime('monday this week'));
$yesterday = date('Y-m-d', strtotime('-1 day'));
$ranges = [];
if (is_array($rangesRaw) && $rangesRaw !== []) {
foreach ($rangesRaw as $r) {
if (!is_array($r)) {
continue;
}
$ranges[] = [
'label' => (string) ($r['label'] ?? ''),
'start_date' => (string) ($r['start_date'] ?? $today),
'end_date' => (string) ($r['end_date'] ?? ($r['start_date'] ?? $today)),
];
}
}
if ($ranges === []) {
$ranges = [
['label' => '本月(' . date('n') . '月)', 'start_date' => $monthStart, 'end_date' => $today],
['label' => '本周(' . substr($weekStart, 5) . '~' . substr($today, 5) . '', 'start_date' => $weekStart, 'end_date' => $today],
['label' => '今日(' . substr($today, 5) . '', 'start_date' => $today, 'end_date' => $today],
['label' => '昨日(' . substr($yesterday, 5) . '', 'start_date' => $yesterday, 'end_date' => $yesterday],
];
}
$base = [];
if (isset($params['dept_ids'])) {
$base['dept_ids'] = $params['dept_ids'];
}
if (isset($params['tag_id'])) {
$base['tag_id'] = $params['tag_id'];
}
if (isset($params['channel_code'])) {
$base['channel_code'] = $params['channel_code'];
}
return $this->data([
'ranges' => $ranges,
'tables' => YejiStatsLogic::overviewBatch($ranges, $base, $this->adminId, $this->adminInfo),
]);
}
public function deptOptions()
{
return $this->data(YejiStatsLogic::deptOptions($this->adminId, $this->adminInfo));
}
/** 渠道(标签)下拉,按 source_group_name 分组 */
public function channelOptions()
{
return $this->data(YejiStatsLogic::channelOptions());
}
/** 医助排行榜:与 overview 同筛选;日期由前端传入(多表模式下前端传「今日」单区间) */
public function leaderboard()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::assistantLeaderboards($params, $this->adminId, $this->adminInfo));
}
/** 「未归属中心」行:按诊单医助拆解业绩(与表格补差、合计业绩诊单医助归属一致) */
public function unassignedBreakdown()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::unassignedCenterBreakdown($params, $this->adminId, $this->adminInfo));
}
/** 进线数据明细:与看板「进线数据」同口径 */
public function leadLines()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::leadLineList($params, $this->adminId, $this->adminInfo));
}
/** 医助排行榜「预约诊单」:挂号记录逐条列表(与计数同口径) */
public function appointmentLines()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::leaderboardAppointmentLines($params, $this->adminId, $this->adminInfo));
}
/** 二中心复诊:按部门行 + 复诊分项拆解医助与业务订单笔数 */
public function revisitBreakdown()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::revisitDeptAssistantBreakdown($params, $this->adminId, $this->adminInfo));
}
/** 被指派数明细:与看板「被指派数」同口径(区间内非继承指派,医助×诊单去重) */
public function assignLines()
{
@set_time_limit(120);
$params = $this->request->get();
return $this->data(YejiStatsLogic::assignLines($params, $this->adminId, $this->adminInfo));
}
}
@@ -0,0 +1,92 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台(PHP版)
// +----------------------------------------------------------------------
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\tcm\BloodRecordLogic;
/**
* 血糖血压记录控制器
* Class BloodRecordController
* @package app\adminapi\controller\tcm
*/
class BloodRecordController extends BaseAdminController
{
/**
* @notes 添加记录
* @return \think\response\Json
*/
public function add()
{
$params = $this->request->post();
$result = BloodRecordLogic::add($params);
if ($result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(BloodRecordLogic::getError());
}
/**
* @notes 编辑记录
* @return \think\response\Json
*/
public function edit()
{
$params = $this->request->post();
$result = BloodRecordLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(BloodRecordLogic::getError());
}
/**
* @notes 删除记录
* @return \think\response\Json
*/
public function delete()
{
$params = $this->request->post();
$result = BloodRecordLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(BloodRecordLogic::getError());
}
/**
* @notes 记录详情
* @return \think\response\Json
*/
public function detail()
{
$params = $this->request->get();
$result = BloodRecordLogic::detail($params);
return $this->data($result);
}
/**
* @notes 获取患者的记录列表
* @return \think\response\Json
*/
public function getRecordsByPatient()
{
$params = $this->request->get();
$result = BloodRecordLogic::getRecordsByPatient($params);
return $this->data($result);
}
/**
* @notes 获取血糖趋势图数据
* @return \think\response\Json
*/
public function getBloodSugarTrend()
{
$params = $this->request->get();
$result = BloodRecordLogic::getBloodSugarTrend($params);
return $this->data($result);
}
}
@@ -0,0 +1,972 @@
<?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\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\tcm\DiagnosisLists;
use app\adminapi\logic\order\OrderActionLogLogic;
use app\adminapi\logic\tcm\DiagnosisAiLogic;
use app\adminapi\logic\tcm\DiagnosisLogic;
use app\adminapi\logic\tcm\PatientAiReportLogic;
use app\adminapi\logic\tcm\TrackingNoteLogic;
use app\adminapi\validate\tcm\DiagnosisValidate;
use app\common\model\Order;
use app\common\model\WechatChatRecord;
/**
* 中医辨房病因诊单控制器
* Class DiagnosisController
* @package app\adminapi\controller\tcm
*/
class DiagnosisController extends BaseAdminController
{
/**
* @notes 测试接口
* @return \think\response\Json
*/
public function test()
{
return $this->success('中医诊单控制器可以访问', [
'controller' => 'TcmDiagnosisController',
'namespace' => __NAMESPACE__,
'class' => __CLASS__,
'method' => __METHOD__
]);
}
/**
* @notes 诊单列表
* @return \think\response\Json
*/
public function lists()
{
return $this->dataLists(new DiagnosisLists());
}
/**
* @notes 医助理诊单统计(按部门、按人)
* @return \think\response\Json
*/
public function assistantDiagnosisStats()
{
$params = $this->request->get();
$result = DiagnosisLogic::assistantDiagnosisStats($params, (int) $this->adminId, $this->adminInfo);
return $this->data($result);
}
/**
* @notes 添加诊单
* @return \think\response\Json
*/
public function add()
{
$params = (new DiagnosisValidate())->post()->goCheck('add');
// 诊单创建人(需表 zyt_tcm_diagnosis 已增加 admin_id 列,见 sql 脚本)
$params['admin_id'] = (int) $this->adminId;
$result = DiagnosisLogic::add($params);
if ($result) {
return $this->success('添加成功', ['id' => $result], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 编辑诊单
* @return \think\response\Json
*/
public function edit()
{
$params = (new DiagnosisValidate())->post()->goCheck('edit');
$result = DiagnosisLogic::edit($params, $this->adminInfo);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 设置复诊接诊率统计起始偏移(业务订单 tab)
*/
public function setRevisitSlotStartOffset()
{
$params = (new DiagnosisValidate())->post()->goCheck('setRevisitSlotStartOffset');
$ok = DiagnosisLogic::setRevisitSlotStartOffset(
(int) $params['id'],
(int) $params['revisit_slot_start_offset'],
$this->adminInfo
);
if (!$ok) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->success('保存成功');
}
/**
* @notes 删除诊单
* @return \think\response\Json
*/
public function delete()
{
$params = (new DiagnosisValidate())->post()->goCheck('id');
$result = DiagnosisLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 诊单详情
* @return \think\response\Json
*/
public function detail()
{
$params = (new DiagnosisValidate())->goCheck('id');
$result = DiagnosisLogic::detail($params, $this->adminInfo);
DiagnosisLogic::markAssignRead((int) ($params['id'] ?? 0), $this->adminId);
return $this->data($result);
}
/**
* @notes 二诊只读病例详情(患者信息 + 病例 + 跟踪记录)
*
* 路由:GET /tcm.diagnosis/readonlyDetail?id=:diagnosisId
* 权限:tcm.diagnosis/readonlyDetail
*
* @return \think\response\Json
*/
public function readonlyDetail()
{
$params = (new DiagnosisValidate())->goCheck('readonlyDetail');
$result = DiagnosisLogic::readonlyDetail($params, $this->adminId, $this->adminInfo);
if (empty($result)) {
return $this->fail(DiagnosisLogic::getError() ?: '诊单不存在或无权访问');
}
DiagnosisLogic::markAssignRead((int) ($params['id'] ?? 0), $this->adminId);
return $this->data($result);
}
/**
* @notes 跟踪信息(血糖血压 / 饮食 / 运动)—— 按日期区间 lazy load
*
* 路由:GET /tcm.diagnosis/trackingWindow?id=:diagnosisId&start_date=&end_date=
* 权限:tcm.diagnosis/readonlyDetail(与只读病例页同档;接诊台亦复用)
*
* @return \think\response\Json
*/
public function trackingWindow()
{
$params = (new DiagnosisValidate())->goCheck('trackingWindow');
$result = DiagnosisLogic::fetchTrackingWindow(
(int) $params['id'],
(string) ($params['start_date'] ?? ''),
(string) ($params['end_date'] ?? '')
);
return $this->data($result);
}
/**
* @notes 新增跟踪备注(按天合并追加,仅文字)
*
* 路由:POST /tcm.diagnosis/addTrackingNote
* 权限:tcm.diagnosis/addTrackingNote
*
* @return \think\response\Json
*/
public function addTrackingNote()
{
$params = (new DiagnosisValidate())->post()->goCheck('addTrackingNote');
$ok = TrackingNoteLogic::addOrAppend([
'diagnosis_id' => (int) $params['diagnosis_id'],
'admin_id' => (int) $this->adminId,
'content' => (string) $params['tracking_content'],
]);
if ($ok === false) {
return $this->fail(TrackingNoteLogic::getError() ?: '保存失败');
}
return $this->success('保存成功');
}
/**
* @notes 拉取跟踪备注列表(note_date DESC
*
* 路由:GET /tcm.diagnosis/trackingNotes?diagnosis_id=:diagnosisId
* 权限:tcm.diagnosis/trackingNotes
*
* @return \think\response\Json
*/
public function trackingNotes()
{
$params = (new DiagnosisValidate())->goCheck('trackingNotes');
return $this->data(TrackingNoteLogic::getByDiagnosis((int) $params['diagnosis_id']));
}
/**
* @notes 诊单挂号 / 取消挂号 操作日志(谁在何时操作)
*/
public function guahaoLogList()
{
$params = (new DiagnosisValidate())->get()->goCheck('guahaoLogList');
return $this->data(DiagnosisLogic::guahaoLogList((int) $params['id']));
}
/**
* @notes 诊单详情(患者端)
* @return \think\response\Json
*/
public function diagnosisDetail()
{
$params = $this->request->get();
if (empty($params['id'])) {
return $this->fail('诊单ID不能为空');
}
if (empty($params['user_id'])) {
return $this->fail('用户ID不能为空');
}
$result = DiagnosisLogic::diagnosisDetail($params);
if ($result) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 检查手机号是否重复
* @return \think\response\Json
*/
public function checkPhone()
{
$params = $this->request->post();
$result = DiagnosisLogic::checkPhone($params);
return $this->data($result);
}
/**
* @notes 检查身份证号是否重复
* @return \think\response\Json
*/
public function checkIdCard()
{
$params = $this->request->post();
$result = DiagnosisLogic::checkIdCard($params);
return $this->data($result);
}
/**
* @notes 补全身份证号(自动计算年龄并更新)
* @return \think\response\Json
*/
public function fillIdCard()
{
$params = (new DiagnosisValidate())->post()->goCheck('fillIdCard');
$result = DiagnosisLogic::fillIdCard($params);
if ($result) {
return $this->success('补全成功,年龄已自动更新', [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 指派医助
* @return \think\response\Json
*/
public function assign()
{
$params = $this->request->post();
// 验证参数
if (empty($params['id'])) {
return $this->fail('诊单ID不能为空');
}
if (!array_key_exists('assistant_id', $params)) {
return $this->fail('请选择医助或取消指派');
}
$result = DiagnosisLogic::assign($params);
if ($result) {
$msg = (int) ($params['assistant_id'] ?? -1) === 0 ? '已取消指派' : '指派成功';
return $this->success($msg, [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 指派医助操作记录
* @return \think\response\Json
*/
public function assignLogList()
{
$params = (new DiagnosisValidate())->goCheck('id');
$result = DiagnosisLogic::assignLogList((int) $params['id']);
return $this->data($result);
}
/**
* @notes 获取通话签名
* @return \think\response\Json
*/
public function getCallSignature()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
if (empty($params['patient_id'])) {
return $this->fail('患者ID不能为空');
}
// 传递当前管理员ID
$params['admin_id'] = $this->adminId;
$result = DiagnosisLogic::getCallSignature($params);
if ($result) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 发起通话
* @return \think\response\Json
*/
public function startCall()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
// 传递当前管理员ID
$params['admin_id'] = $this->adminId;
$result = DiagnosisLogic::startCall($params, $this->adminInfo);
if ($result !== false) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/** @notes 为当前医生的指定通话记录启动实时录音转写 */
public function startCallTranscription()
{
$params = $this->request->post();
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::startCallTranscription($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/** @notes 幂等写入当前通话的已完成转写分段 */
public function upsertCallTranscriptSegments()
{
$params = $this->request->post();
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::upsertCallTranscriptSegments($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/** @notes 完成当前通话转写并固化对话文字 */
public function finishCallTranscription()
{
$params = $this->request->post();
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::finishCallTranscription($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 结束通话
* @return \think\response\Json
*/
public function endCall()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
// 传递当前管理员ID
$params['admin_id'] = $this->adminId;
$result = DiagnosisLogic::endCall($params);
if ($result) {
return $this->success('', [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 获取通话记录
* @return \think\response\Json
*/
public function getCallRecords()
{
$params = $this->request->get();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
$result = DiagnosisLogic::getCallRecords($params);
return $this->data($result);
}
/**
* @notes 获取诊单关联的腾讯云 IM 单聊记录(admin_getroammsg
*/
public function getImChatMessages()
{
// 增加执行时间限制到 120 秒
set_time_limit(120);
$diagnosisId = (int)$this->request->get('diagnosis_id', 0);
if ($diagnosisId <= 0) {
return $this->fail('诊单ID不能为空');
}
$onlyArchived = (int)$this->request->get('only_archived', 0) === 1;
$result = DiagnosisLogic::getImChatMessagesForDiagnosis($diagnosisId, $onlyArchived);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 触发后台异步同步当前诊单的腾讯云 IM 聊天记录到本地归档表
* 请求即返回,真正的同步逻辑在 fastcgi_finish_request 之后执行
*/
public function triggerImChatSync()
{
$diagnosisId = (int)$this->request->post('diagnosis_id', 0);
if ($diagnosisId <= 0) {
$diagnosisId = (int)$this->request->get('diagnosis_id', 0);
}
if ($diagnosisId <= 0) {
return $this->fail('诊单ID不能为空');
}
register_shutdown_function(function () use ($diagnosisId) {
try {
@set_time_limit(300);
ignore_user_abort(true);
DiagnosisLogic::syncImChatArchiveForDiagnosis($diagnosisId);
} catch (\Throwable $e) {
\think\facade\Log::warning('triggerImChatSync failed', [
'diagnosis_id' => $diagnosisId,
'err' => $e->getMessage(),
]);
}
});
return $this->success('已发起后台同步,几秒后请重新加载查看', ['queued' => true]);
}
/**
* @notes 绑定 TRTC 房间号到当前诊单通话记录(便于云端录制回调关联)
* @return \think\response\Json
*/
public function bindCallRoom()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
if (empty($params['room_id'])) {
return $this->fail('房间号不能为空');
}
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::bindCallRoom($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->success('', is_array($result) ? $result : [], 1, 0);
}
/**
* @notes 接通后发起腾讯云云端混流录制(需配置 CAM 与云点播)
* @return \think\response\Json
*/
public function startCloudRecording()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::startCloudRecording($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 浏览器本地上传通话录制后,关联到通话记录(合并 recording_urls
* @return \think\response\Json
*/
public function attachLocalCallRecording()
{
$params = $this->request->post();
if (empty($params['diagnosis_id'])) {
return $this->fail('诊单ID不能为空');
}
if (empty($params['file_url'])) {
return $this->fail('文件地址不能为空');
}
$params['admin_id'] = (int)$this->adminId;
$result = DiagnosisLogic::attachLocalCallRecording($params);
if ($result) {
return $this->success('已关联录制', [], 1, 1);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 手动上传视频前,先创建一条模拟通话记录
* @return \think\response\Json
*/
public function createManualCallRecord()
{
$params = (new DiagnosisValidate())->post()->goCheck('trackingNotes');
$result = DiagnosisLogic::createManualCallRecord([
'diagnosis_id' => (int)$params['diagnosis_id'],
'admin_id' => (int)$this->adminId,
]);
if (!$result) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->success('创建成功', $result);
}
/**
* @notes 医助旁观诊单当前视频通话(TRTC 进房参数,仅拉流)
* @return \think\response\Json
*/
public function watchCall()
{
$diagnosisId = (int)$this->request->get('diagnosis_id', 0);
if ($diagnosisId <= 0) {
return $this->fail('诊单ID不能为空');
}
$result = DiagnosisLogic::getAssistantWatchRoomParams([
'diagnosis_id' => $diagnosisId,
'admin_id' => (int)$this->adminId,
]);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 获取患者通话签名(用于测试)
* @return \think\response\Json
*/
public function getDoctorSignature()
{
$params = $this->request->get();
if (empty($params['patient_id'])) {
return $this->fail('医助理ID不能为空');
}
$result = DiagnosisLogic::getDoctorSignature((int)$params['patient_id']);
if ($result) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 获取患者通话签名(用于测试)
* @return \think\response\Json
*/
public function getPatientSignature()
{
$params = $this->request->get();
if (empty($params['patient_id'])) {
return $this->fail('患者ID不能为空');
}
$result = DiagnosisLogic::getPatientSignature((int)$params['patient_id']);
if ($result) {
return $this->data($result);
}
return $this->fail(DiagnosisLogic::getError());
}
/**
* @notes 获取医助列表
* @return \think\response\Json
*/
public function getAssistants()
{
$result = DiagnosisLogic::getAssistants((int) $this->adminId, $this->adminInfo);
return $this->data($result);
}
/**
* @notes 获取医生列表
* @return \think\response\Json
*/
public function getDoctors()
{
$result = DiagnosisLogic::getDoctors();
return $this->data($result);
}
/**
* @notes 生成小程序码
* @return \think\response\Json
*/
public function generateMiniProgramQrcode()
{
$params = (new DiagnosisValidate())->post()->goCheck('generateQrcode');
$result = DiagnosisLogic::generateMiniProgramQrcode($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 生成订单小程序码
* @return \think\response\Json
*/
public function generateOrderQrcode()
{
$params = $this->request->post();
$params['share_user_id'] = $this->adminId;
$result = DiagnosisLogic::generateOrderQrcode($params);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
$orderNo = (string)($params['order_no'] ?? '');
if ($orderNo !== '') {
$po = Order::where('order_no', $orderNo)->find();
if ($po) {
OrderActionLogLogic::record(
(int)$po->id,
(int)$this->adminId,
$this->adminInfo,
'wx_qrcode',
'生成订单小程序码'
);
}
}
return $this->data($result);
}
/**
* @notes 获取企业微信聊天记录
*/
public function getWechatChatRecords()
{
$diagnosisId = $this->request->get('diagnosis_id', 0);
$patientId = $this->request->get('patient_id', 0);
$pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 20);
if (empty($diagnosisId) && empty($patientId)) {
return $this->fail('诊单ID或患者ID不能都为空');
}
$query = WechatChatRecord::order('chat_time', 'desc');
if ($diagnosisId) {
$query->where('diagnosis_id', $diagnosisId);
}
if ($patientId) {
$query->where('patient_id', $patientId);
}
$count = (clone $query)->count();
$lists = $query->page($pageNo, $pageSize)->select()->toArray();
return $this->data([
'lists' => $lists,
'count' => $count,
'page_no' => $pageNo,
'page_size' => $pageSize
]);
}
/**
* @notes 添加企业微信聊天记录(手动录入/同步写入)
*/
public function addWechatChatRecord()
{
$params = $this->request->post();
if (empty($params['diagnosis_id']) && empty($params['patient_id'])) {
return $this->fail('诊单ID或患者ID不能都为空');
}
if (empty($params['content'])) {
return $this->fail('内容不能为空');
}
$adminInfo = $this->adminInfo;
$data = [
'diagnosis_id' => $params['diagnosis_id'] ?? 0,
'patient_id' => $params['patient_id'] ?? 0,
'staff_userid' => $adminInfo['work_wechat_userid'] ?? ($params['staff_userid'] ?? ''),
'staff_name' => $params['staff_name'] ?? ($adminInfo['name'] ?? ''),
'external_userid' => $params['external_userid'] ?? '',
'external_name' => $params['external_name'] ?? '',
'msg_type' => $params['msg_type'] ?? 'note',
'content' => $params['content'],
'media_url' => $params['media_url'] ?? '',
'chat_time' => $params['chat_time'] ?? time(),
'direction' => $params['direction'] ?? 0,
'create_time' => time(),
];
$record = WechatChatRecord::create($data);
return $this->success('添加成功', ['id' => $record->id]);
}
/**
* @notes 删除企业微信聊天记录
*/
public function deleteWechatChatRecord()
{
$id = $this->request->post('id', 0);
if (empty($id)) {
return $this->fail('记录ID不能为空');
}
WechatChatRecord::destroy($id);
return $this->success('删除成功');
}
/**
* @notes 同步企业微信外部联系人信息(查找该患者在企业微信中的跟进人)
*/
public function getWechatExternalContact()
{
$patientId = $this->request->get('patient_id', 0);
if (empty($patientId)) {
return $this->fail('患者ID不能为空');
}
$result = DiagnosisLogic::getWechatExternalContact($patientId);
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 获取会话内容存档开启的成员列表
*/
public function getMsgAuditPermitUsers()
{
$result = DiagnosisLogic::getMsgAuditPermitUsers();
if ($result === false) {
return $this->fail(DiagnosisLogic::getError());
}
return $this->data($result);
}
/**
* @notes 搜索患者(用于创建订单等场景)
* @return \think\response\Json
*/
public function searchPatient()
{
$keyword = $this->request->get('keyword', '');
$page_no = $this->request->get('page_no', 1);
$page_size = $this->request->get('page_size', 10);
if (empty($keyword)) {
return $this->success('', ['lists' => [], 'count' => 0]);
}
$offset = ($page_no - 1) * $page_size;
$lists = \app\common\model\tcm\Diagnosis::where('patient_name|phone|id_card', 'like', '%' . $keyword . '%')
->field(['id', 'patient_name', 'phone', 'id_card', 'gender', 'age'])
->limit($offset, $page_size)
->order('id desc')
->select()
->toArray();
$count = \app\common\model\tcm\Diagnosis::where('patient_name|phone|id_card', 'like', '%' . $keyword . '%')
->count();
return $this->success('', [
'lists' => $lists,
'count' => $count,
'page_no' => $page_no,
'page_size' => $page_size
]);
}
/**
* @notes 读取已保存的双模型诊单 AI 报告,不触发上游调用
*/
public function aiReports()
{
$params = (new DiagnosisValidate())->get()->goCheck('aiReports');
$reports = DiagnosisAiLogic::getSavedReports(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($reports === null) {
return $this->fail(DiagnosisAiLogic::getError());
}
return $this->data($reports);
}
/**
* @notes 基于当前授权诊单向 AI 助手提问,不接收客户端上游配置
*/
public function aiAssistant()
{
$params = (new DiagnosisValidate())->post()->goCheck('aiAssistant');
$result = DiagnosisAiLogic::assistant(
(int) $params['id'],
(string) $params['task'],
(string) ($params['prompt'] ?? ''),
$this->adminId,
$this->adminInfo
);
if ($result === null) {
return $this->fail(DiagnosisAiLogic::getError());
}
return $this->data($result);
}
/**
* @notes 对当前授权诊单生成一次结构化 AI 智能分析,仅接受 qwen/openai 模型键
*/
public function aiAnalysis()
{
$params = (new DiagnosisValidate())->post()->goCheck('aiAnalysis');
$result = DiagnosisAiLogic::analysis(
(int) $params['id'],
$this->adminId,
$this->adminInfo,
(string) ($params['model'] ?? 'qwen')
);
if ($result === null) {
return $this->fail(DiagnosisAiLogic::getError());
}
return $this->data($result);
}
/**
* @notes 查询患者级 AI 诊断报告全部历史及各模型最新版本,不触发模型调用
*/
public function patientAiReports()
{
$params = (new DiagnosisValidate())->get()->goCheck('patientAiReports');
$result = PatientAiReportLogic::reports(
(int) $params['patient_id'],
$this->adminId,
$this->adminInfo
);
if ($result === null) {
return $this->fail(PatientAiReportLogic::getError());
}
return $this->data($result);
}
/**
* @notes 聚合当前数据域内患者纵向资料,调用指定固定模型并新增一份不可变报告快照
*/
public function generatePatientAiReport()
{
$params = (new DiagnosisValidate())->post()->goCheck('generatePatientAiReport');
$result = PatientAiReportLogic::generate(
(int) $params['patient_id'],
(string) $params['model'],
$this->adminId,
$this->adminInfo
);
if ($result === null) {
return $this->fail(PatientAiReportLogic::getError());
}
return $this->data($result);
}
/**
* @notes 整份重新生成两个固定模型的诊单 AI 报告并保存成功项
*/
public function generateAiReports()
{
$params = (new DiagnosisValidate())->post()->goCheck('generateAiReports');
$reports = DiagnosisAiLogic::generateAll(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($reports === null) {
return $this->fail(DiagnosisAiLogic::getError());
}
return $this->data($reports);
}
/**
* @notes 编辑一份已保存的诊单 AI 报告
*/
public function editAiReport()
{
$params = (new DiagnosisValidate())->post()->goCheck('editAiReport');
$report = DiagnosisAiLogic::editReport(
(int) $params['id'],
(int) $params['report_id'],
$params['content'] ?? null,
$this->adminId,
$this->adminInfo
);
if ($report === null) {
return $this->fail(DiagnosisAiLogic::getError());
}
return $this->data($report);
}
}
@@ -0,0 +1,81 @@
<?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\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\tcm\DiagnosisTodoLists;
use app\adminapi\logic\tcm\DiagnosisTodoLogic;
use app\adminapi\validate\tcm\DiagnosisTodoValidate;
/**
* 诊单待办事项控制器
*
* 职责:仅 lists / add / cancel / detail;编辑能力故意不开放(要改 = 取消重建)
*
* @package app\adminapi\controller\tcm
*/
class DiagnosisTodoController extends BaseAdminController
{
/**
* @notes 待办列表(按 diagnosis_id
*/
public function lists()
{
(new DiagnosisTodoValidate())->goCheck('list');
return $this->dataLists(new DiagnosisTodoLists());
}
/**
* @notes 新增待办
*/
public function add()
{
$params = (new DiagnosisTodoValidate())->post()->goCheck('add');
$result = DiagnosisTodoLogic::add($params, $this->adminId, $this->adminInfo);
if (!$result) {
return $this->fail(DiagnosisTodoLogic::getError() ?: '创建失败');
}
return $this->success('创建成功', [], 1, 1);
}
/**
* @notes 取消待办(仅 status=0 可取消,仅创建人/超管)
*/
public function cancel()
{
$params = (new DiagnosisTodoValidate())->post()->goCheck('cancel');
$result = DiagnosisTodoLogic::cancel((int) $params['id'], $this->adminId);
if (!$result) {
return $this->fail(DiagnosisTodoLogic::getError() ?: '取消失败');
}
return $this->success('已取消', [], 1, 1);
}
/**
* @notes 待办详情
*/
public function detail()
{
$params = (new DiagnosisTodoValidate())->goCheck('detail');
$result = DiagnosisTodoLogic::detail((int) $params['id'], $this->adminId);
return $this->data($result);
}
}
@@ -0,0 +1,53 @@
<?php
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\tcm\DietRecordLogic;
class DietRecordController extends BaseAdminController
{
public function add()
{
$params = $this->request->post();
$result = DietRecordLogic::add($params);
if ($result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(DietRecordLogic::getError());
}
public function edit()
{
$params = $this->request->post();
$result = DietRecordLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(DietRecordLogic::getError());
}
public function delete()
{
$params = $this->request->post();
$result = DietRecordLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(DietRecordLogic::getError());
}
public function detail()
{
$params = $this->request->get();
$result = DietRecordLogic::detail($params);
return $this->data($result);
}
public function getRecordsByPatient()
{
$params = $this->request->get();
$result = DietRecordLogic::getRecordsByPatient($params);
return $this->data($result);
}
}
@@ -0,0 +1,60 @@
<?php
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\tcm\ExerciseRecordLogic;
class ExerciseRecordController extends BaseAdminController
{
public function add()
{
$params = $this->request->post();
$result = ExerciseRecordLogic::add($params);
if ($result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail(ExerciseRecordLogic::getError());
}
public function edit()
{
$params = $this->request->post();
$result = ExerciseRecordLogic::edit($params);
if ($result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail(ExerciseRecordLogic::getError());
}
public function delete()
{
$params = $this->request->post();
$result = ExerciseRecordLogic::delete($params);
if ($result) {
return $this->success('删除成功', [], 1, 1);
}
return $this->fail(ExerciseRecordLogic::getError());
}
public function detail()
{
$params = $this->request->get();
$result = ExerciseRecordLogic::detail($params);
return $this->data($result);
}
public function getRecordsByPatient()
{
$params = $this->request->get();
$result = ExerciseRecordLogic::getRecordsByPatient($params);
return $this->data($result);
}
public function getExerciseTrend()
{
$params = $this->request->get();
$result = ExerciseRecordLogic::getExerciseTrend($params);
return $this->data($result);
}
}
@@ -0,0 +1,181 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\tcm\PrescriptionLogic;
use app\adminapi\validate\tcm\PrescriptionValidate;
/**
* 中医处方单控制器
*/
class PrescriptionController extends BaseAdminController
{
/**
* @notes 处方列表
*/
public function lists()
{
return $this->dataLists(new \app\adminapi\lists\tcm\PrescriptionLists());
}
/**
* @notes 添加处方
*/
public function add()
{
$params = (new PrescriptionValidate())->post()->goCheck('add');
$params['creator_id'] = $this->adminId;
$id = PrescriptionLogic::add($params, $this->adminId);
if ($id === null) {
return $this->fail(PrescriptionLogic::getError());
}
return $this->success('保存成功', ['id' => $id]);
}
/**
* @notes 编辑处方
*/
public function edit()
{
$params = (new PrescriptionValidate())->post()->goCheck('edit');
$result = PrescriptionLogic::edit($params, $this->adminId);
if (!$result) {
return $this->fail(PrescriptionLogic::getError());
}
return $this->success('编辑成功');
}
/**
* @notes 修正处方患者姓名手机性别
*/
public function patchPatient()
{
$params = (new PrescriptionValidate())->post()->goCheck('patchPatient');
$ok = PrescriptionLogic::patchPatientContact(
(int) $params['id'],
(string) $params['patient_name'],
(string) $params['phone'],
(int) $params['gender'],
(int) $this->adminId,
$this->adminInfo
);
if (!$ok) {
return $this->fail(PrescriptionLogic::getError());
}
return $this->success('已更新');
}
/**
* @notes 删除处方
*/
public function delete()
{
$params = (new PrescriptionValidate())->post()->goCheck('delete');
$result = PrescriptionLogic::delete($params['id']);
if (!$result) {
return $this->fail(PrescriptionLogic::getError());
}
return $this->success('删除成功');
}
/**
* @notes 处方详情
*/
public function detail()
{
$params = (new PrescriptionValidate())->get()->goCheck('detail');
$detail = PrescriptionLogic::detail((int) $params['id'], (int) $this->adminId, $this->adminInfo);
if (!$detail) {
$msg = PrescriptionLogic::getError();
return $this->fail($msg !== '' ? $msg : '处方不存在');
}
return $this->data($detail);
}
/**
* @notes 审核处方(通过 / 驳回,驳回即作废)
*/
public function audit()
{
$params = (new PrescriptionValidate())->post()->goCheck('audit');
$ok = PrescriptionLogic::audit(
(int) $params['id'],
(string) $params['action'],
(string) ($params['remark'] ?? ''),
(int) $this->adminId,
$this->adminInfo
);
if (!$ok) {
return $this->fail(PrescriptionLogic::getError());
}
$msg = $params['action'] === 'reject' ? '已驳回并作废处方' : '审核通过';
$wecom = PrescriptionLogic::consumeLastAuditWecomNotify();
$data = [];
if (is_array($wecom)) {
$data['wecom_notify_ok'] = !empty($wecom['ok']);
if (empty($wecom['ok']) && !empty($wecom['message'])) {
$data['wecom_notify_hint'] = (string) $wecom['message'];
}
}
return $this->success($msg, $data);
}
/**
* @notes 根据诊单获取处方列表
*/
public function listByDiagnosis()
{
$diagnosisId = (int)($this->request->get('diagnosis_id') ?? 0);
if (!$diagnosisId) {
return $this->fail('诊单ID不能为空');
}
$list = PrescriptionLogic::listByDiagnosis($diagnosisId);
return $this->data($list);
}
/**
* @notes 根据预约获取处方
*/
public function getByAppointment()
{
$appointmentId = (int)($this->request->get('appointment_id') ?? 0);
if (!$appointmentId) {
return $this->fail('预约ID不能为空');
}
$prescription = PrescriptionLogic::getByAppointment($appointmentId, (int)$this->adminId, $this->adminInfo);
if ($prescription === null) {
$msg = PrescriptionLogic::getError();
if ($msg !== '') {
return $this->fail($msg);
}
return $this->data([]);
}
return $this->data($prescription);
}
/**
* @notes 作废处方
*/
public function void()
{
$id = (int)($this->request->post('id') ?? 0);
if (!$id) {
return $this->fail('处方ID不能为空');
}
$admin = $this->adminInfo;
$ok = PrescriptionLogic::void($id, (int)$this->adminId, $admin['name'] ?? '');
if (!$ok) {
return $this->fail(PrescriptionLogic::getError());
}
return $this->success('作废成功');
}
}
@@ -0,0 +1,151 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\logic\tcm\PrescriptionLibraryAiLogic;
use app\adminapi\logic\tcm\PrescriptionLibraryLogic;
use app\adminapi\validate\tcm\PrescriptionLibraryValidate;
/**
* 处方库控制器
*/
class PrescriptionLibraryController extends BaseAdminController
{
/**
* @notes 处方库列表
*/
public function lists()
{
return $this->dataLists(new \app\adminapi\lists\tcm\PrescriptionLibraryLists());
}
/**
* @notes 添加处方库
*/
public function add()
{
$params = (new PrescriptionLibraryValidate())->post()->goCheck('add');
$params['creator_id'] = $this->adminId;
$params['creator_name'] = $this->adminInfo['name'] ?? '';
$id = PrescriptionLibraryLogic::add($params);
if ($id === null) {
return $this->fail(PrescriptionLibraryLogic::getError());
}
return $this->success('保存成功', ['id' => $id]);
}
/**
* @notes 编辑处方库
*/
public function edit()
{
$params = (new PrescriptionLibraryValidate())->post()->goCheck('edit');
$canAll = PrescriptionLibraryLogic::canManageAllPrescriptions($this->adminId, $this->adminInfo);
$result = PrescriptionLibraryLogic::edit($params, $this->adminId, $canAll);
if (!$result) {
return $this->fail(PrescriptionLibraryLogic::getError());
}
return $this->success('编辑成功');
}
/**
* @notes 删除处方库
*/
public function delete()
{
$params = (new PrescriptionLibraryValidate())->post()->goCheck('delete');
$canAll = PrescriptionLibraryLogic::canManageAllPrescriptions($this->adminId, $this->adminInfo);
$result = PrescriptionLibraryLogic::delete((int) $params['id'], $this->adminId, $canAll);
if (!$result) {
return $this->fail(PrescriptionLibraryLogic::getError());
}
return $this->success('删除成功');
}
/**
* @notes 处方库详情
*/
public function detail()
{
$params = (new PrescriptionLibraryValidate())->get()->goCheck('detail');
$canAll = PrescriptionLibraryLogic::canManageAllPrescriptions($this->adminId, $this->adminInfo);
$detail = PrescriptionLibraryLogic::detail((int) $params['id'], $this->adminId, $canAll);
if (!$detail) {
return $this->fail('处方不存在或无权限查看');
}
return $this->data($detail);
}
/**
* @notes 读取已保存的双模型 AI 解释,不触发上游调用
*/
public function aiReports()
{
$params = (new PrescriptionLibraryValidate())->get()->goCheck('aiReports');
$reports = PrescriptionLibraryAiLogic::getSavedReports(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($reports === null) {
return $this->fail(PrescriptionLibraryAiLogic::getError());
}
return $this->data($reports);
}
/**
* @notes 查询当前数据范围内完全没有 AI 报告的处方,不触发上游调用
*/
public function missingAiReports()
{
$params = (new PrescriptionLibraryValidate())->get()->goCheck('missingAiReports');
$result = PrescriptionLibraryAiLogic::getMissingReports(
(int) ($params['limit'] ?? 500),
$this->adminId,
$this->adminInfo
);
if ($result === null) {
return $this->fail(PrescriptionLibraryAiLogic::getError());
}
return $this->data($result);
}
/**
* @notes 整份重新生成两个固定模型的 AI 解释并保存成功项
*/
public function generateAiReports()
{
$params = (new PrescriptionLibraryValidate())->post()->goCheck('generateAiReports');
$reports = PrescriptionLibraryAiLogic::generateAll(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($reports === null) {
return $this->fail(PrescriptionLibraryAiLogic::getError());
}
return $this->data($reports);
}
/**
* @notes 编辑一份已保存的 AI 解释
*/
public function editAiReport()
{
$params = (new PrescriptionLibraryValidate())->post()->goCheck('editAiReport');
$report = PrescriptionLibraryAiLogic::editReport(
(int) $params['id'],
(int) $params['report_id'],
$params['content'] ?? null,
$this->adminId,
$this->adminInfo
);
if ($report === null) {
return $this->fail(PrescriptionLibraryAiLogic::getError());
}
return $this->data($report);
}
}
@@ -0,0 +1,560 @@
<?php
declare(strict_types=1);
namespace app\adminapi\controller\tcm;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\tcm\PrescriptionOrderLists;
use app\adminapi\logic\order\OrderLogic;
use app\adminapi\logic\tcm\PrescriptionOrderLogic;
use app\adminapi\validate\tcm\PrescriptionOrderValidate;
/**
* 处方业务订单(非支付单)
*/
class PrescriptionOrderController extends BaseAdminController
{
public function lists()
{
return $this->dataLists(new PrescriptionOrderLists());
}
/**
* 处方业务订单导出(与 lists 相同筛选条件,Excel;参数 export=1 预估 export=2 下载)
*/
public function export()
{
return $this->dataLists(new PrescriptionOrderLists());
}
/**
* 指定诊单下可关联的支付单(待支付/已支付,创建/编辑业务订单时多选关联)
*/
public function paidPayOrders()
{
$params = (new PrescriptionOrderValidate())->get()->goCheck('paidPayOrders');
$exceptPo = (int) $this->request->get('prescription_order_id', 0);
$lists = OrderLogic::listPaidOrdersForDiagnosis(
(int) $params['diagnosis_id'],
$this->adminId,
$this->adminInfo,
$exceptPo > 0 ? $exceptPo : null
);
$min = PrescriptionOrderLogic::depositMinAmount();
// if ($min > 0) {
// $lists = array_values(array_filter(
// $lists,
// static fn(array $r): bool => round((float) ($r['amount'] ?? 0), 2) >= $min
// ));
// }
return $this->success('', [
'lists' => $lists,
'deposit_min_amount' => $min,
]);
}
public function create()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('create');
$result = PrescriptionOrderLogic::create($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('创建成功', $result);
}
public function detail()
{
$params = (new PrescriptionOrderValidate())->get()->goCheck('detail');
$detail = PrescriptionOrderLogic::detail((int) $params['id'], $this->adminId, $this->adminInfo);
if ($detail === null) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->data($detail);
}
/**
* 快递轨迹查询(对接快递100;未配置时仍可跳转顺丰/京东官网)
*/
public function logisticsTrace()
{
$params = (new PrescriptionOrderValidate())->get()->goCheck('logisticsTrace');
$expressOverride = trim((string) $this->request->get('express_company', ''));
$phoneTail = trim((string) ($params['phone_tail'] ?? ''));
$data = PrescriptionOrderLogic::logisticsTrace(
(int) $params['id'],
$expressOverride,
$this->adminId,
$this->adminInfo,
$phoneTail
);
if ($data === null) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('', $data);
}
/**
* 直接调用京东官方物流接口刷新轨迹并落库(绕过快递100缓存)
*/
public function logisticsJdUpdate()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('logisticsJdUpdate');
$data = PrescriptionOrderLogic::logisticsJdUpdate(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($data === null) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success((string) ($data['message'] ?? '京东物流轨迹已更新'), $data);
}
public function edit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('edit');
$result = PrescriptionOrderLogic::edit($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('保存成功', $result);
}
/**
* 仅修改承运商与快递单号,不受订单履约状态或远端药房快照锁限制。
*/
public function ddcode()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('ddcode');
$result = PrescriptionOrderLogic::ddcode(
(int) $params['id'],
(string) ($params['express_company'] ?? 'auto'),
(string) $params['tracking_number'],
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('快递单号已保存', $result);
}
public function updateAmount()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
$result = PrescriptionOrderLogic::updateAmount($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('修改成功');
}
/**
* 设置发货类型(甘草 / 洛阳)
*/
public function setShipMode()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('setShipMode');
$result = PrescriptionOrderLogic::setShipMode(
(int) $params['id'],
(string) ($params['ship_mode'] ?? 'gancao'),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('已保存', $result);
}
/**
* 人工核对甘草不确定提交:确认远端成功或确认未创建。
*/
public function confirmGancaoSubmission()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('confirmGancaoSubmission');
$result = PrescriptionOrderLogic::confirmGancaoSubmission(
(int) $params['id'],
(string) $params['resolution'],
(string) ($params['remote_order_no'] ?? ''),
(string) $params['note'],
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('甘草提交核对已记录', $result);
}
/**
* 修改关联处方的患者姓名与手机号(订单详情场景)
*/
public function patchPrescriptionPatient()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('patchPrescriptionPatient');
$ok = PrescriptionOrderLogic::patchPrescriptionPatient(
(int) $params['id'],
(string) $params['patient_name'],
(string) $params['phone'],
$this->adminId,
$this->adminInfo
);
if (!$ok) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('保存成功');
}
/**
* 修改关联处方服用参数(主方/辅方次数与开立天数)及订单服用天数
*/
public function patchPrescriptionUsage()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('patchPrescriptionUsage');
$ok = PrescriptionOrderLogic::patchPrescriptionUsage($params, $this->adminId, $this->adminInfo);
if (!$ok) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('保存成功');
}
public function auditPrescription()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPrescription');
$result = PrescriptionOrderLogic::auditPrescription(
(int) $params['id'],
(string) $params['action'],
(string) ($params['remark'] ?? ''),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
/**
* 撤回处方审核
*/
public function revokeRxAudit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
$result = PrescriptionOrderLogic::revokeRxAudit(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('处方审核已撤回', $result);
}
public function auditPayment()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPayment');
$result = PrescriptionOrderLogic::auditPaymentSlip(
(int) $params['id'],
(string) $params['action'],
(string) ($params['remark'] ?? ''),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
/**
* 撤回支付单审核
*/
public function revokePayAudit()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
$result = PrescriptionOrderLogic::revokePayAudit(
(int) $params['id'],
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('支付单审核已撤回', $result);
}
/**
* 确认发货:将履约状态推进到 5(已发货),同时更新快递信息
*/
public function ship()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('ship');
$result = PrescriptionOrderLogic::ship(
(int) $params['id'],
(string) ($params['express_company'] ?? 'auto'),
(string) ($params['tracking_number'] ?? ''),
(string) ($params['ship_mode'] ?? 'gancao'),
$this->adminId,
$this->adminInfo
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('发货成功', $result);
}
/**
* 医助/创建人撤回:仅「待双审通过」可撤(未通过或双审均驳回等仍为该状态)
*/
public function withdraw()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('withdraw');
$result = PrescriptionOrderLogic::withdraw((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('已撤回', $result);
}
/**
* @notes 批量将处方业务订单改派给其他医助(写入 creator_id 并逐单记操作日志)
*/
public function batchAssignAssistant()
{
if (!PrescriptionOrderLogic::canSeeAllPrescriptionOrders($this->adminInfo)) {
return $this->fail('无权限批量改派订单');
}
$params = $this->request->post();
$rawIds = $params['order_ids'] ?? [];
if (!\is_array($rawIds) || $rawIds === []) {
return $this->fail('请选择订单');
}
$assistantId = (int) ($params['assistant_id'] ?? 0);
$result = PrescriptionOrderLogic::batchAssignAssistant($rawIds, $assistantId, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
$msg = '已改派 ' . (int) $result['success'] . ' 单';
if (!empty($result['errors'])) {
$msg .= '' . implode('', $result['errors']);
}
return $this->success($msg, $result);
}
/**
* 获取业务订单操作日志
*/
public function logs()
{
$params = (new PrescriptionOrderValidate())->get()->goCheck('logs');
$result = PrescriptionOrderLogic::getLogs((int) $params['id'], $this->adminId, $this->adminInfo);
// 遇到没有权限或者订单不存在,逻辑里设置了 self::$error
if ($result === [] && PrescriptionOrderLogic::getError() !== '') {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('', $result);
}
/**
* 手工新增操作日志(可选同步调整处方/支付单审核状态)
*/
public function addLog()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('addLog');
$result = PrescriptionOrderLogic::addLog($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('日志已添加', $result);
}
/**
* 为「已发货」订单新增一条关联支付单,并重置支付单审核状态为待审核
*/
public function addPayOrder()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('addPayOrder');
$result = PrescriptionOrderLogic::addPayOrder($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('新增支付单成功', $result);
}
/**
* 为「已发货」订单关联已有支付单,并重置支付单审核状态为待审核
*/
public function linkPayOrder()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('linkPayOrder');
$result = PrescriptionOrderLogic::linkPayOrder($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('关联支付单成功', $result);
}
/**
* 已发货/已签收:仅提交完单申请(不新增/关联支付单),并重置支付审核为待审核
*/
public function requestCompletion()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('requestCompletion');
$result = PrescriptionOrderLogic::requestCompletion($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('完单申请已提交', $result);
}
/**
* 将「已发货」且支付审核已通过的订单标记为「已完成」
*/
public function complete()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('complete');
$result = PrescriptionOrderLogic::complete(
(int) $params['id'],
$this->adminId,
$this->adminInfo,
(int) $params['fulfillment_status']
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('操作成功', $result);
}
/**
* 业务订单退款(须填写原因;关联收款单标记已退款)
*/
public function refund()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('refund');
$rawRefundAmount = $params['refund_amount'] ?? null;
$refundAmount = ($rawRefundAmount === null || $rawRefundAmount === '')
? null
: round((float) $rawRefundAmount, 2);
$result = PrescriptionOrderLogic::refund(
(int) $params['id'],
(string) ($params['reason'] ?? ''),
$this->adminId,
$this->adminInfo,
$refundAmount
);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('退款成功', $result);
}
/**
* 甘草药管家:处方下单(CTM_PREVIEW → CTM_SUBMIT_RECIPEL
*
* @see https://apidoc.igancao.com/service-doc/scm-outer-recipel.html
*/
public function submitGancaoRecipel()
{
try {
$params = (new PrescriptionOrderValidate())->post()->goCheck('submitGancaoRecipel');
$result = PrescriptionOrderLogic::uploadToPharmacy((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
$error = PrescriptionOrderLogic::getError();
\think\facade\Log::error('submitGancaoRecipel failed', ['error' => $error, 'params' => $params]);
return $this->fail($error);
}
// 确保返回的数据是可序列化的
if (!is_array($result)) {
\think\facade\Log::error('submitGancaoRecipel result is not array', ['result' => $result]);
return $this->fail('返回数据格式错误');
}
return $this->success('药方上传成功', $result);
} catch (\Throwable $e) {
\think\facade\Log::error('submitGancaoRecipel exception', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
return $this->fail('系统错误:' . $e->getMessage());
}
}
/**
* Unified pharmacy upload. The order ship_mode decides the target.
*/
public function uploadToPharmacy()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('uploadToPharmacy');
$result = PrescriptionOrderLogic::uploadToPharmacy((int) $params['id'], $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('药方上传成功', $result);
}
/**
* 甘草药管家:预下单测试(仅 CTM_PREVIEW,不提交订单)
* 用于在编辑订单时测试价格和配置
*/
public function previewGancaoRecipel()
{
try {
$params = (new PrescriptionOrderValidate())->post()->goCheck('previewGancaoRecipel');
$result = PrescriptionOrderLogic::previewGancaoRecipel((int) $params['id'], $this->adminId, $this->adminInfo, $params);
if ($result === false) {
$error = PrescriptionOrderLogic::getError();
\think\facade\Log::error('previewGancaoRecipel failed', ['error' => $error, 'params' => $params]);
return $this->fail($error);
}
return $this->success('预下单成功', $result);
} catch (\Throwable $e) {
\think\facade\Log::error('previewGancaoRecipel exception', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
return $this->fail('系统错误:' . $e->getMessage());
}
}
}
@@ -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,120 @@
<?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 搜索用户(用于创建订单等场景)
* @return \think\response\Json
*/
public function search()
{
$keyword = $this->request->get('keyword', '');
$page_no = $this->request->get('page_no', 1);
$page_size = $this->request->get('page_size', 10);
if (empty($keyword)) {
return $this->success('', ['lists' => [], 'count' => 0]);
}
$offset = ($page_no - 1) * $page_size;
$lists = \app\common\model\user\User::where('nickname|mobile|account', 'like', '%' . $keyword . '%')
->field(['id', 'nickname', 'mobile', 'account', 'avatar'])
->limit($offset, $page_size)
->order('id desc')
->select()
->toArray();
$count = \app\common\model\user\User::where('nickname|mobile|account', 'like', '%' . $keyword . '%')
->count();
return $this->success('', [
'lists' => $lists,
'count' => $count,
'page_no' => $page_no,
'page_size' => $page_size
]);
}
}

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