;rgb:0000/0000/0000

This commit is contained in:
gr
2026-09-09 10:02:43 +08:00
640 changed files with 51641 additions and 20099 deletions
@@ -15,6 +15,7 @@
namespace app\adminapi\controller;
use app\common\cache\AdminAuthCache;
use app\common\service\DirectUploadService;
use app\common\service\UploadService;
use Exception;
@@ -86,7 +87,12 @@ class UploadController extends BaseAdminController
{
$type = trim((string)$this->request->post('type', 'video'));
try {
$result = DirectUploadService::issueCredentials($type);
$this->assertDirectUploadPermission($type);
$result = DirectUploadService::issueCredentials(
$type,
$this->adminId,
trim((string)$this->request->post('name', ''))
);
return $this->success('ok', $result);
} catch (Exception $e) {
return $this->fail($e->getMessage());
@@ -100,8 +106,10 @@ class UploadController extends BaseAdminController
public function ossConfirm()
{
try {
$type = trim((string)$this->request->post('type', 'video'));
$this->assertDirectUploadPermission($type);
$result = DirectUploadService::confirm([
'type' => trim((string)$this->request->post('type', 'video')),
'type' => $type,
'key' => trim((string)$this->request->post('key', '')),
'name' => trim((string)$this->request->post('name', '')),
'size' => (int)$this->request->post('size', 0),
@@ -115,4 +123,22 @@ class UploadController extends BaseAdminController
}
}
/**
* 安装包属于发布能力,不能沿用普通素材上传的“登录即放行”。
* @throws Exception
*/
private function assertDirectUploadPermission(string $type): void
{
if ($type !== DirectUploadService::TYPE_DESKTOP_PACKAGE
|| (int)($this->adminInfo['root'] ?? 0) === 1) {
return;
}
$permissions = (new AdminAuthCache($this->adminId))->getAdminUri() ?? [];
$permissions = array_map('strtolower', $permissions);
if (!in_array('setting.desktop_workstation/setconfig', $permissions, true)) {
throw new Exception('权限不足,无法上传医生工作站安装包');
}
}
}
@@ -5,13 +5,48 @@ 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;
use app\common\service\qywx\QywxPromotionContactApiService;
use app\common\service\qywx\QywxPromotionMediaService;
use app\common\service\qywx\QywxPromotionOperatorAccess;
class WecomPromotionController extends BaseAdminController
{
private const PAGE_PERMISSION = 'firstvisit.wecomPromotion/overview';
public function tagOptions()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->data((new QywxPromotionContactApiService())->tagOptions()));
}
public function createTag()
{
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
if (!$this->request->isPost()) {
return $this->fail('请使用 POST 创建标签');
}
$name = $this->request->post('name', '');
if (!is_string($name)) {
return $this->fail('标签名称格式不正确');
}
return $this->run(fn () => $this->data((new QywxPromotionContactApiService())->createTag($name)));
}
public function uploadWelcomeMedia()
{
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->data((new QywxPromotionMediaService())->upload(
$this->request->file('file'),
(string) $this->request->post('type', ''),
$this->adminId
)));
}
public function overview()
{
@@ -31,8 +66,25 @@ class WecomPromotionController extends BaseAdminController
if (!$this->hasPagePermission()) {
return $this->fail('权限不足');
}
$params = $this->request->post();
if ((int) ($params['id'] ?? 0) <= 0 && !$this->hasBasePagePermission()) {
return $this->fail('共享操作人只能编辑已授权方案,不能新建分流方案');
}
return $this->run(fn () => $this->success('分流方案已保存', WecomPromotionLogic::savePool(
$params,
$this->adminId,
$this->adminInfo
)));
}
public function batchUpdatePools()
{
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('分流方案配置已批量更新', WecomPromotionLogic::batchUpdatePools(
$this->request->post(),
$this->adminId,
$this->adminInfo
@@ -52,9 +104,22 @@ class WecomPromotionController extends BaseAdminController
)));
}
public function batchSetOperators()
{
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
return $this->run(fn () => $this->success('方案操作人已批量更新', WecomPromotionLogic::batchSetOperators(
$this->request->post(),
$this->adminId,
$this->adminInfo
)));
}
public function deletePool()
{
if (!$this->hasPagePermission()) {
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
@@ -108,7 +173,7 @@ class WecomPromotionController extends BaseAdminController
public function checkApiPermission()
{
if (!$this->hasPagePermission()) {
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
@@ -117,7 +182,7 @@ class WecomPromotionController extends BaseAdminController
public function syncRemoteLinks()
{
if (!$this->hasPagePermission()) {
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
$poolId = (int) $this->request->post('pool_id', 0);
@@ -145,7 +210,7 @@ class WecomPromotionController extends BaseAdminController
public function deleteRemoteLink()
{
if (!$this->hasPagePermission()) {
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
@@ -200,7 +265,7 @@ class WecomPromotionController extends BaseAdminController
public function deleteLink()
{
if (!$this->hasPagePermission()) {
if (!$this->hasBasePagePermission()) {
return $this->fail('权限不足');
}
$id = (int) $this->request->post('id', 0);
@@ -223,10 +288,11 @@ class WecomPromotionController extends BaseAdminController
private function hasPagePermission(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return QywxPromotionOperatorAccess::hasPagePermission($this->adminId, $this->adminInfo);
}
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
private function hasBasePagePermission(): bool
{
return QywxPromotionOperatorAccess::hasBasePagePermission($this->adminId, $this->adminInfo);
}
}
@@ -6,6 +6,7 @@ namespace app\adminapi\controller\order;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\order\OrderLists;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\order\OrderActionLogLogic;
use app\adminapi\logic\order\OrderLogic;
use app\adminapi\validate\order\OrderValidate;
@@ -17,6 +18,8 @@ use app\adminapi\validate\order\OrderValidate;
*/
class OrderController extends BaseAdminController
{
private const EDIT_TIME_PERMISSION = 'order.order/editTime';
/**
* @notes 订单列表
* @return \think\response\Json
@@ -341,13 +344,21 @@ class OrderController extends BaseAdminController
}
/**
* @notes 编辑订单(关联患者、订单类型)
* @notes 编辑订单(关联患者、订单类型、支付时间、创建时间
* 权限:超管或指定角色组可修改任意订单;其他用户只能修改自己创建的订单
* @return \think\response\Json
*/
public function edit()
{
$params = (new OrderValidate())->post()->goCheck('edit');
$hasTimeParams = array_key_exists('payment_time', $params)
|| array_key_exists('create_time', $params);
if ($hasTimeParams) {
if (!$this->canEditOrderTime()) {
return $this->fail('无权限修改订单支付时间或创建时间');
}
$params = (new OrderValidate())->post()->goCheck('edit_time');
}
$orderId = (int)$params['id'];
$order = \app\common\model\Order::find($orderId);
if (!$order) {
@@ -357,11 +368,15 @@ class OrderController extends BaseAdminController
return $this->fail('无权限修改此订单');
}
$result = OrderLogic::edit($orderId, $params);
$result = OrderLogic::edit($orderId, $params, $hasTimeParams);
if (!$result) {
return $this->fail(OrderLogic::getError());
}
$this->logOrderAction($orderId, 'edit', '编辑患者/订单类型等');
$this->logOrderAction(
$orderId,
'edit',
$hasTimeParams ? '编辑患者/订单类型/支付时间/创建时间等' : '编辑患者/订单类型等'
);
return $this->success('编辑成功');
}
@@ -382,6 +397,18 @@ class OrderController extends BaseAdminController
return (int)$order->creator_id === $this->adminId;
}
/**
* @notes 是否拥有支付单时间修正权限
*/
private function canEditOrderTime(): bool
{
if (!empty($this->adminInfo['root']) && (int)$this->adminInfo['root'] === 1) {
return true;
}
return in_array(self::EDIT_TIME_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
/**
* @notes 支付订单
* @return \think\response\Json
@@ -4,16 +4,19 @@ 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;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\qywx\CustomerLists;
use app\adminapi\logic\auth\AuthLogic;
use app\adminapi\logic\qywx\CustomerLogic;
use app\adminapi\validate\qywx\CustomerValidate;
/**
* 企业微信客户管理控制器
*/
class CustomerController extends BaseAdminController
{
class CustomerController extends BaseAdminController
{
private const DELETE_PERMISSION = 'qywx.customer/delete';
/**
* @notes 客户列表
*/
@@ -25,16 +28,34 @@ class CustomerController extends BaseAdminController
/**
* @notes 同步企业微信客户
*/
public function sync()
{
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);
}
return $this->success($msg, $result);
}
/**
* @notes 删除一条本地企业微信客户同步记录
*/
public function delete()
{
// 显式鉴权,避免权限菜单迁移漏执行时被通用中间件当成“未受控 URI”放行。
if (!$this->canDeleteCustomer()) {
return $this->fail('权限不足,无法删除企业微信客户');
}
$params = (new CustomerValidate())->post()->goCheck('delete');
if (!CustomerLogic::deleteCustomer((int) $params['id'])) {
return $this->fail(CustomerLogic::getError());
}
return $this->success('删除成功');
}
/**
* @notes 获取统计信息
@@ -84,13 +105,22 @@ class CustomerController extends BaseAdminController
/**
* @notes 保存同步设置
*/
public function saveSyncSettings()
public function saveSyncSettings()
{
$params = (new CustomerValidate())->post()->goCheck('syncSettings');
$result = CustomerLogic::saveSyncSettings($params);
if ($result === false) {
return $this->fail(CustomerLogic::getError());
}
return $this->success('保存成功');
}
}
return $this->success('保存成功');
}
private function canDeleteCustomer(): bool
{
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
return true;
}
return in_array(self::DELETE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
}
}
@@ -1010,13 +1010,20 @@ class DiagnosisController extends BaseAdminController
}
if ($result === null) {
$emit('error', [
'code' => 'AI_ASSISTANT_FAILED',
'message' => 'AI 助手暂时不可用,请稍后重试',
'code' => DiagnosisAiLogic::getAssistantErrorCode(),
'message' => DiagnosisAiLogic::getError(),
]);
} else {
$emit('done', $result);
}
} catch (\Throwable $e) {
\think\facade\Log::warning('diagnosis ai assistant sse failed ' . json_encode([
'diagnosis_id' => (int) ($prepared['diagnosis_id'] ?? 0),
'profile' => (string) ($prepared['profile'] ?? ''),
'task' => (string) ($prepared['task'] ?? ''),
'admin_id' => (int) ($prepared['admin_id'] ?? 0),
'exception_class' => get_class($e),
], JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE));
$emit('error', [
'code' => 'AI_ASSISTANT_FAILED',
'message' => 'AI 助手暂时不可用,请稍后重试',
@@ -425,6 +425,18 @@ class PrescriptionOrderController extends BaseAdminController
return $this->success('关联支付单成功', $result);
}
/** 解除单笔收款关联,总金额不变,同步更新已付金额和需代收。 */
public function unlinkPayOrder()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('unlinkPayOrder');
$result = PrescriptionOrderLogic::unlinkPayOrder($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('收款关联已移除,金额已同步更新', $result);
}
/**
* 已发货/已签收:仅提交完单申请(不新增/关联支付单),并重置支付审核为待审核
*/