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
@@ -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
]);
}
}