init
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\bootstrap;
|
||||
|
||||
use app\utils\Logger;
|
||||
use Throwable;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
|
||||
class Handler extends \support\exception\Handler
|
||||
{
|
||||
public function render(Request $request, Throwable $exception): Response
|
||||
{
|
||||
Logger::error($exception->getMessage(),$exception);
|
||||
$code = $exception->getCode();
|
||||
$debug = $this->_debug ?? $this->debug;
|
||||
if ($request->expectsJson()) {
|
||||
$json = ['code' => $code ?: 500, 'msg' => $debug ? $exception->getMessage() : 'Server internal error', 'type' => 'failed'];
|
||||
$debug && $json['traces'] = (string)$exception;
|
||||
return new Response(200, ['Content-Type' => 'application/json'],
|
||||
\json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
$error = $debug ? \nl2br((string)$exception) : 'Server internal error';
|
||||
return new Response(500, [], $error);
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,9 @@ class SqlDebug implements Bootstrap
|
||||
}
|
||||
|
||||
$appPath = app_path();
|
||||
$pluginPath = dirname($appPath) . DIRECTORY_SEPARATOR . 'plugin';
|
||||
|
||||
if (Config::getInstance()->dbDebug) Db::connection()->listen(function (QueryExecuted $queryExecuted) use ($appPath) {
|
||||
if (Config::getInstance()->dbDebug) Db::connection()->listen(function (QueryExecuted $queryExecuted) use ($pluginPath, $appPath) {
|
||||
// 过滤掉 "select 1" 这类心跳检测SQL
|
||||
if (isset($queryExecuted->sql) && $queryExecuted->sql !== "select 1") {
|
||||
$bindings = $queryExecuted->bindings;
|
||||
@@ -60,7 +61,7 @@ class SqlDebug implements Bootstrap
|
||||
// 定位产生SQL的业务文件/行号/方法
|
||||
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
foreach ($traces as $trace) {
|
||||
if (isset($trace['file'], $trace['function']) && str_contains($trace['file'], $appPath)) {
|
||||
if (isset($trace['file'], $trace['function']) && (str_contains($trace['file'], $appPath) || str_contains($trace['file'], $pluginPath))) {
|
||||
// 格式化文件路径(去掉项目根目录,只保留相对路径)
|
||||
$file = str_replace(base_path(), '', $trace['file']);
|
||||
$file = ltrim($file, '/\\');
|
||||
|
||||
@@ -82,6 +82,9 @@ class Config
|
||||
public int $httpPort{
|
||||
get => $this->httpPort;
|
||||
}
|
||||
public bool $enableRequestTimeLog{
|
||||
get => $this->enableRequestTimeLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 人员检测回调函数
|
||||
@@ -112,6 +115,7 @@ class Config
|
||||
$this->httpPort = self::getIntEnv('HTTP_PORT', 8080);
|
||||
$this->zlm = new ZLMConfig();
|
||||
$this->personDetectionCallback = null;
|
||||
$this->enableRequestTimeLog = self::getBoolEnv('ENABLE_REQUEST_TIME_LOG', false);
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && $this->tcpServerProcessNum > 1) {
|
||||
$this->tcpServerProcessNum = 1;
|
||||
echo "Warning: TCP_SERVER_PROCESS_NUM set to 1 on Windows.\n";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace app\controller;
|
||||
|
||||
use app\config\Config;
|
||||
use app\utils\ModelAutoGenerator;
|
||||
use plugin\admin\app\common\ModelAutoGenerator;
|
||||
use app\zlm\ZLMClient;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
@@ -144,7 +144,7 @@ class IndexController
|
||||
|
||||
if ($httpCode !== 200 || empty($imageData)) {
|
||||
// 记录错误日志
|
||||
\app\utils\Logger::error("ZLM截图失败: HTTP {$httpCode}, 错误: {$error}, URL: {$url}");
|
||||
\plugin\admin\app\common\Logger::error("ZLM截图失败: HTTP {$httpCode}, 错误: {$error}, URL: {$url}");
|
||||
// 返回错误提示图
|
||||
return $this->generateErrorImage("截图失败: HTTP {$httpCode}");
|
||||
}
|
||||
@@ -165,7 +165,7 @@ class IndexController
|
||||
]);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
\app\utils\Logger::error("ZLM截图异常: " . $e->getMessage());
|
||||
\plugin\admin\app\common\Logger::error("ZLM截图异常: " . $e->getMessage());
|
||||
return $this->generateErrorImage("截图异常: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* AdminData 模型
|
||||
* 表说明:admin_data 数据表模型
|
||||
* 对应数据表:admin_data
|
||||
* @property int $id id(非空,主键)
|
||||
* @property int $uid uid 用户ID(非空)
|
||||
* @property string $hospital_id hospital_id 医院id(非空)
|
||||
* @property string $dept_id dept_id 科室id(非空)
|
||||
*/
|
||||
class AdminData extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'admin_data';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* OpmMwDepartment 模型
|
||||
* 表说明:opm_mw_department 数据表模型
|
||||
* 对应数据表:opm_mw_department
|
||||
* @property string $id id(非空,主键)
|
||||
* @property int $organ_id organ_id
|
||||
* @property int $sort_id sort_id
|
||||
* @property string $dept_name dept_name
|
||||
* @property string $description description
|
||||
* @property string $dept_code dept_code
|
||||
* @property string $dept_det_code dept_det_code
|
||||
* @property string $dept_det_name dept_det_name
|
||||
* @property string $coll_type coll_type 归集方式 0:本院产生,1:外院归集(默认值:1)
|
||||
* @property string $handover_code handover_code 科室的交接码,每一个科室有一个交接码
|
||||
* @property string $created_at created_at
|
||||
* @property int $collection_id collection_id
|
||||
* @property int $card_id card_id
|
||||
* @property int $storey_id storey_id 属于那栋楼
|
||||
* @property int $floor_id floor_id 属于那一层
|
||||
* @property int $is_sync is_sync 是否同步(默认值:1)
|
||||
* @property string $type type
|
||||
* @property string $report_dep_id report_dep_id
|
||||
* @property int $is_report is_report(默认值:1)
|
||||
* @property string $deptId deptId
|
||||
* @property int $s_report s_report(默认值:1)
|
||||
*/
|
||||
class OpmMwDepartment extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'opm_mw_department';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* OpmMwHospital 模型
|
||||
* 表说明:opm_mw_hospital 数据表模型
|
||||
* 对应数据表:opm_mw_hospital
|
||||
* @property string $id id(非空,主键)
|
||||
* @property int $area_id area_id
|
||||
* @property string $organ_name organ_name
|
||||
* @property string $former_name former_name
|
||||
* @property string $sql_host sql_host
|
||||
* @property string $sql_database sql_database
|
||||
* @property string $sql_port sql_port
|
||||
* @property string $sql_account sql_account
|
||||
* @property string $sql_password sql_password
|
||||
* @property string $organ_code organ_code
|
||||
* @property string $organ_level organ_level 0未定级 1一级 2二级 3三级
|
||||
* @property string $grade grade 0未定级 1甲级 2乙级
|
||||
* @property string $contacts_idcard contacts_idcard
|
||||
* @property string $phone phone
|
||||
* @property string $region_code region_code
|
||||
* @property string $address address
|
||||
* @property string $person_name person_name
|
||||
* @property string $created_at created_at
|
||||
* @property string $mobile mobile
|
||||
* @property string $push_url push_url
|
||||
* @property int $is_true is_true(默认值:1)
|
||||
* @property string $dealer dealer 经销商
|
||||
* @property string $dealer_mobile dealer_mobile 经销商联系电话
|
||||
* @property string $leader leader 医院负责人
|
||||
* @property string $leader_mobile leader_mobile 医院负责人电话
|
||||
* @property string $warranty_period warranty_period 质保期
|
||||
* @property int $is_report is_report(默认值:1)
|
||||
* @property string $url2 url2
|
||||
* @property int $is_push is_push(默认值:0)
|
||||
*/
|
||||
class OpmMwHospital extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'opm_mw_hospital';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaAdminRoles 模型
|
||||
* 表说明:管理员角色表
|
||||
* 对应数据表:wa_admin_roles
|
||||
* @property int $id id 主键(非空,主键)
|
||||
* @property int $role_id role_id 角色id(非空)
|
||||
* @property int $admin_id admin_id 管理员id(非空)
|
||||
*/
|
||||
class WaAdminRoles extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_admin_roles';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaAdmins 模型
|
||||
* 表说明:管理员表
|
||||
* 对应数据表:wa_admins
|
||||
* @property string $id id ID(非空,主键)
|
||||
* @property string $username username 用户名(非空)
|
||||
* @property string $nickname nickname 昵称(非空)
|
||||
* @property string $password password 密码(非空)
|
||||
* @property string $avatar avatar 头像(默认值:/app/admin/avatar.png)
|
||||
* @property string $email email 邮箱
|
||||
* @property string $mobile mobile 手机
|
||||
* @property string $created_at created_at 创建时间
|
||||
* @property string $updated_at updated_at 更新时间
|
||||
* @property string $login_at login_at 登录时间
|
||||
* @property int $status status 禁用
|
||||
*/
|
||||
class WaAdmins extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_admins';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaOptions 模型
|
||||
* 表说明:选项表
|
||||
* 对应数据表:wa_options
|
||||
* @property string $id id(非空,主键)
|
||||
* @property string $name name 键(非空)
|
||||
* @property string $value value 值(非空)
|
||||
* @property string $created_at created_at 创建时间(非空,默认值:2022-08-15 00:00:00)
|
||||
* @property string $updated_at updated_at 更新时间(非空,默认值:2022-08-15 00:00:00)
|
||||
*/
|
||||
class WaOptions extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_options';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaRoles 模型
|
||||
* 表说明:管理员角色
|
||||
* 对应数据表:wa_roles
|
||||
* @property string $id id 主键(非空,主键)
|
||||
* @property string $name name 角色组(非空)
|
||||
* @property string $rules rules 权限
|
||||
* @property string $created_at created_at 创建时间(非空)
|
||||
* @property string $updated_at updated_at 更新时间(非空)
|
||||
* @property string $pid pid 父级
|
||||
*/
|
||||
class WaRoles extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_roles';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaRules 模型
|
||||
* 表说明:权限规则
|
||||
* 对应数据表:wa_rules
|
||||
* @property string $id id 主键(非空,主键)
|
||||
* @property string $title title 标题(非空)
|
||||
* @property string $icon icon 图标
|
||||
* @property string $key key 标识(非空)
|
||||
* @property string $pid pid 上级菜单(默认值:0)
|
||||
* @property string $created_at created_at 创建时间(非空)
|
||||
* @property string $updated_at updated_at 更新时间(非空)
|
||||
* @property string $href href url
|
||||
* @property int $type type 类型(非空,默认值:1)
|
||||
* @property int $weight weight 排序(默认值:0)
|
||||
*/
|
||||
class WaRules extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_rules';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaUploads 模型
|
||||
* 表说明:附件
|
||||
* 对应数据表:wa_uploads
|
||||
* @property int $id id 主键(非空,主键)
|
||||
* @property string $name name 名称(非空)
|
||||
* @property string $url url 文件(非空)
|
||||
* @property int $admin_id admin_id 管理员
|
||||
* @property int $file_size file_size 文件大小(非空)
|
||||
* @property string $mime_type mime_type mime类型(非空)
|
||||
* @property int $image_width image_width 图片宽度
|
||||
* @property int $image_height image_height 图片高度
|
||||
* @property string $ext ext 扩展名(非空)
|
||||
* @property string $storage storage 存储位置(非空,默认值:local)
|
||||
* @property string $created_at created_at 上传时间
|
||||
* @property string $category category 类别
|
||||
* @property string $updated_at updated_at 更新时间
|
||||
*/
|
||||
class WaUploads extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_uploads';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* WaUsers 模型
|
||||
* 表说明:用户表
|
||||
* 对应数据表:wa_users
|
||||
* @property string $id id 主键(非空,主键)
|
||||
* @property string $username username 用户名(非空)
|
||||
* @property string $nickname nickname 昵称(非空)
|
||||
* @property string $password password 密码(非空)
|
||||
* @property string $sex sex 性别(非空,默认值:1)
|
||||
* @property string $avatar avatar 头像
|
||||
* @property string $email email 邮箱
|
||||
* @property string $mobile mobile 手机
|
||||
* @property int $level level 等级(非空,默认值:0)
|
||||
* @property string $birthday birthday 生日
|
||||
* @property float $money money 余额(元)(非空,默认值:0.00)
|
||||
* @property int $score score 积分(非空,默认值:0)
|
||||
* @property string $last_time last_time 登录时间
|
||||
* @property string $last_ip last_ip 登录ip
|
||||
* @property string $join_time join_time 注册时间
|
||||
* @property string $join_ip join_ip 注册ip
|
||||
* @property string $token token token
|
||||
* @property string $created_at created_at 创建时间
|
||||
* @property string $updated_at updated_at 更新时间
|
||||
* @property int $role role 角色(非空,默认值:1)
|
||||
* @property int $status status 禁用(非空,默认值:0)
|
||||
*/
|
||||
class WaUsers extends Model
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'wa_users';
|
||||
|
||||
/**
|
||||
* 主键字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关闭自动时间戳(如需开启请改为 true,需确保表有 create_time/update_time 字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = false;
|
||||
|
||||
/**
|
||||
* 字段严格检查(false=允许操作未定义字段)
|
||||
* @var bool
|
||||
*/
|
||||
protected $strict = false;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace app\zlm;
|
||||
|
||||
use app\config\Config;
|
||||
use app\utils\Logger;
|
||||
use plugin\admin\app\common\Logger;
|
||||
|
||||
/**
|
||||
* ZLMediaKit API 客户端
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use app\bootstrap\Handler;
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
// '' => support\exception\Handler::class,
|
||||
'' => Handler::class,
|
||||
];
|
||||
@@ -173,6 +173,13 @@ return [
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日志名称
|
||||
$logger = $record['logger'] ?? '';
|
||||
if (str_starts_with($logger, 'plugin.')) {
|
||||
$logger = preg_replace('/^plugin\.([^.]+)\./', '[$1] ', $logger);
|
||||
}
|
||||
$record['logger'] = $logger;
|
||||
|
||||
$record['Level'] = str_pad(strtoupper($record['level_name']), 5);
|
||||
return $record;
|
||||
}
|
||||
|
||||
@@ -1,395 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
use app\utils\Logger;
|
||||
|
||||
class AccessDataUtil
|
||||
{
|
||||
|
||||
|
||||
public static function admin_id(): ?int
|
||||
{
|
||||
return runCatching(fn() => admin()['id'], "无法获取到管理员登录信息")->getOrNull();
|
||||
}
|
||||
|
||||
public static function admin_username(): ?string
|
||||
{
|
||||
return runCatching(fn() => admin()['username'], "无法获取到管理员登录信息")->getOrNull();
|
||||
}
|
||||
|
||||
public static function admin_nickname(): ?string
|
||||
{
|
||||
return runCatching(fn() => admin()['nickname'], "无法获取到管理员登录信息")->getOrNull();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取&设置权限树
|
||||
*/
|
||||
public static function data_permission_tree(?array $data = null): DataPermissionInterface
|
||||
{
|
||||
// 获取 session
|
||||
try {
|
||||
$data_permission_tree = session()("data_permission_tree");
|
||||
if (!empty($data_permission_tree)) return new DataPermission($data_permission_tree);
|
||||
} catch (\Exception $e) {
|
||||
Logger::error("获取 session data_permission_tree key 失败",$e);
|
||||
}
|
||||
// 如果不存在就去数据库查表
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据权限基础接口
|
||||
* 定义所有权限类必须实现的核心方法
|
||||
*/
|
||||
interface DataPermissionInterface
|
||||
{
|
||||
/**
|
||||
* 获取权限唯一标识ID
|
||||
*/
|
||||
public function id(): int;
|
||||
|
||||
/**
|
||||
* 获取权限名称
|
||||
*/
|
||||
public function name(): string;
|
||||
|
||||
/**
|
||||
* 转为array
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 科室权限类(你需要的 DepartmentPxx)
|
||||
* 最小权限单元:管理科室下的具体权限项(如查看、编辑、删除等)
|
||||
*/
|
||||
class DepartmentPermission implements DataPermissionInterface
|
||||
{
|
||||
// 科室ID
|
||||
private int $deptId;
|
||||
// 科室名称
|
||||
private string $deptName;
|
||||
|
||||
public function __construct(int $deptId, string $deptName)
|
||||
{
|
||||
$this->deptId = $deptId;
|
||||
$this->deptName = $deptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取科室ID
|
||||
*/
|
||||
public function id(): int
|
||||
{
|
||||
return $this->deptId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取科室名称
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return $this->deptName;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = [];
|
||||
$array['id'] = $this->deptId;
|
||||
$array['name'] = $this->deptName;
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 医院权限类
|
||||
* 内部管理:多个科室权限对象(DepartmentPermission)
|
||||
*/
|
||||
class HospitalPermission implements DataPermissionInterface
|
||||
{
|
||||
// 医院ID
|
||||
private int $hospitalId;
|
||||
// 医院名称
|
||||
private string $hospitalName;
|
||||
// 科室权限集合:科室ID => DepartmentPermission对象
|
||||
private array $deptPermissions = [];
|
||||
|
||||
public function __construct(int $hospitalId, string $hospitalName)
|
||||
{
|
||||
$this->hospitalId = $hospitalId;
|
||||
$this->hospitalName = $hospitalName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取医院ID
|
||||
*/
|
||||
public function id(): int
|
||||
{
|
||||
return $this->hospitalId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取医院名称
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return $this->hospitalName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单个科室权限
|
||||
*/
|
||||
public function addDept(DepartmentPermission $deptPermission): void
|
||||
{
|
||||
$this->deptPermissions[$deptPermission->id()] = $deptPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加科室权限
|
||||
*/
|
||||
public function addDepts(array $deptPermissions): void
|
||||
{
|
||||
foreach ($deptPermissions as $dept) {
|
||||
if ($dept instanceof DepartmentPermission) {
|
||||
$this->addDept($dept);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个科室权限
|
||||
*/
|
||||
public function getDept(int $deptId): ?DepartmentPermission
|
||||
{
|
||||
return $this->deptPermissions[$deptId] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含某个科室
|
||||
*/
|
||||
public function hasDept(int $deptId): bool
|
||||
{
|
||||
return isset($this->deptPermissions[$deptId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定科室权限
|
||||
*/
|
||||
public function removeDept(int $deptId): void
|
||||
{
|
||||
unset($this->deptPermissions[$deptId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有科室权限
|
||||
*/
|
||||
public function getAllDepts(): array
|
||||
{
|
||||
return $this->deptPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有科室权限
|
||||
*/
|
||||
public function clearDepts(): void
|
||||
{
|
||||
$this->deptPermissions = [];
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = [];
|
||||
$depts = [];
|
||||
$array['id'] = $this->id();
|
||||
$array['name'] = $this->name();
|
||||
foreach ($this->deptPermissions as $deptPermission) {
|
||||
$depts[] = $deptPermission->toArray();
|
||||
}
|
||||
$array['depts'] = $depts;
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 顶级数据权限类
|
||||
*/
|
||||
class DataPermission implements DataPermissionInterface
|
||||
{
|
||||
/**
|
||||
* 从传入数组中获取的 ID 与名称
|
||||
*/
|
||||
private int $id;
|
||||
private string $name;
|
||||
|
||||
/**
|
||||
* 多医院集合:hospitalId => HospitalPermission
|
||||
*/
|
||||
private array $hospitalPermissions = [];
|
||||
|
||||
/**
|
||||
* 构造方法:接收 toArray() 输出的权限数组,自动还原为多医院对象结构
|
||||
* @param array $data_permission_tree 传入 DataPermission::toArray() 输出的数组
|
||||
*/
|
||||
public function __construct(array $data_permission_tree)
|
||||
{
|
||||
$this->clear();
|
||||
|
||||
// 读取传入的 id 和 name,不硬编码
|
||||
$this->id = isset($data_permission_tree['id']) ? (int)$data_permission_tree['id'] : 0;
|
||||
$this->name = isset($data_permission_tree['name']) ? (string)$data_permission_tree['name'] : '';
|
||||
|
||||
// 获取所有医院数组
|
||||
$hospitalList = $data_permission_tree['hospitals'] ?? [];
|
||||
if (!is_array($hospitalList) || empty($hospitalList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 循环还原所有医院 + 下属科室
|
||||
foreach ($hospitalList as $hospitalData) {
|
||||
if (
|
||||
!is_array($hospitalData)
|
||||
|| empty($hospitalData['id'])
|
||||
|| empty($hospitalData['name'])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 创建医院权限
|
||||
$hospitalId = (int)$hospitalData['id'];
|
||||
$hospitalName = (string)$hospitalData['name'];
|
||||
$hospitalPermission = new HospitalPermission($hospitalId, $hospitalName);
|
||||
|
||||
// 添加下属科室
|
||||
$deptList = $hospitalData['depts'] ?? [];
|
||||
foreach ($deptList as $deptData) {
|
||||
if (empty($deptData['id']) || empty($deptData['name'])) {
|
||||
continue;
|
||||
}
|
||||
$deptPermission = new DepartmentPermission(
|
||||
(int)$deptData['id'],
|
||||
(string)$deptData['name']
|
||||
);
|
||||
$hospitalPermission->addDept($deptPermission);
|
||||
}
|
||||
|
||||
// 存入多医院集合
|
||||
$this->hospitalPermissions[$hospitalId] = $hospitalPermission;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取顶级权限ID(来自传入数组)
|
||||
*/
|
||||
public function id(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现接口:获取顶级权限名称(来自传入数组)
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单个医院权限
|
||||
*/
|
||||
public function addHospital(HospitalPermission $hospitalPermission): void
|
||||
{
|
||||
$this->hospitalPermissions[$hospitalPermission->id()] = $hospitalPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加医院
|
||||
*/
|
||||
public function addHospitals(array $hospitalPermissions): void
|
||||
{
|
||||
foreach ($hospitalPermissions as $hospital) {
|
||||
if ($hospital instanceof HospitalPermission) {
|
||||
$this->addHospital($hospital);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个医院
|
||||
*/
|
||||
public function getHospital(int $hospitalId): ?HospitalPermission
|
||||
{
|
||||
return $this->hospitalPermissions[$hospitalId] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含某个医院
|
||||
*/
|
||||
public function hasHospital(int $hospitalId): bool
|
||||
{
|
||||
return isset($this->hospitalPermissions[$hospitalId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定医院
|
||||
*/
|
||||
public function removeHospital(int $hospitalId): void
|
||||
{
|
||||
unset($this->hospitalPermissions[$hospitalId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有医院
|
||||
*/
|
||||
public function getAllHospitals(): array
|
||||
{
|
||||
return $this->hospitalPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有医院ID
|
||||
*/
|
||||
public function getAllHospitalIds(): array
|
||||
{
|
||||
return array_keys($this->hospitalPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有医院权限
|
||||
*/
|
||||
public function has(): bool
|
||||
{
|
||||
return !empty($this->hospitalPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有医院权限
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->hospitalPermissions = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为array(完美支持构造方法还原)
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = [
|
||||
'id' => $this->id(),
|
||||
'name' => $this->name(),
|
||||
'hospitals' => []
|
||||
];
|
||||
|
||||
foreach ($this->hospitalPermissions as $hospital) {
|
||||
$array['hospitals'][] = $hospital->toArray();
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
use app\utils\Logger;
|
||||
|
||||
class ExUtil
|
||||
{
|
||||
/**
|
||||
* 执行闭包,捕获异常并记录日志,不中断程序
|
||||
* @param callable $func 要执行的逻辑
|
||||
* @param string $errorMsg 异常日志描述
|
||||
* @return mixed|null 执行结果 / 异常返回null
|
||||
*/
|
||||
public static function runCatching(callable $func, string $errorMsg = '执行异常'): mixed
|
||||
{
|
||||
try {
|
||||
return $func();
|
||||
} catch (\Throwable $e) {
|
||||
Logger::error($errorMsg, $e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,16 @@
|
||||
|
||||
namespace plugin\admin\app\controller;
|
||||
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use plugin\admin\app\common\Layui;
|
||||
use plugin\admin\app\common\Util;
|
||||
use plugin\admin\app\model\Role;
|
||||
use plugin\admin\app\model\Rule;
|
||||
use plugin\admin\app\model\Option;
|
||||
use support\exception\BusinessException;
|
||||
use support\Request;
|
||||
use plugin\admin\app\model\OpmMwDepartment;
|
||||
use plugin\admin\app\model\OpmMwHospital;
|
||||
use app\utils\Logger;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
|
||||
class TestController extends Crud
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 浏览
|
||||
* @return Response
|
||||
@@ -25,4 +21,52 @@ class TestController extends Crud
|
||||
{
|
||||
return raw_view('test/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取医院科室树形结构
|
||||
* @return Response
|
||||
*/
|
||||
public function tree(): Response
|
||||
{
|
||||
// 1. 查询所有医院
|
||||
$hospitals = OpmMwHospital::where('is_true', 1) // 只查有效医院
|
||||
->withDataPermission()
|
||||
->orderBy('id')
|
||||
->get();
|
||||
|
||||
// 2. 组装树结构
|
||||
$treeData = [];
|
||||
foreach ($hospitals as $hospital) {
|
||||
// 医院节点
|
||||
$hospitalNode = [
|
||||
'id' => $hospital->id,
|
||||
'title' => $hospital->organ_name, // 医院名称
|
||||
'children' => []
|
||||
];
|
||||
|
||||
// 3. 查询该医院下的所有科室
|
||||
$departments = OpmMwDepartment::where('organ_id', $hospital->id)
|
||||
->withDataPermission()
|
||||
->orderBy('sort_id')
|
||||
->get();
|
||||
|
||||
// 4. 组装科室节点
|
||||
foreach ($departments as $dept) {
|
||||
$hospitalNode['children'][] = [
|
||||
'id' => $dept->id,
|
||||
'title' => $dept->dept_name // 科室名称
|
||||
];
|
||||
}
|
||||
|
||||
$treeData[] = $hospitalNode;
|
||||
}
|
||||
|
||||
// 5. 返回 Layui 树需要的格式
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => 'success',
|
||||
'data' => $treeData
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
namespace plugin\admin\app\middleware;
|
||||
|
||||
use app\utils\Logger;
|
||||
use plugin\admin\api\Auth;
|
||||
use ReflectionException;
|
||||
use support\exception\BusinessException;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
|
||||
/**
|
||||
* 账户数据权限表
|
||||
*/
|
||||
class AccessDataControl implements MiddlewareInterface
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param callable $handler
|
||||
* @return Response
|
||||
* @throws ReflectionException|BusinessException
|
||||
*/
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
// 获取当前登录的管理员
|
||||
$admin = runCatching(fn() => admin(), "无法获取到管理员登录信息")->getOrNull();
|
||||
|
||||
|
||||
|
||||
|
||||
$controller = $request->controller;
|
||||
$action = $request->action;
|
||||
|
||||
$code = 0;
|
||||
$msg = '';
|
||||
if (!Auth::canAccess($controller, $action, $code, $msg)) {
|
||||
if ($request->expectsJson()) {
|
||||
$response = json(['code' => $code, 'msg' => $msg, 'data' => []]);
|
||||
} else {
|
||||
if ($code === 401) {
|
||||
$response = admin_error_401_script();
|
||||
} else {
|
||||
$request->app = '';
|
||||
$request->plugin = 'admin';
|
||||
$response = view('common/error/403')->withStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\admin\app\middleware;
|
||||
|
||||
|
||||
use app\config\Config;
|
||||
use app\utils\Logger;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* 请求耗时监测中间件
|
||||
* 记录从请求进入到响应返回的全流程耗时
|
||||
*/
|
||||
class RequestTimeMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
// 1. 请求进入时记录开始时间(微秒级,高精度)
|
||||
$startTime = microtime(true);
|
||||
if (Config::getInstance()->enableRequestTimeLog) {
|
||||
Logger::debug("{} {}", [$request->method(), $request->fullUrl()]);
|
||||
}
|
||||
// 2. 执行后续中间件/控制器业务逻辑
|
||||
$response = $handler($request);
|
||||
|
||||
if (Config::getInstance()->enableRequestTimeLog) {
|
||||
// 3. 请求处理完成后计算耗时
|
||||
$endTime = microtime(true);
|
||||
$costTime = round(($endTime - $startTime) * 1000, 2); // 转换为毫秒,保留2位小数
|
||||
|
||||
// 获取请求信息(方便日志定位)
|
||||
$requestMethod = $request->method();
|
||||
$requestUrl = $request->fullUrl();
|
||||
$clientIp = $request->getRealIp();
|
||||
|
||||
// 4. 打印耗时日志
|
||||
Logger::debug("[请求耗时] {} {} | IP: {} | 耗时: {} ms", [
|
||||
$requestMethod,
|
||||
$requestUrl,
|
||||
$clientIp,
|
||||
$costTime
|
||||
]);
|
||||
}
|
||||
|
||||
// 5. 返回响应给客户端
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,16 @@
|
||||
|
||||
namespace plugin\admin\app\model;
|
||||
|
||||
use app\utils\Logger;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use support\Db;
|
||||
use support\Model;
|
||||
|
||||
|
||||
/**
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|static withDataPermission()
|
||||
*/
|
||||
class Base extends Model
|
||||
{
|
||||
/**
|
||||
@@ -23,4 +29,185 @@ class Base extends Model
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
public function scopeWithDataPermission(Builder $query): Builder
|
||||
{
|
||||
$admin = runCatching(fn() => admin(),"无法获取登录状态")->getOrDefault([]);
|
||||
|
||||
$hospitalRaw = trim((string)($admin['hospitals'] ?? ''));
|
||||
$departmentRaw = trim((string)($admin['departments'] ?? ''));
|
||||
|
||||
if ($hospitalRaw === '*' && $departmentRaw === '*') {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$hospitalIds = $this->parseVisibleIds($hospitalRaw);
|
||||
$departmentIds = $this->parseVisibleIds($departmentRaw);
|
||||
|
||||
if (empty($hospitalIds) && empty($departmentIds)) {
|
||||
return $query->whereRaw('1 = 0');
|
||||
}
|
||||
|
||||
$baseQuery = $query->getQuery();
|
||||
|
||||
// 主表
|
||||
[$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? ''));
|
||||
|
||||
// 识别 join 里的医院/科室表别名
|
||||
$hospitalAlias = $this->findTableAlias($baseQuery, 'opm_mw_hospital');
|
||||
$departmentAlias = $this->findTableAlias($baseQuery, 'opm_mw_department');
|
||||
|
||||
Logger::debug('scopeWithDataPermission fromTable:{} fromAlias:{} hospitalAlias:{} departmentAlias:{} hospitalIds:{} departmentIds:{}', [
|
||||
$fromTable,
|
||||
$fromAlias,
|
||||
$hospitalAlias,
|
||||
$departmentAlias,
|
||||
$hospitalIds,
|
||||
$departmentIds,
|
||||
]);
|
||||
|
||||
// 1) 主表就是医院表:只加医院权限
|
||||
if ($fromTable === 'opm_mw_hospital' && $hospitalAlias) {
|
||||
if (empty($hospitalIds)) {
|
||||
return $query->whereRaw('1 = 0');
|
||||
}
|
||||
|
||||
return $query->whereIn("{$hospitalAlias}.id", $hospitalIds);
|
||||
}
|
||||
|
||||
// 2) 主表就是科室表:只加科室权限
|
||||
if ($fromTable === 'opm_mw_department' && $departmentAlias) {
|
||||
return $query->where(function (Builder $q) use ($departmentAlias, $hospitalIds, $departmentIds) {
|
||||
$has = false;
|
||||
|
||||
// 科室权限:department.id
|
||||
if (!empty($departmentIds)) {
|
||||
$q->whereIn("{$departmentAlias}.id", $departmentIds);
|
||||
$has = true;
|
||||
}
|
||||
|
||||
// 医院权限:department.organ_id
|
||||
if (!empty($hospitalIds)) {
|
||||
if ($has) {
|
||||
$q->whereIn("{$departmentAlias}.organ_id", $hospitalIds);
|
||||
} else {
|
||||
$q->orWhereIn("{$departmentAlias}.organ_id", $hospitalIds);
|
||||
}
|
||||
$has = true;
|
||||
}
|
||||
|
||||
if (!$has) {
|
||||
$q->whereRaw('1 = 0');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3) 主表不是这两个,但 join 里有它们:按别名补条件
|
||||
return $query->where(function (Builder $q) use (
|
||||
$hospitalAlias,
|
||||
$departmentAlias,
|
||||
$hospitalIds,
|
||||
$departmentIds
|
||||
) {
|
||||
$hasAny = false;
|
||||
|
||||
if ($hospitalAlias && !empty($hospitalIds)) {
|
||||
$q->whereIn("{$hospitalAlias}.id", $hospitalIds);
|
||||
$hasAny = true;
|
||||
}
|
||||
|
||||
if ($departmentAlias) {
|
||||
$q->where(function (Builder $dq) use ($departmentAlias, $hospitalIds, $departmentIds) {
|
||||
$has = false;
|
||||
|
||||
if (!empty($departmentIds)) {
|
||||
$dq->whereIn("{$departmentAlias}.id", $departmentIds);
|
||||
$has = true;
|
||||
}
|
||||
|
||||
if (!empty($hospitalIds)) {
|
||||
if ($has) {
|
||||
$dq->orWhereIn("{$departmentAlias}.organ_id", $hospitalIds);
|
||||
} else {
|
||||
$dq->whereIn("{$departmentAlias}.organ_id", $hospitalIds);
|
||||
}
|
||||
$has = true;
|
||||
}
|
||||
|
||||
if (!$has) {
|
||||
$dq->whereRaw('1 = 0');
|
||||
}
|
||||
});
|
||||
|
||||
$hasAny = true;
|
||||
}
|
||||
|
||||
if (!$hasAny) {
|
||||
$q->whereRaw('1 = 0');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 "table as t" / "table t"
|
||||
*/
|
||||
protected function parseTableAlias(string $table): array
|
||||
{
|
||||
$table = trim(str_replace('`', '', $table));
|
||||
|
||||
if ($table === '') {
|
||||
return ['', ''];
|
||||
}
|
||||
|
||||
if (stripos($table, ' as ') !== false) {
|
||||
[$name, $alias] = preg_split('/\s+as\s+/i', $table, 2);
|
||||
return [trim($name), trim($alias)];
|
||||
}
|
||||
|
||||
$parts = preg_split('/\s+/', $table);
|
||||
if (count($parts) >= 2) {
|
||||
return [trim($parts[0]), trim($parts[1])];
|
||||
}
|
||||
|
||||
return [$table, $table];
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 from / joins 中找指定表的别名
|
||||
*/
|
||||
protected function findTableAlias($baseQuery, string $tableName): ?string
|
||||
{
|
||||
[$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? ''));
|
||||
if ($fromTable === $tableName) {
|
||||
return $fromAlias;
|
||||
}
|
||||
|
||||
foreach (($baseQuery->joins ?? []) as $join) {
|
||||
[$joinTable, $joinAlias] = $this->parseTableAlias((string)($join->table ?? ''));
|
||||
if ($joinTable === $tableName) {
|
||||
return $joinAlias;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把 "1,2,3" / "1,2,3" / " 1 , 2 " 转成数组
|
||||
*/
|
||||
protected function parseVisibleIds(string $raw): array
|
||||
{
|
||||
$raw = trim($raw);
|
||||
|
||||
if ($raw === '' || $raw === '*') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$parts = preg_split('/[,\s,]+/u', $raw) ?: [];
|
||||
$parts = array_filter($parts, static fn($v) => $v !== '');
|
||||
|
||||
return array_values(array_unique(array_map('intval', $parts)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
namespace plugin\admin\app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* OpmMwDepartment 模型
|
||||
@@ -30,7 +29,7 @@ use support\Model;
|
||||
* @property string $deptId deptId
|
||||
* @property int $s_report s_report(默认值:1)
|
||||
*/
|
||||
class OpmMwDepartment extends Model
|
||||
class OpmMwDepartment extends Base
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
namespace plugin\admin\app\model;
|
||||
|
||||
use plugin\admin\app\model\Base;
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
@@ -38,7 +39,7 @@ use support\Model;
|
||||
* @property string $url2 url2
|
||||
* @property int $is_push is_push(默认值:0)
|
||||
*/
|
||||
class OpmMwHospital extends Model
|
||||
class OpmMwHospital extends Base
|
||||
{
|
||||
/**
|
||||
* 数据表名
|
||||
|
||||
@@ -2,9 +2,59 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<title>医院科室树形结构</title>
|
||||
<!-- 引入你提供的资源 -->
|
||||
<link rel="stylesheet" href="/app/admin/component/pear/css/pear.css" />
|
||||
<link rel="stylesheet" href="/app/admin/admin/css/reset.css" />
|
||||
</head>
|
||||
<body>
|
||||
iiij
|
||||
<!-- 树形结构容器 -->
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
<div id="hospitalDeptTree" style="padding: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/app/admin/component/layui/layui.js?v=2.8.12"></script>
|
||||
<script src="/app/admin/component/pear/pear.js"></script>
|
||||
<script src="/app/admin/admin/js/permission.js"></script>
|
||||
<script src="/app/admin/admin/js/common.js"></script>
|
||||
|
||||
<script>
|
||||
layui.use(['tree', 'layer', 'jquery'], function(){
|
||||
var tree = layui.tree;
|
||||
var layer = layui.layer;
|
||||
var $ = layui.jquery;
|
||||
|
||||
// 渲染医院科室树形结构
|
||||
function renderHospitalTree() {
|
||||
// 请求后端接口获取树数据
|
||||
$.get("/app/admin/test/tree", function(res){
|
||||
if(res.code === 0){
|
||||
tree.render({
|
||||
elem: '#hospitalDeptTree', // 容器ID
|
||||
data: res.data, // 树数据
|
||||
showCheckbox: false, // 不显示复选框
|
||||
onlyIconControl: true, // 仅允许图标展开/折叠
|
||||
click: function(obj){
|
||||
// 点击节点事件
|
||||
layer.msg("你选择了:" + obj.data.title);
|
||||
console.log("节点数据:", obj.data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
layer.msg(res.msg || "加载树形结构失败");
|
||||
}
|
||||
}).fail(function(){
|
||||
layer.msg("接口请求失败,请检查后端服务");
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载完成渲染树
|
||||
$(function(){
|
||||
renderHospitalTree();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,7 +12,9 @@
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use plugin\admin\app\exception\Handler;
|
||||
//use plugin\admin\app\exception\Handler;
|
||||
|
||||
use app\bootstrap\Handler;
|
||||
|
||||
return [
|
||||
'' => Handler::class,
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -13,11 +13,11 @@
|
||||
*/
|
||||
|
||||
use plugin\admin\app\middleware\AccessControl;
|
||||
use plugin\admin\app\middleware\AccessDataControl;
|
||||
use plugin\admin\app\middleware\RequestTimeMiddleware;
|
||||
|
||||
return [
|
||||
'' => [
|
||||
AccessControl::class,
|
||||
AccessDataControl::class,
|
||||
RequestTimeMiddleware::class,
|
||||
]
|
||||
];
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace tests\db;
|
||||
|
||||
use app\model\EctUser;
|
||||
use app\utils\Logger;
|
||||
use app\utils\ModelAutoGenerator;
|
||||
use plugin\admin\app\model\EctUser;
|
||||
use plugin\admin\app\common\Logger;
|
||||
use plugin\admin\app\common\ModelAutoGenerator;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use support\Db;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user