i
`Merge branch 'master' into chufang-9-9
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\controller;
|
||||
|
||||
use app\adminapi\service\iam\IamLoginService;
|
||||
use think\facade\Log;
|
||||
|
||||
/** Dedicated optional endpoints: existing account and WeCom actions are untouched. */
|
||||
class IamController extends BaseAdminController
|
||||
{
|
||||
public array $notNeedLogin = ['config', 'start', 'callback', 'exchange'];
|
||||
private const COOKIE = 'ZYT_IAM_BROWSER';
|
||||
|
||||
public function config()
|
||||
{
|
||||
return $this->data(IamLoginService::settings())->header(['Cache-Control' => 'no-store']);
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
try {
|
||||
$service = new IamLoginService();
|
||||
$browser = $this->browser();
|
||||
if ($browser === '') {
|
||||
$browser = bin2hex(random_bytes(32));
|
||||
}
|
||||
setcookie(self::COOKIE, $browser, ['expires' => time() + 600, 'path' => '/adminapi/iam', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax']);
|
||||
return redirect($service->start($browser, $this->request->ip()))->header($this->privateHeaders());
|
||||
} catch (\Throwable $error) {
|
||||
return $this->back(['iam_error' => $this->message($error)]);
|
||||
}
|
||||
}
|
||||
|
||||
public function callback()
|
||||
{
|
||||
try {
|
||||
if ($this->browser() === '' || $this->request->get('error', '') !== '') {
|
||||
throw new \RuntimeException('授权已取消或浏览器状态过期,请重新登录');
|
||||
}
|
||||
$ticket = (new IamLoginService())->callback($this->browser(), (string) $this->request->get('state', ''), (string) $this->request->get('code', ''));
|
||||
return $this->back(['iam_ticket' => $ticket]);
|
||||
} catch (\Throwable $error) {
|
||||
return $this->back(['iam_error' => $this->message($error)]);
|
||||
}
|
||||
}
|
||||
|
||||
public function exchange()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return $this->fail('请使用 POST 兑换登录状态')->code(405);
|
||||
}
|
||||
try {
|
||||
if ($this->browser() === '') {
|
||||
throw new \RuntimeException('浏览器登录状态已过期,请重新登录');
|
||||
}
|
||||
$payload = (new IamLoginService())->exchange($this->browser(), (string) $this->request->post('ticket', ''), (string) $this->request->header('origin', ''));
|
||||
return $this->data($payload)->header($this->privateHeaders());
|
||||
} catch (\Throwable $error) {
|
||||
return $this->fail($this->message($error))->header($this->privateHeaders());
|
||||
}
|
||||
}
|
||||
|
||||
private function browser(): string
|
||||
{
|
||||
$value = (string) ($_COOKIE[self::COOKIE] ?? '');
|
||||
return preg_match('/^[a-f0-9]{64}$/D', $value) ? $value : '';
|
||||
}
|
||||
|
||||
private function back(array $query)
|
||||
{
|
||||
// Relative, fixed path: never derive the return origin from request headers or query strings.
|
||||
return redirect('/admin/login?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986))->header($this->privateHeaders());
|
||||
}
|
||||
|
||||
private function privateHeaders(): array
|
||||
{
|
||||
return ['Cache-Control' => 'no-store', 'Referrer-Policy' => 'no-referrer'];
|
||||
}
|
||||
|
||||
private function message(\Throwable $error): string
|
||||
{
|
||||
Log::warning('IAM login rejected: ' . get_class($error));
|
||||
$message = $error->getMessage();
|
||||
return preg_match('/^[\x{4e00}-\x{9fff}]/u', $message) ? $message : '统一账号登录失败,请重试或使用原账号登录';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\service\iam;
|
||||
|
||||
use RuntimeException;
|
||||
use app\adminapi\logic\auth\AdminLogic;
|
||||
use think\facade\Config;
|
||||
use think\facade\Db;
|
||||
|
||||
/** Local identity ledger survives IAM timeouts; no names/phones/emails are identity proofs. */
|
||||
final class IamAccountProvisioner
|
||||
{
|
||||
private $imImport;
|
||||
|
||||
public function __construct(?callable $imImport = null)
|
||||
{
|
||||
$this->imImport = $imImport ?? static function (int $id, string $name): void {
|
||||
AdminLogic::importDoctorAccountToIm($id, $name);
|
||||
};
|
||||
}
|
||||
|
||||
public static function identity(array $config, string $subject): string
|
||||
{
|
||||
return json_encode([$config['issuer'], $config['application_id'], $subject], JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
public static function validateContext(array $context, string $subject, string $applicationId): void
|
||||
{
|
||||
if (($context['applicationId'] ?? '') !== $applicationId || ($context['localIdentityKey'] ?? '') !== $subject
|
||||
|| ($context['employee']['oidcSubject'] ?? '') !== $subject || ($context['employee']['status'] ?? '') !== 'active') {
|
||||
throw new RuntimeException('当前统一账号未获得甄养堂访问权限');
|
||||
}
|
||||
}
|
||||
|
||||
public function resolve(IamOidcClient $client, array $config, string $subject): int
|
||||
{
|
||||
$context = $client->provisioning($subject);
|
||||
self::validateContext($context, $subject, $config['application_id']);
|
||||
if (($context['shouldCreateLocalAccount'] ?? null) !== true) {
|
||||
return IamLoginService::boundAdminId($context, $subject, $config['application_id']);
|
||||
}
|
||||
if (($context['externalAccountId'] ?? null) !== '') {
|
||||
throw new RuntimeException('统一账号绑定状态不一致');
|
||||
}
|
||||
$id = $this->createOrResume(self::identity($config, $subject), $context);
|
||||
// Creation is durable before the remote call. On timeout retry this SAME account, never another one.
|
||||
$client->bind($subject, $id);
|
||||
$confirmed = IamLoginService::boundAdminId($client->provisioning($subject), $subject, $config['application_id']);
|
||||
if ($confirmed !== $id) {
|
||||
throw new RuntimeException('统一账号绑定冲突,请联系管理员');
|
||||
}
|
||||
// Match AdminLogic::add's best-effort doctor IM initialization only after central confirmation.
|
||||
// importDoctorAccountToIm catches/logs provider failures; it does not grant permissions.
|
||||
($this->imImport)($id, (string) Db::name('admin')->where('id', $id)->value('name'));
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function createOrResume(string $identity, array $context): int
|
||||
{
|
||||
$key = hash('sha256', $identity);
|
||||
try {
|
||||
return Db::transaction(function () use ($key, $identity, $context): int {
|
||||
$row = Db::name('iam_local_identity')->where('identity_key', $key)->lock(true)->find();
|
||||
if ($row) {
|
||||
return $this->existing($row, $identity);
|
||||
}
|
||||
// Unique PK serializes concurrent workers, including workers on different servers.
|
||||
Db::name('iam_local_identity')->insert(['identity_key' => $key, 'identity_value' => $identity,
|
||||
'admin_id' => null, 'create_time' => time()]);
|
||||
$role = Db::name('system_role')->where('id', 2)->whereNull('delete_time')->lock(true)->find();
|
||||
if (!$role || ($role['name'] ?? '') !== '医助' || (isset($role['disable']) && (int) $role['disable'] !== 0)) {
|
||||
throw new RuntimeException('默认医助角色未就绪,请联系管理员');
|
||||
}
|
||||
// Random local login name; never adopt an existing similarly named local account.
|
||||
$account = 'iam_' . bin2hex(random_bytes(12));
|
||||
if (Db::name('admin')->where('account', $account)->find()) {
|
||||
throw new RuntimeException('新账号标识冲突,请重新登录');
|
||||
}
|
||||
$name = (string) ($context['employee']['displayName'] ?? '统一账号用户');
|
||||
$id = (int) Db::name('admin')->insertGetId([
|
||||
'account' => $account, 'name' => mb_substr($name !== '' ? $name : '统一账号用户', 0, 20),
|
||||
'password' => create_password(bin2hex(random_bytes(32)), Config::get('project.unique_identification')),
|
||||
'avatar' => (string) Config::get('project.default_image.admin_avatar', ''),
|
||||
'root' => 0, 'disable' => 0, 'is_paw' => 0, 'multipoint_login' => 0,
|
||||
'gender' => 1, 'enable_image_consult' => 1, 'enable_video_consult' => 1, 'enable_charge' => 0,
|
||||
'create_time' => time(), 'update_time' => time(),
|
||||
]);
|
||||
Db::name('admin_role')->insert(['admin_id' => $id, 'role_id' => 2]);
|
||||
Db::name('iam_local_identity')->where('identity_key', $key)->update(['admin_id' => $id]);
|
||||
return $id;
|
||||
});
|
||||
} catch (\Throwable $error) {
|
||||
// A concurrent insert may have won while our transaction rolled back. Only the exact ledger is reusable.
|
||||
$row = Db::name('iam_local_identity')->where('identity_key', $key)->find();
|
||||
if ($row) {
|
||||
return $this->existing($row, $identity);
|
||||
}
|
||||
throw $error;
|
||||
}
|
||||
}
|
||||
|
||||
private function existing(array $row, string $identity): int
|
||||
{
|
||||
if (!hash_equals((string) $row['identity_value'], $identity) || (int) $row['admin_id'] <= 0) {
|
||||
throw new RuntimeException('统一账号本地开户状态异常');
|
||||
}
|
||||
$admin = Db::name('admin')->where('id', (int) $row['admin_id'])->find();
|
||||
if (!$admin || (int) $admin['disable'] !== 0 || !empty($admin['delete_time'])) {
|
||||
throw new RuntimeException('甄养堂账号已停用,请联系管理员');
|
||||
}
|
||||
// Existing permissions and password/WeCom requirements are never rewritten.
|
||||
return (int) $row['admin_id'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\service\iam;
|
||||
|
||||
use app\adminapi\logic\LoginLogic;
|
||||
use app\common\enum\AdminTerminalEnum;
|
||||
use app\common\model\auth\Admin;
|
||||
use RuntimeException;
|
||||
use think\facade\Config;
|
||||
|
||||
final class IamLoginService
|
||||
{
|
||||
private array $config;
|
||||
private IamOidcClient $client;
|
||||
private IamLoginTransactionStore $transactions;
|
||||
|
||||
public static function settings(): array
|
||||
{
|
||||
$config = (array) Config::get('iam', []);
|
||||
$enabled = in_array(strtolower((string) ($config['enabled'] ?? '')), ['1', 'true', 'yes', 'on'], true);
|
||||
if (!$enabled) {
|
||||
return ['enabled' => false, 'loginUrl' => ''];
|
||||
}
|
||||
try {
|
||||
new IamOidcClient($config);
|
||||
$origin = self::publicOrigin($config);
|
||||
if (($config['redirect_uri'] ?? '') !== $origin . '/adminapi/iam/callback') {
|
||||
return ['enabled' => false, 'loginUrl' => ''];
|
||||
}
|
||||
return ['enabled' => true, 'loginUrl' => $origin . '/adminapi/iam/start'];
|
||||
} catch (\Throwable $error) {
|
||||
return ['enabled' => false, 'loginUrl' => ''];
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!self::settings()['enabled']) {
|
||||
throw new RuntimeException('统一账号快捷登录尚未启用,请使用原账号登录');
|
||||
}
|
||||
$this->config = (array) Config::get('iam');
|
||||
$this->client = new IamOidcClient($this->config);
|
||||
$this->transactions = new IamLoginTransactionStore(app()->getRuntimePath() . 'iam-login');
|
||||
}
|
||||
|
||||
public function start(string $browser, string $ip): string
|
||||
{
|
||||
if (!$this->transactions->allowStart($ip)) {
|
||||
throw new RuntimeException('快捷登录请求过于频繁,请稍后重试');
|
||||
}
|
||||
$state = bin2hex(random_bytes(32));
|
||||
$nonce = bin2hex(random_bytes(32));
|
||||
$verifier = bin2hex(random_bytes(32));
|
||||
$target = $this->client->authorizationUrl($state, $nonce, $verifier);
|
||||
$this->transactions->put('state', $state, $browser, ['nonce' => $nonce, 'verifier' => $verifier], 600);
|
||||
return $target;
|
||||
}
|
||||
|
||||
public function callback(string $browser, string $state, string $code): string
|
||||
{
|
||||
$transaction = $this->transactions->consume('state', $state, $browser);
|
||||
if ($code === '' || strlen($code) > 4096) {
|
||||
throw new RuntimeException('快捷登录回调无效,请重新登录');
|
||||
}
|
||||
$claims = $this->client->exchange($code, $transaction['verifier'], $transaction['nonce']);
|
||||
$this->verifiedAdmin($claims['sub']);
|
||||
$ticket = bin2hex(random_bytes(32));
|
||||
$this->transactions->put('ticket', $ticket, $browser, ['subject' => $claims['sub']], 60);
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
public function exchange(string $browser, string $ticket, string $origin): array
|
||||
{
|
||||
if ($origin !== '' && $origin !== self::publicOrigin($this->config)) {
|
||||
throw new RuntimeException('快捷登录来源无效,请重新登录');
|
||||
}
|
||||
$transaction = $this->transactions->consume('ticket', $ticket, $browser);
|
||||
// Recheck entitlement, binding and local status immediately before issuing the existing business token.
|
||||
$admin = $this->verifiedAdmin($transaction['subject']);
|
||||
return (array) (new LoginLogic())->login(['account' => $admin->account, 'terminal' => AdminTerminalEnum::PC]);
|
||||
}
|
||||
|
||||
public static function boundAdminId(array $context, string $subject, string $applicationId): int
|
||||
{
|
||||
if (($context['applicationId'] ?? '') !== $applicationId || ($context['localIdentityKey'] ?? '') !== $subject
|
||||
|| ($context['employee']['oidcSubject'] ?? '') !== $subject || ($context['employee']['status'] ?? '') !== 'active') {
|
||||
throw new RuntimeException('当前统一账号未获得甄养堂访问权限');
|
||||
}
|
||||
$rawId = $context['externalAccountId'] ?? '';
|
||||
if (!is_string($rawId) && !is_int($rawId)) {
|
||||
throw new RuntimeException('统一账号绑定格式无效,请联系管理员');
|
||||
}
|
||||
$id = (string) $rawId;
|
||||
if (!preg_match('/^[1-9][0-9]{0,9}$/D', $id) || ($context['shouldCreateLocalAccount'] ?? true) !== false) {
|
||||
throw new RuntimeException('统一账号尚未开通甄养堂账号,请联系管理员');
|
||||
}
|
||||
return (int) $id;
|
||||
}
|
||||
|
||||
private function verifiedAdmin(string $subject): Admin
|
||||
{
|
||||
$id = (new IamAccountProvisioner())->resolve($this->client, $this->config, $subject);
|
||||
$admin = Admin::findOrEmpty($id);
|
||||
if ($admin->isEmpty() || (int) $admin->disable !== 0 || !empty($admin->getData('delete_time'))) {
|
||||
throw new RuntimeException('甄养堂账号已停用,请联系管理员');
|
||||
}
|
||||
return $admin;
|
||||
}
|
||||
|
||||
private static function publicOrigin(array $config): string
|
||||
{
|
||||
$value = rtrim((string) ($config['public_url'] ?? ''), '/');
|
||||
$parts = parse_url($value);
|
||||
if (!is_array($parts) || ($parts['scheme'] ?? '') !== 'https' || empty($parts['host'])
|
||||
|| isset($parts['user']) || isset($parts['pass']) || isset($parts['query']) || isset($parts['fragment'])
|
||||
|| !empty($parts['path']) || preg_match('/[\x00-\x20\x7f\\\\]/', $value)) {
|
||||
throw new RuntimeException('IAM public origin must be fixed HTTPS');
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\service\iam;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/** Private, browser-bound, single-use state. File locks work with the existing PHP-FPM deployment. */
|
||||
final class IamLoginTransactionStore
|
||||
{
|
||||
public function __construct(private string $directory)
|
||||
{
|
||||
if (!is_dir($directory) && !mkdir($directory, 0700, true) && !is_dir($directory)) {
|
||||
throw new RuntimeException('IAM transaction storage unavailable');
|
||||
}
|
||||
}
|
||||
|
||||
public function put(string $kind, string $value, string $browser, array $payload, int $ttl): void
|
||||
{
|
||||
$handle = fopen($this->path($kind, $value), 'x');
|
||||
if ($handle === false) {
|
||||
throw new RuntimeException('IAM transaction creation failed');
|
||||
}
|
||||
try {
|
||||
chmod($this->path($kind, $value), 0600);
|
||||
$data = json_encode(['browser' => hash('sha256', $browser), 'expires' => time() + $ttl, 'payload' => $payload], JSON_THROW_ON_ERROR);
|
||||
if (fwrite($handle, $data) !== strlen($data)) {
|
||||
throw new RuntimeException('IAM transaction write failed');
|
||||
}
|
||||
} finally {
|
||||
fclose($handle);
|
||||
}
|
||||
// Only expired private IAM files are collected, and never a file held by another request.
|
||||
if (random_int(1, 20) === 1) {
|
||||
foreach (array_slice(glob($this->directory . '/*.json') ?: [], 0, 200) as $file) {
|
||||
if (filemtime($file) >= time() - 1200) {
|
||||
continue;
|
||||
}
|
||||
$lock = @fopen($file, 'r+');
|
||||
if ($lock !== false) {
|
||||
if (flock($lock, LOCK_EX | LOCK_NB)) {
|
||||
@unlink($file);
|
||||
flock($lock, LOCK_UN);
|
||||
}
|
||||
fclose($lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function consume(string $kind, string $value, string $browser): array
|
||||
{
|
||||
$handle = @fopen($this->path($kind, $value), 'r+');
|
||||
if ($handle === false) {
|
||||
throw new RuntimeException('登录状态已失效,请重新发起快捷登录');
|
||||
}
|
||||
try {
|
||||
if (!flock($handle, LOCK_EX)) {
|
||||
throw new RuntimeException('IAM transaction lock failed');
|
||||
}
|
||||
$data = json_decode(stream_get_contents($handle), true);
|
||||
if (!is_array($data) || ($data['expires'] ?? 0) <= time() || !isset($data['browser'])
|
||||
|| !hash_equals($data['browser'], hash('sha256', $browser)) || !is_array($data['payload'] ?? null)) {
|
||||
throw new RuntimeException('登录状态已失效,请重新发起快捷登录');
|
||||
}
|
||||
// Truncate under the lock before returning, so previously opened file descriptors cannot replay.
|
||||
if (!ftruncate($handle, 0) || !fflush($handle)) {
|
||||
throw new RuntimeException('IAM transaction consumption failed');
|
||||
}
|
||||
return $data['payload'];
|
||||
} finally {
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
||||
public function allowStart(string $ip): bool
|
||||
{
|
||||
$file = $this->directory . '/limit-' . hash('sha256', $ip) . '.json';
|
||||
$handle = fopen($file, 'c+');
|
||||
if ($handle === false) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
chmod($file, 0600);
|
||||
if (!flock($handle, LOCK_EX)) {
|
||||
return false;
|
||||
}
|
||||
$data = json_decode(stream_get_contents($handle), true);
|
||||
if (!is_array($data) || ($data['expires'] ?? 0) <= time()) {
|
||||
$data = ['count' => 0, 'expires' => time() + 600];
|
||||
}
|
||||
if ($data['count'] >= 20) {
|
||||
return false;
|
||||
}
|
||||
++$data['count'];
|
||||
rewind($handle);
|
||||
ftruncate($handle, 0);
|
||||
$encoded = json_encode($data, JSON_THROW_ON_ERROR);
|
||||
return fwrite($handle, $encoded) === strlen($encoded) && fflush($handle);
|
||||
} finally {
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
||||
private function path(string $kind, string $value): string
|
||||
{
|
||||
if (!in_array($kind, ['state', 'ticket'], true) || !preg_match('/^[a-f0-9]{64}$/D', $value)) {
|
||||
throw new RuntimeException('登录状态无效,请重新发起快捷登录');
|
||||
}
|
||||
return $this->directory . '/' . $kind . '-' . hash('sha256', $value) . '.json';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\adminapi\service\iam;
|
||||
|
||||
use Firebase\JWT\JWK;
|
||||
use Firebase\JWT\JWT;
|
||||
use RuntimeException;
|
||||
|
||||
/** Fixed-origin OIDC client. Transaction storage and account binding belong to the caller. */
|
||||
final class IamOidcClient
|
||||
{
|
||||
private array $config;
|
||||
private $transport;
|
||||
private ?array $discovery = null;
|
||||
|
||||
/** Transport signature: (method, url, headers, body): ['status'=>int, 'body'=>string]. */
|
||||
public function __construct(array $config, ?callable $transport = null)
|
||||
{
|
||||
foreach (['issuer', 'client_id', 'client_secret', 'redirect_uri', 'api_url', 'application_id', 'application_token'] as $key) {
|
||||
if (!isset($config[$key]) || !is_string($config[$key]) || trim($config[$key]) === '' || preg_match('/[\r\n]/', $config[$key])) {
|
||||
throw new RuntimeException('IAM configuration is incomplete');
|
||||
}
|
||||
}
|
||||
$this->config = $config;
|
||||
$this->transport = $transport;
|
||||
$this->httpsUrl($config['issuer']);
|
||||
$this->httpsUrl($config['redirect_uri']);
|
||||
$this->endpoint($config['api_url']);
|
||||
if (parse_url($config['issuer'], PHP_URL_QUERY) !== null || parse_url($config['api_url'], PHP_URL_QUERY) !== null) {
|
||||
throw new RuntimeException('IAM base URL must not contain a query');
|
||||
}
|
||||
}
|
||||
|
||||
public function authorizationUrl(string $state, string $nonce, string $verifier): string
|
||||
{
|
||||
$this->verifier($verifier);
|
||||
if (strlen($state) < 32 || strlen($nonce) < 32) {
|
||||
throw new RuntimeException('IAM state and nonce must be random transaction values');
|
||||
}
|
||||
$metadata = $this->metadata();
|
||||
return $metadata['authorization_endpoint'] . (str_contains($metadata['authorization_endpoint'], '?') ? '&' : '?') . http_build_query([
|
||||
'response_type' => 'code', 'client_id' => $this->config['client_id'],
|
||||
'redirect_uri' => $this->config['redirect_uri'], 'scope' => 'openid profile',
|
||||
'state' => $state, 'nonce' => $nonce,
|
||||
'code_challenge' => rtrim(strtr(base64_encode(hash('sha256', $verifier, true)), '+/', '-_'), '='),
|
||||
'code_challenge_method' => 'S256',
|
||||
], '', '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
|
||||
public function exchange(string $code, string $verifier, string $nonce): array
|
||||
{
|
||||
$this->verifier($verifier);
|
||||
if ($code === '' || $nonce === '') {
|
||||
throw new RuntimeException('IAM authorization response is incomplete');
|
||||
}
|
||||
$metadata = $this->metadata();
|
||||
$response = $this->request('POST', $metadata['token_endpoint'], [
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Authorization: Basic ' . base64_encode(urlencode($this->config['client_id']) . ':' . urlencode($this->config['client_secret'])),
|
||||
], http_build_query([
|
||||
'grant_type' => 'authorization_code', 'code' => $code, 'code_verifier' => $verifier,
|
||||
'redirect_uri' => $this->config['redirect_uri'],
|
||||
], '', '&', PHP_QUERY_RFC3986));
|
||||
if (!isset($response['id_token']) || !is_string($response['id_token']) || strlen($response['id_token']) > 65536) {
|
||||
throw new RuntimeException('IAM ID token is missing');
|
||||
}
|
||||
$jwks = $this->request('GET', $metadata['jwks_uri']);
|
||||
$keys = [];
|
||||
$kids = [];
|
||||
foreach ($jwks['keys'] ?? [] as $key) {
|
||||
if (is_array($key) && ($key['kty'] ?? '') === 'RSA' && ($key['alg'] ?? 'RS256') === 'RS256'
|
||||
&& ($key['use'] ?? 'sig') === 'sig' && (!isset($key['key_ops']) || in_array('verify', $key['key_ops'], true))) {
|
||||
if (!is_string($key['kid'] ?? null) || $key['kid'] === '' || isset($kids[$key['kid']])) {
|
||||
throw new RuntimeException('IAM signing key identifier is invalid');
|
||||
}
|
||||
$kids[$key['kid']] = true;
|
||||
$key['alg'] = 'RS256';
|
||||
$keys[] = $key;
|
||||
}
|
||||
}
|
||||
if ($keys === []) {
|
||||
throw new RuntimeException('IAM signing keys are unavailable');
|
||||
}
|
||||
try {
|
||||
$claims = (array) JWT::decode($response['id_token'], JWK::parseKeySet(['keys' => $keys]));
|
||||
} catch (\Throwable $error) {
|
||||
throw new RuntimeException('IAM ID token verification failed');
|
||||
}
|
||||
$aud = $claims['aud'] ?? null;
|
||||
$audiences = is_string($aud) ? [$aud] : (is_array($aud) ? $aud : []);
|
||||
$now = time();
|
||||
if (($claims['iss'] ?? null) !== $this->config['issuer']
|
||||
|| !in_array($this->config['client_id'], $audiences, true)
|
||||
|| (count($audiences) > 1 && !isset($claims['azp']))
|
||||
|| (isset($claims['azp']) && $claims['azp'] !== $this->config['client_id'])
|
||||
|| !is_string($claims['sub'] ?? null) || $claims['sub'] === ''
|
||||
|| !is_string($claims['nonce'] ?? null) || !hash_equals($nonce, $claims['nonce'])
|
||||
|| !is_int($claims['exp'] ?? null) || $claims['exp'] <= $now
|
||||
|| !is_int($claims['iat'] ?? null) || $claims['iat'] > $now
|
||||
|| (isset($claims['nbf']) && (!is_int($claims['nbf']) || $claims['nbf'] > $now))) {
|
||||
throw new RuntimeException('IAM ID token claims are invalid');
|
||||
}
|
||||
return $claims;
|
||||
}
|
||||
|
||||
public function provisioning(string $subject): array
|
||||
{
|
||||
if ($subject === '' || strlen($subject) > 512) {
|
||||
throw new RuntimeException('IAM subject is invalid');
|
||||
}
|
||||
return $this->request('GET', rtrim($this->config['api_url'], '/') . '/internal/v1/applications/'
|
||||
. rawurlencode($this->config['application_id']) . '/employees/' . rawurlencode($subject) . '/provisioning-context',
|
||||
['Authorization: Bearer ' . $this->config['application_token']]);
|
||||
}
|
||||
|
||||
public function bind(string $subject, int $adminId): array
|
||||
{
|
||||
if ($subject === '' || strlen($subject) > 512 || $adminId <= 0) {
|
||||
throw new RuntimeException('IAM binding input is invalid');
|
||||
}
|
||||
$key = hash('sha256', json_encode([$this->config['issuer'], $this->config['application_id'], $subject, $adminId], JSON_THROW_ON_ERROR));
|
||||
return $this->request('POST', rtrim($this->config['api_url'], '/') . '/internal/v1/applications/'
|
||||
. rawurlencode($this->config['application_id']) . '/bindings', [
|
||||
'Authorization: Bearer ' . $this->config['application_token'],
|
||||
'Content-Type: application/json', 'X-Request-ID: ' . bin2hex(random_bytes(16)),
|
||||
'Idempotency-Key: zyt-provision-' . $key,
|
||||
], json_encode(['employeeSubject' => $subject, 'externalAccountId' => (string) $adminId,
|
||||
'verificationMethod' => 'oidc_verified_subject_local_creation'], JSON_THROW_ON_ERROR), [201]);
|
||||
}
|
||||
|
||||
private function metadata(): array
|
||||
{
|
||||
if ($this->discovery !== null) {
|
||||
return $this->discovery;
|
||||
}
|
||||
$metadata = $this->request('GET', rtrim($this->config['issuer'], '/') . '/.well-known/openid-configuration');
|
||||
if (($metadata['issuer'] ?? null) !== $this->config['issuer']) {
|
||||
throw new RuntimeException('IAM discovery issuer mismatch');
|
||||
}
|
||||
foreach (['authorization_endpoint', 'token_endpoint', 'jwks_uri'] as $key) {
|
||||
if (!isset($metadata[$key]) || !is_string($metadata[$key])) {
|
||||
throw new RuntimeException('IAM discovery endpoint is missing');
|
||||
}
|
||||
$this->endpoint($metadata[$key]);
|
||||
}
|
||||
return $this->discovery = $metadata;
|
||||
}
|
||||
|
||||
private function verifier(string $verifier): void
|
||||
{
|
||||
if (!preg_match('/^[A-Za-z0-9._~-]{43,128}$/D', $verifier)) {
|
||||
throw new RuntimeException('IAM PKCE verifier is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
private function httpsUrl(string $url): array
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
if (!is_array($parts) || ($parts['scheme'] ?? '') !== 'https' || empty($parts['host'])
|
||||
|| isset($parts['user']) || isset($parts['pass']) || isset($parts['fragment'])
|
||||
|| preg_match('/[\x00-\x20\x7f\\\\]/', $url)) {
|
||||
throw new RuntimeException('IAM URL must be a fixed HTTPS URL');
|
||||
}
|
||||
return $parts;
|
||||
}
|
||||
|
||||
private function endpoint(string $url): void
|
||||
{
|
||||
$urlParts = $this->httpsUrl($url);
|
||||
$issuer = $this->httpsUrl($this->config['issuer']);
|
||||
if (strtolower($urlParts['host']) !== strtolower($issuer['host']) || ($urlParts['port'] ?? 443) !== ($issuer['port'] ?? 443)) {
|
||||
throw new RuntimeException('IAM endpoint origin mismatch');
|
||||
}
|
||||
}
|
||||
|
||||
private function request(string $method, string $url, array $headers = [], string $body = '', array $statuses = [200]): array
|
||||
{
|
||||
$this->endpoint($url);
|
||||
$headers[] = 'Accept: application/json';
|
||||
if ($this->transport !== null) {
|
||||
$result = ($this->transport)($method, $url, $headers, $body);
|
||||
} else {
|
||||
$curl = curl_init($url);
|
||||
$response = '';
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => false,
|
||||
CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 15,
|
||||
CURLOPT_WRITEFUNCTION => static function ($handle, string $chunk) use (&$response): int {
|
||||
if (strlen($response) + strlen($chunk) > 1048576) {
|
||||
return 0;
|
||||
}
|
||||
$response .= $chunk;
|
||||
return strlen($chunk);
|
||||
},
|
||||
]);
|
||||
if ($method === 'POST') {
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
|
||||
}
|
||||
$ok = curl_exec($curl);
|
||||
$result = ['status' => curl_getinfo($curl, CURLINFO_RESPONSE_CODE), 'body' => $ok === false ? false : $response];
|
||||
curl_close($curl);
|
||||
}
|
||||
if (!is_array($result) || !in_array($result['status'] ?? 0, $statuses, true) || !is_string($result['body'] ?? null) || strlen($result['body']) > 1048576) {
|
||||
throw new RuntimeException('IAM request failed');
|
||||
}
|
||||
try {
|
||||
$data = json_decode($result['body'], true, 64, JSON_THROW_ON_ERROR);
|
||||
} catch (\Throwable $error) {
|
||||
throw new RuntimeException('IAM response is invalid');
|
||||
}
|
||||
if (!is_array($data) || isset($data['error'])) {
|
||||
throw new RuntimeException('IAM response is invalid');
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"firebase/php-jwt": "^7.1",
|
||||
"php": ">=8.0",
|
||||
"topthink/framework": "^8.0.2",
|
||||
"topthink/think-orm": "^3.0",
|
||||
|
||||
Generated
+67
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "a5f0d3c9e4372fa66156ac28411cd86e",
|
||||
"content-hash": "72ffe2f144b34a313ce8f815e0f0e5bd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adbario/php-dot-notation",
|
||||
@@ -583,6 +583,72 @@
|
||||
},
|
||||
"time": "2022-09-18T07:06:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "v7.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/googleapis/php-jwt.git",
|
||||
"reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/googleapis/php-jwt/zipball/b374a5d1a4f1f67fadc2165cdb284645945e2fc0",
|
||||
"reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"phpfastcache/phpfastcache": "^9.2",
|
||||
"phpseclib/phpseclib": "~3.0",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psr/cache": "^2.0||^3.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures",
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
|
||||
"phpseclib/phpseclib": "Support PS256 (RSASSA-PSS) signatures"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Neuman Vong",
|
||||
"email": "neuman+pear@twilio.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Anant Narayanan",
|
||||
"email": "anant@php.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||
"homepage": "https://github.com/googleapis/php-jwt",
|
||||
"keywords": [
|
||||
"jwt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/googleapis/php-jwt/issues",
|
||||
"source": "https://github.com/googleapis/php-jwt/tree/v7.1.0"
|
||||
},
|
||||
"time": "2026-06-11T17:54:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/command",
|
||||
"version": "1.3.0",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
// Optional integration: disabled installations never touch IAM or its transaction store.
|
||||
return [
|
||||
'enabled' => env('iam.enabled', false),
|
||||
'issuer' => env('iam.issuer', ''),
|
||||
'client_id' => env('iam.client_id', 'zyt'),
|
||||
'client_secret' => env('iam.client_secret', ''),
|
||||
'redirect_uri' => env('iam.redirect_uri', ''),
|
||||
'api_url' => env('iam.api_url', ''),
|
||||
'application_id' => env('iam.application_id', 'zyt'),
|
||||
'application_token' => env('iam.application_token', ''),
|
||||
'public_url' => env('iam.public_url', ''),
|
||||
];
|
||||
@@ -0,0 +1,10 @@
|
||||
-- Apply once before enabling the new adapter. Replace zyt_ only if database.prefix differs.
|
||||
-- Do not drop this ledger while IAM-created accounts exist: it is retry/deduplication state.
|
||||
CREATE TABLE IF NOT EXISTS `zyt_iam_local_identity` (
|
||||
`identity_key` char(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
||||
`identity_value` text NOT NULL,
|
||||
`admin_id` int unsigned DEFAULT NULL,
|
||||
`create_time` int unsigned NOT NULL,
|
||||
PRIMARY KEY (`identity_key`),
|
||||
UNIQUE KEY `uniq_iam_admin` (`admin_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -0,0 +1 @@
|
||||
import r from"./error-BerWbCRn.js";import{f as p,ak as i,I as m,a as e,aN as s,J as o}from"./@vue/runtime-core-C6bnekPw.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/shared-mAAVTE9n.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./vue-router-QlpZ4wdW.js";import"./index-MKPKssyT.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const a="/admin/assets/no_perms-jDxcYpYC.png",n={class:"error404"},W=p({__name:"403",setup(c){return(_,t)=>(i(),m("div",n,[e(r,{code:"403",title:"您的账号权限不足,请联系管理员添加权限!","show-btn":!1},{content:s(()=>[...t[0]||(t[0]=[o("div",{class:"flex justify-center"},[o("img",{class:"w-[150px] h-[150px]",src:a,alt:""})],-1)])]),_:1})]))}});export{W as default};
|
||||
@@ -0,0 +1 @@
|
||||
import r from"./error-DDb6iC9p.js";import{f as p,ak as i,I as m,a as e,aN as s,J as o}from"./@vue/runtime-core-C6bnekPw.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/shared-mAAVTE9n.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./vue-router-QlpZ4wdW.js";import"./index-dDVfDL1w.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const a="/admin/assets/no_perms-jDxcYpYC.png",n={class:"error404"},W=p({__name:"403",setup(c){return(_,t)=>(i(),m("div",n,[e(r,{code:"403",title:"您的账号权限不足,请联系管理员添加权限!","show-btn":!1},{content:s(()=>[...t[0]||(t[0]=[o("div",{class:"flex justify-center"},[o("img",{class:"w-[150px] h-[150px]",src:a,alt:""})],-1)])]),_:1})]))}});export{W as default};
|
||||
@@ -0,0 +1 @@
|
||||
import o from"./error-BerWbCRn.js";import{f as r,ak as t,I as m,a as p}from"./@vue/runtime-core-C6bnekPw.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/shared-mAAVTE9n.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./vue-router-QlpZ4wdW.js";import"./index-MKPKssyT.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const i={class:"error404"},T=r({__name:"404",setup(e){return(a,s)=>(t(),m("div",i,[p(o,{code:"404",title:"哎呀,出错了!您访问的页面不存在…"})]))}});export{T as default};
|
||||
@@ -0,0 +1 @@
|
||||
import o from"./error-DDb6iC9p.js";import{f as r,ak as t,I as m,a as p}from"./@vue/runtime-core-C6bnekPw.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/shared-mAAVTE9n.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./vue-router-QlpZ4wdW.js";import"./index-dDVfDL1w.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const i={class:"error404"},T=r({__name:"404",setup(e){return(a,s)=>(t(),m("div",i,[p(o,{code:"404",title:"哎呀,出错了!您访问的页面不存在…"})]))}});export{T as default};
|
||||
@@ -0,0 +1 @@
|
||||
function a(e){"@babel/helpers - typeof";return a=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},a(e)}function c(e,t,r,n,f,y,i){try{var u=e[y](i),o=u.value}catch(l){return void r(l)}u.done?t(o):Promise.resolve(o).then(n,f)}function p(e){return function(){var t=this,r=arguments;return new Promise(function(n,f){var y=e.apply(t,r);function i(o){c(y,n,f,i,u,"next",o)}function u(o){c(y,n,f,i,u,"throw",o)}i(void 0)})}}function b(e,t){if(a(e)!="object"||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var n=r.call(e,t);if(a(n)!="object")return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}function m(e){var t=b(e,"string");return a(t)=="symbol"?t:t+""}function s(e,t,r){return(t=m(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}export{a as _,p as a,s as b};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import{H as u}from"../highlight.js-Bxt7hFFy.js";import{f as c,i as g,w as s,A as n}from"../@vue/runtime-core-C6bnekPw.js";import{n as h}from"../@vue/reactivity-DiY1c2vO.js";var i=c({props:{code:{type:String,required:!0},language:{type:String,default:""},autodetect:{type:Boolean,default:!0},ignoreIllegals:{type:Boolean,default:!0}},setup:function(e){var t=h(e.language);s((function(){return e.language}),(function(a){t.value=a}));var r=n((function(){return e.autodetect||!t.value})),o=n((function(){return!r.value&&!u.getLanguage(t.value)}));return{className:n((function(){return o.value?"":"hljs "+t.value})),highlightedCode:n((function(){var a;if(o.value)return console.warn('The language "'+t.value+'" you specified could not be found.'),e.code.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'");if(r.value){var l=u.highlightAuto(e.code);return t.value=(a=l.language)!==null&&a!==void 0?a:"",l.value}return(l=u.highlight(e.code,{language:t.value,ignoreIllegals:e.ignoreIllegals})).value}))}},render:function(){return g("pre",{},[g("code",{class:this.className,innerHTML:this.highlightedCode})])}}),v={install:function(e){e.component("highlightjs",i)},component:i};export{v as o};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import"./uikit-base-component-vue3-YgTqL4da.js";import{A as r}from"../tuikit-atomicx-vue3-Dln8Zi6e.js";import{f as s,ak as c,I as l,aq as m,G as u,at as i,H as p,A as d}from"../@vue/runtime-core-C6bnekPw.js";import{y as v}from"../@vue/reactivity-DiY1c2vO.js";import"./chat-uikit-engine-zx802ozq.js";const _=(t,o)=>{const a=t.__vccOpts||t;for(const[e,n]of o)a[e]=n;return a},f={key:0,class:"chat"},h=s({name:"Chat",__name:"Chat",props:{PlaceholderEmpty:{default:null}},setup(t){const{activeConversation:o}=r(),a=d(()=>{var e;return!((e=o.value)!=null&&e.conversationID)});return(e,n)=>v(o)?(c(),l("div",f,[m(e.$slots,"default",{},void 0,!0)])):a.value&&t.PlaceholderEmpty?(c(),u(i(t.PlaceholderEmpty),{key:1})):p("",!0)}}),A=_(h,[["__scopeId","data-v-1c9c77cd"]]);typeof window<"u"&&(window.__CHAT_ATOMICX_VUE3__={name:"@tencentcloud/chat-uikit-vue3",version:"4.5.4"},console.log("[@tencentcloud/chat-uikit-vue3] v4.5.4"));export{A as E};
|
||||
@@ -0,0 +1 @@
|
||||
.chat[data-v-1c9c77cd]{display:flex;flex-direction:column;min-width:0}.uikit-chat-header[data-v-a0c42ddc]{padding:14px 10px;height:64px;display:flex;justify-content:center;background-color:var(--bg-color-operate)}.uikit-chat-header__container[data-v-a0c42ddc]{padding:0 10px;flex-direction:row;align-items:center;justify-content:space-between}.uikit-chat-header__left[data-v-a0c42ddc]{flex:1 1 auto;display:flex;flex-direction:row;align-items:center}.uikit-chat-header__avatar[data-v-a0c42ddc]{margin-right:12px}.uikit-chat-header__info[data-v-a0c42ddc]{flex:1;display:flex;flex-direction:column;justify-content:center}.uikit-chat-header__title[data-v-a0c42ddc]{display:block;margin:0;font-size:16px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-color-primary)}.uikit-chat-header__typing-indicator[data-v-a0c42ddc]{font-size:12px;color:var(--text-color-secondary)}.uikit-chat-header__live[data-v-a0c42ddc]{margin-top:4px;font-size:12px;color:var(--text-color-secondary)}/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}:root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,*:after,*:before{box-sizing:border-box}ul,li{list-style:none;padding:0;margin:0}picture,img,video,canvas,svg{display:block;max-width:100%}img{max-width:100%;height:auto;vertical-align:middle;image-rendering:-webkit-optimize-contrast;aspect-ratio:attr(width)/attr(height);display:inline-block;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}img:not([src],[srcset]){visibility:hidden}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{C as A,F as C,a as w,L as h,q as D,J as R,H as g,u as k,n as W}from"../@vue/reactivity-DiY1c2vO.js";import{w as b,b as x,n as L,g as F,$ as M,a5 as P}from"../@vue/runtime-core-C6bnekPw.js";function J(e){return A()?(C(e),!0):!1}const d=new WeakMap,z=(...e)=>{var t;const r=e[0],n=(t=F())==null?void 0:t.proxy;if(n==null&&!M())throw new Error("injectLocal must be called in setup");return n&&d.has(n)&&r in d.get(n)?d.get(n)[r]:P(...e)},B=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const K=e=>typeof e<"u",I=Object.prototype.toString,Q=e=>I.call(e)==="[object Object]",m=()=>{};function j(e,t){function r(...n){return new Promise((a,o)=>{Promise.resolve(e(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(a).catch(o)})}return r}const S=e=>e();function V(...e){let t=0,r,n=!0,a=m,o,s,i,u,c;!w(e[0])&&typeof e[0]=="object"?{delay:s,trailing:i=!0,leading:u=!0,rejectOnCancel:c=!1}=e[0]:[s,i=!0,u=!0,c=!1]=e;const f=()=>{r&&(clearTimeout(r),r=void 0,a(),a=m)};return O=>{const l=h(s),v=Date.now()-t,p=()=>o=O();return f(),l<=0?(t=Date.now(),p()):(v>l&&(u||!n)?(t=Date.now(),p()):i&&(o=new Promise((y,T)=>{a=c?T:y,r=setTimeout(()=>{t=Date.now(),n=!0,y(p()),f()},Math.max(0,l-v))})),!u&&!r&&(r=setTimeout(()=>n=!0,l)),n=!1,o)}}function E(e=S,t={}){const{initialState:r="active"}=t,n=N(r==="active");function a(){n.value=!1}function o(){n.value=!0}const s=(...i)=>{n.value&&e(...i)};return{isActive:g(n),pause:a,resume:o,eventFilter:s}}function U(e){return e.endsWith("rem")?Number.parseFloat(e)*16:Number.parseFloat(e)}function G(e){return F()}function X(e){return Array.isArray(e)?e:[e]}function N(...e){if(e.length!==1)return R(...e);const t=e[0];return typeof t=="function"?g(k(()=>({get:t,set:m}))):W(t)}function Y(e,t=200,r=!1,n=!0,a=!1){return j(V(t,r,n,a),e)}function _(e,t,r={}){const{eventFilter:n=S,...a}=r;return b(e,j(n,t),a)}function Z(e,t,r={}){const{eventFilter:n,initialState:a="active",...o}=r,{eventFilter:s,pause:i,resume:u,isActive:c}=E(n,{initialState:a});return{stop:_(e,t,{...o,eventFilter:s}),pause:i,resume:u,isActive:c}}function ee(e,t=!0,r){G()?x(e,r):t?e():L(e)}function te(e=!1,t={}){const{truthyValue:r=!0,falsyValue:n=!1}=t,a=w(e),o=D(e);function s(i){if(arguments.length)return o.value=i,o.value;{const u=h(r);return o.value=o.value===u?h(n):u,o.value}}return a?s:[o,s]}function ne(e,t,r){return b(e,t,{...r,immediate:!0})}export{N as a,ee as b,Q as c,X as d,Z as e,z as f,K as g,Y as h,B as i,U as p,J as t,te as u,ne as w};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
import{i as C,Q as y,a as E}from"./editor-Cyf37SuL.js";import{ak as g,I as h,f as w,b as P,w as O,aJ as b}from"../@vue/runtime-core-C6bnekPw.js";import{n as d,t as $,q as F}from"../@vue/reactivity-DiY1c2vO.js";var B=Object.defineProperty,D=Object.defineProperties,j=Object.getOwnPropertyDescriptors,m=Object.getOwnPropertySymbols,H=Object.prototype.hasOwnProperty,S=Object.prototype.propertyIsEnumerable,_=(e,t,o)=>t in e?B(e,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[t]=o,A=(e,t)=>{for(var o in t||(t={}))H.call(t,o)&&_(e,o,t[o]);if(m)for(var o of m(t))S.call(t,o)&&_(e,o,t[o]);return e},M=(e,t)=>D(e,j(t));function u(e){let t=`请使用 '@${e}' 事件,不要放在 props 中`;return t+=`
|
||||
Please use '@${e}' event instead of props`,t}var v=(e,t)=>{for(const[o,a]of t)e[o]=a;return e};const V=w({props:{mode:{type:String,default:"default"},defaultContent:{type:Array,default:[]},defaultHtml:{type:String,default:""},defaultConfig:{type:Object,default:{}},modelValue:{type:String,default:""}},setup(e,t){const o=d(null),a=F(null),i=d(""),s=()=>{if(!o.value)return;const f=$(e.defaultContent);C({selector:o.value,mode:e.mode,content:f||[],html:e.defaultHtml||e.modelValue||"",config:M(A({},e.defaultConfig),{onCreated(r){if(a.value=r,t.emit("onCreated",r),e.defaultConfig.onCreated){const n=u("onCreated");throw new Error(n)}},onChange(r){const n=r.getHtml();if(i.value=n,t.emit("update:modelValue",n),t.emit("onChange",r),e.defaultConfig.onChange){const l=u("onChange");throw new Error(l)}},onDestroyed(r){if(t.emit("onDestroyed",r),e.defaultConfig.onDestroyed){const n=u("onDestroyed");throw new Error(n)}},onMaxLength(r){if(t.emit("onMaxLength",r),e.defaultConfig.onMaxLength){const n=u("onMaxLength");throw new Error(n)}},onFocus(r){if(t.emit("onFocus",r),e.defaultConfig.onFocus){const n=u("onFocus");throw new Error(n)}},onBlur(r){if(t.emit("onBlur",r),e.defaultConfig.onBlur){const n=u("onBlur");throw new Error(n)}},customAlert(r,n){if(t.emit("customAlert",r,n),e.defaultConfig.customAlert){const l=u("customAlert");throw new Error(l)}},customPaste:(r,n)=>{if(e.defaultConfig.customPaste){const c=u("customPaste");throw new Error(c)}let l;return t.emit("customPaste",r,n,c=>{l=c}),l}})})};function p(f){const r=a.value;r!=null&&r.setHtml(f)}return P(()=>{s()}),O(()=>e.modelValue,f=>{f!==i.value&&p(f)}),{box:o}}}),I={ref:"box",style:{height:"100%"}};function L(e,t,o,a,i,s){return g(),h("div",I,null,512)}var J=v(V,[["render",L]]);const T=w({props:{editor:{type:Object},mode:{type:String,default:"default"},defaultConfig:{type:Object,default:{}}},setup(e){const t=d(null),o=a=>{if(t.value){if(a==null)throw new Error("Not found instance of Editor when create <Toolbar/> component");y.getToolbar(a)||E({editor:a,selector:t.value||"<div></div>",mode:e.mode,config:e.defaultConfig})}};return b(()=>{const{editor:a}=e;a!=null&&o(a)}),{selector:t}}}),R={ref:"selector"};function k(e,t,o,a,i,s){return g(),h("div",R,null,512)}var N=v(T,[["render",k]]);export{J as E,N as T};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{M as T,N as C,T as $,r as D,d as L,L as k}from"./element-plus-CWHdHlgZ.js";import{Y as E}from"./@element-plus/icons-vue-CbYn5zW9.js";import{ag as P}from"./tcm-CSYiFMlc.js";import{f as A,w as B,ak as p,I as b,aP as F,G as h,aN as n,a as i,O as m,J as M}from"./@vue/runtime-core-C6bnekPw.js";import{Q as c}from"./@vue/shared-mAAVTE9n.js";import{y as V,n as w}from"./@vue/reactivity-DiY1c2vO.js";import{_ as K}from"./index-MKPKssyT.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const Y={class:"assign-log-panel"},q={key:1,class:"text-gray-400"},z=A({__name:"AssignLogPanel",props:{diagnosisId:{}},setup(N,{expose:v}){const _=N,d=w(!1),u=w([]);function y(o){const e=o.related_po_creator_name;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(o.related_po_creator_id);return Number.isFinite(t)&&t>0?`ID:${t}`:"—"}function x(o){const e=o.related_po_create_time_text;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(o.related_po_create_time);if(!Number.isFinite(t)||t<=0)return"—";const a=new Date(t*1e3);if(Number.isNaN(a.getTime()))return"—";const r=l=>String(l).padStart(2,"0");return`${a.getFullYear()}-${r(a.getMonth()+1)}-${r(a.getDate())} ${r(a.getHours())}:${r(a.getMinutes())}:${r(a.getSeconds())}`}function f(o,e){const t=e==="from"?"from_assistant_name":"to_assistant_name",a=e==="from"?"from_assistant_id":"to_assistant_id",r=o[t];if(r!=null&&String(r).trim()!==""&&String(r)!=="—")return String(r);const l=Number(o[a]);return Number.isFinite(l)&&l>0?`ID:${l}`:"—"}const g=async()=>{if(_.diagnosisId){d.value=!0;try{const o=await P({id:_.diagnosisId}),e=Array.isArray(o)?o:[];u.value=e}catch(o){console.error(o),u.value=[]}finally{d.value=!1}}};return B(()=>_.diagnosisId,()=>{g()},{immediate:!0}),v({refresh:g}),(o,e)=>{const t=C,a=$,r=L,l=D,S=T,I=k;return p(),b("div",Y,[F((p(),h(S,{data:u.value,border:"",stripe:"","empty-text":"暂无指派记录"},{default:n(()=>[i(t,{label:"操作时间",width:"175",prop:"create_time_text"}),i(t,{label:"原医助","min-width":"120"},{default:n(({row:s})=>[m(c(f(s,"from")),1)]),_:1}),i(t,{label:"新医助","min-width":"120"},{default:n(({row:s})=>[m(c(f(s,"to")),1)]),_:1}),i(t,{label:"继承",width:"72",align:"center"},{default:n(({row:s})=>[Number(s.is_inherit)===1?(p(),h(a,{key:0,type:"success",size:"small"},{default:n(()=>[...e[0]||(e[0]=[m("是",-1)])]),_:1})):(p(),b("span",q,"否"))]),_:1}),i(t,{label:"快照·业务单创建人","min-width":"130","show-overflow-tooltip":""},{default:n(({row:s})=>[m(c(y(s)),1)]),_:1}),i(t,{label:"快照·业务单创建时间",width:"190"},{header:n(()=>[e[1]||(e[1]=M("span",null,"快照·业务单创建时间",-1)),i(l,{placement:"top",content:"related_po_create_time:触发本次操作的处方业务订单 create_time;与原文助一致时表示医助创建订单时间"},{default:n(()=>[i(r,{class:"assign-log-col-hint"},{default:n(()=>[i(V(E))]),_:1})]),_:1})]),default:n(({row:s})=>[m(c(x(s)),1)]),_:1}),i(t,{label:"操作人",width:"110",prop:"operator_name"}),i(t,{label:"操作账号",width:"120",prop:"operator_account","show-overflow-tooltip":""}),i(t,{label:"IP",width:"130",prop:"ip","show-overflow-tooltip":""})]),_:1},8,["data"])),[[I,d.value]])])}}}),Ct=K(z,[["__scopeId","data-v-0a09e3d2"]]);export{Ct as default};
|
||||
@@ -0,0 +1 @@
|
||||
.assign-log-col-hint[data-v-0a09e3d2]{margin-left:4px;vertical-align:middle;color:var(--el-text-color-secondary);cursor:help}
|
||||
@@ -0,0 +1 @@
|
||||
import{M as T,N as C,T as $,r as D,d as L,L as k}from"./element-plus-CWHdHlgZ.js";import{Y as E}from"./@element-plus/icons-vue-CbYn5zW9.js";import{ag as P}from"./tcm-CdJxXEws.js";import{f as A,w as B,ak as p,I as b,aP as F,G as h,aN as n,a as i,O as m,J as M}from"./@vue/runtime-core-C6bnekPw.js";import{Q as c}from"./@vue/shared-mAAVTE9n.js";import{y as V,n as w}from"./@vue/reactivity-DiY1c2vO.js";import{_ as K}from"./index-dDVfDL1w.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const Y={class:"assign-log-panel"},q={key:1,class:"text-gray-400"},z=A({__name:"AssignLogPanel",props:{diagnosisId:{}},setup(N,{expose:v}){const _=N,d=w(!1),u=w([]);function y(o){const e=o.related_po_creator_name;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(o.related_po_creator_id);return Number.isFinite(t)&&t>0?`ID:${t}`:"—"}function x(o){const e=o.related_po_create_time_text;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(o.related_po_create_time);if(!Number.isFinite(t)||t<=0)return"—";const a=new Date(t*1e3);if(Number.isNaN(a.getTime()))return"—";const r=l=>String(l).padStart(2,"0");return`${a.getFullYear()}-${r(a.getMonth()+1)}-${r(a.getDate())} ${r(a.getHours())}:${r(a.getMinutes())}:${r(a.getSeconds())}`}function f(o,e){const t=e==="from"?"from_assistant_name":"to_assistant_name",a=e==="from"?"from_assistant_id":"to_assistant_id",r=o[t];if(r!=null&&String(r).trim()!==""&&String(r)!=="—")return String(r);const l=Number(o[a]);return Number.isFinite(l)&&l>0?`ID:${l}`:"—"}const g=async()=>{if(_.diagnosisId){d.value=!0;try{const o=await P({id:_.diagnosisId}),e=Array.isArray(o)?o:[];u.value=e}catch(o){console.error(o),u.value=[]}finally{d.value=!1}}};return B(()=>_.diagnosisId,()=>{g()},{immediate:!0}),v({refresh:g}),(o,e)=>{const t=C,a=$,r=L,l=D,S=T,I=k;return p(),b("div",Y,[F((p(),h(S,{data:u.value,border:"",stripe:"","empty-text":"暂无指派记录"},{default:n(()=>[i(t,{label:"操作时间",width:"175",prop:"create_time_text"}),i(t,{label:"原医助","min-width":"120"},{default:n(({row:s})=>[m(c(f(s,"from")),1)]),_:1}),i(t,{label:"新医助","min-width":"120"},{default:n(({row:s})=>[m(c(f(s,"to")),1)]),_:1}),i(t,{label:"继承",width:"72",align:"center"},{default:n(({row:s})=>[Number(s.is_inherit)===1?(p(),h(a,{key:0,type:"success",size:"small"},{default:n(()=>[...e[0]||(e[0]=[m("是",-1)])]),_:1})):(p(),b("span",q,"否"))]),_:1}),i(t,{label:"快照·业务单创建人","min-width":"130","show-overflow-tooltip":""},{default:n(({row:s})=>[m(c(y(s)),1)]),_:1}),i(t,{label:"快照·业务单创建时间",width:"190"},{header:n(()=>[e[1]||(e[1]=M("span",null,"快照·业务单创建时间",-1)),i(l,{placement:"top",content:"related_po_create_time:触发本次操作的处方业务订单 create_time;与原文助一致时表示医助创建订单时间"},{default:n(()=>[i(r,{class:"assign-log-col-hint"},{default:n(()=>[i(V(E))]),_:1})]),_:1})]),default:n(({row:s})=>[m(c(x(s)),1)]),_:1}),i(t,{label:"操作人",width:"110",prop:"operator_name"}),i(t,{label:"操作账号",width:"120",prop:"operator_account","show-overflow-tooltip":""}),i(t,{label:"IP",width:"130",prop:"ip","show-overflow-tooltip":""})]),_:1},8,["data"])),[[I,d.value]])])}}}),Ct=K(z,[["__scopeId","data-v-0a09e3d2"]]);export{Ct as default};
|
||||
@@ -0,0 +1 @@
|
||||
.watch-state[data-v-8c719418]{min-height:200px;display:flex;align-items:center;justify-content:center;color:var(--el-text-color-secondary);font-size:14px}.watch-error[data-v-8c719418]{color:var(--el-color-danger)}.watch-grid[data-v-8c719418]{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;min-height:220px}.watch-tile[data-v-8c719418]{background:#0f0f0f;border-radius:8px;overflow:hidden;aspect-ratio:16 / 10;display:flex;flex-direction:column}.watch-tile-cap[data-v-8c719418]{padding:6px 10px;font-size:12px;color:#e5e5e5;background:#0000008c}.watch-tile-view[data-v-8c719418]{flex:1;min-height:0;position:relative}.watch-hint[data-v-8c719418]{float:left;line-height:32px;font-size:12px;color:var(--el-text-color-secondary)}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{i as L,L as T,N as V,T as D,M as z,W as M}from"./element-plus-CWHdHlgZ.js";import{ao as O}from"./tcm-CSYiFMlc.js";import{f as P,b as F,w as j,ak as a,I as n,a as i,aN as s,O as m,H as w,aP as A,G as g,F as H,J as R}from"./@vue/runtime-core-C6bnekPw.js";import{y as d,n as k}from"./@vue/reactivity-DiY1c2vO.js";import{Q as c}from"./@vue/shared-mAAVTE9n.js";import{_ as G}from"./index-MKPKssyT.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const J={class:"case-record-list"},Q={key:0,class:"mb-3 flex justify-end"},W={key:0},Y={key:1,class:"text-gray-400"},q={class:"void-detail text-xs text-gray-500 mt-1"},K=P({__name:"CaseRecordList",props:{diagnosisId:{type:Number,default:0},readOnly:{type:Boolean,default:!1}},emits:["view","openPrescription"],setup(y,{expose:x,emit:C}){const _=y,h=C,l=k([]),p=k(!1),u=async()=>{if(_.diagnosisId){p.value=!0;try{const e=await O({diagnosis_id:_.diagnosisId});l.value=Array.isArray(e)?e:[]}catch(e){console.error("获取病历记录失败:",e),l.value=[]}finally{p.value=!1}}},S=e=>{if(!e)return"";const t=new Date(e*1e3);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`},$=e=>{h("view",e)},B=()=>{h("openPrescription")};return F(()=>{u()}),j(()=>_.diagnosisId,()=>{u()}),x({refresh:u}),(e,t)=>{const b=L,r=V,v=D,E=z,N=M,I=T;return a(),n("div",J,[y.readOnly?w("",!0):(a(),n("div",Q,[i(b,{type:"primary",size:"small",onClick:B},{default:s(()=>[...t[0]||(t[0]=[m("开方",-1)])]),_:1})])),A((a(),g(E,{data:d(l),border:""},{default:s(()=>[i(r,{prop:"prescription_date",label:"就诊日期",width:"120"}),i(r,{prop:"visit_no",label:"门诊号",width:"120"}),i(r,{prop:"clinical_diagnosis",label:"临床诊断","min-width":"160","show-overflow-tooltip":""}),i(r,{label:"处方摘要","min-width":"180"},{default:s(({row:o})=>[o.herbs&&o.herbs.length?(a(),n("span",W,c(o.herbs.slice(0,3).map(f=>`${f.name}${f.dosage}克`).join("、"))+c(o.herbs.length>3?"...":""),1)):(a(),n("span",Y,"—"))]),_:1}),i(r,{prop:"doctor_name",label:"医师",width:"90","show-overflow-tooltip":""}),i(r,{label:"状态",width:"140",align:"center"},{default:s(({row:o})=>[o.void_status===1?(a(),n(H,{key:0},[i(v,{type:"danger",size:"small"},{default:s(()=>[...t[1]||(t[1]=[m("已作废",-1)])]),_:1}),R("div",q,c(o.void_by_name||"—")+" "+c(S(o.void_time)),1)],64)):(a(),g(v,{key:1,type:"success",size:"small"},{default:s(()=>[...t[2]||(t[2]=[m("正常",-1)])]),_:1}))]),_:1}),i(r,{label:"操作",width:"120",fixed:"right"},{default:s(({row:o})=>[i(b,{link:"",type:"primary",size:"small",onClick:f=>$(o)},{default:s(()=>[...t[3]||(t[3]=[m(" 查看 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[I,d(p)]]),!d(p)&&d(l).length===0?(a(),g(N,{key:1,description:"暂无病历记录,开方后会自动显示",class:"mt-4"})):w("",!0)])}}}),zt=G(K,[["__scopeId","data-v-043d2738"]]);export{zt as default};
|
||||
@@ -0,0 +1 @@
|
||||
import{i as L,L as T,N as V,T as D,M as z,W as M}from"./element-plus-CWHdHlgZ.js";import{ao as O}from"./tcm-CdJxXEws.js";import{f as P,b as F,w as j,ak as a,I as n,a as i,aN as s,O as m,H as w,aP as A,G as g,F as H,J as R}from"./@vue/runtime-core-C6bnekPw.js";import{y as d,n as k}from"./@vue/reactivity-DiY1c2vO.js";import{Q as c}from"./@vue/shared-mAAVTE9n.js";import{_ as G}from"./index-dDVfDL1w.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const J={class:"case-record-list"},Q={key:0,class:"mb-3 flex justify-end"},W={key:0},Y={key:1,class:"text-gray-400"},q={class:"void-detail text-xs text-gray-500 mt-1"},K=P({__name:"CaseRecordList",props:{diagnosisId:{type:Number,default:0},readOnly:{type:Boolean,default:!1}},emits:["view","openPrescription"],setup(y,{expose:x,emit:C}){const _=y,h=C,l=k([]),p=k(!1),u=async()=>{if(_.diagnosisId){p.value=!0;try{const e=await O({diagnosis_id:_.diagnosisId});l.value=Array.isArray(e)?e:[]}catch(e){console.error("获取病历记录失败:",e),l.value=[]}finally{p.value=!1}}},S=e=>{if(!e)return"";const t=new Date(e*1e3);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`},$=e=>{h("view",e)},B=()=>{h("openPrescription")};return F(()=>{u()}),j(()=>_.diagnosisId,()=>{u()}),x({refresh:u}),(e,t)=>{const b=L,r=V,v=D,E=z,N=M,I=T;return a(),n("div",J,[y.readOnly?w("",!0):(a(),n("div",Q,[i(b,{type:"primary",size:"small",onClick:B},{default:s(()=>[...t[0]||(t[0]=[m("开方",-1)])]),_:1})])),A((a(),g(E,{data:d(l),border:""},{default:s(()=>[i(r,{prop:"prescription_date",label:"就诊日期",width:"120"}),i(r,{prop:"visit_no",label:"门诊号",width:"120"}),i(r,{prop:"clinical_diagnosis",label:"临床诊断","min-width":"160","show-overflow-tooltip":""}),i(r,{label:"处方摘要","min-width":"180"},{default:s(({row:o})=>[o.herbs&&o.herbs.length?(a(),n("span",W,c(o.herbs.slice(0,3).map(f=>`${f.name}${f.dosage}克`).join("、"))+c(o.herbs.length>3?"...":""),1)):(a(),n("span",Y,"—"))]),_:1}),i(r,{prop:"doctor_name",label:"医师",width:"90","show-overflow-tooltip":""}),i(r,{label:"状态",width:"140",align:"center"},{default:s(({row:o})=>[o.void_status===1?(a(),n(H,{key:0},[i(v,{type:"danger",size:"small"},{default:s(()=>[...t[1]||(t[1]=[m("已作废",-1)])]),_:1}),R("div",q,c(o.void_by_name||"—")+" "+c(S(o.void_time)),1)],64)):(a(),g(v,{key:1,type:"success",size:"small"},{default:s(()=>[...t[2]||(t[2]=[m("正常",-1)])]),_:1}))]),_:1}),i(r,{label:"操作",width:"120",fixed:"right"},{default:s(({row:o})=>[i(b,{link:"",type:"primary",size:"small",onClick:f=>$(o)},{default:s(()=>[...t[3]||(t[3]=[m(" 查看 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[I,d(p)]]),!d(p)&&d(l).length===0?(a(),g(N,{key:1,description:"暂无病历记录,开方后会自动显示",class:"mt-4"})):w("",!0)])}}}),zt=G(K,[["__scopeId","data-v-043d2738"]]);export{zt as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.daily-matrix[data-v-a5368e74]{padding:16px}.daily-matrix__toolbar[data-v-a5368e74]{display:flex;justify-content:space-between;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:12px}.daily-matrix__toolbar-left[data-v-a5368e74],.daily-matrix__toolbar-right[data-v-a5368e74]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.daily-matrix__table[data-v-a5368e74],.daily-matrix__table-wrap[data-v-a5368e74]{width:100%}.daily-matrix__chart[data-v-a5368e74]{margin-top:16px;padding:16px 18px;border:1px solid var(--el-border-color-lighter);border-radius:10px;background:linear-gradient(180deg,#fff,#f8fafc)}.daily-matrix__chart-canvas[data-v-a5368e74]{height:280px;width:100%}.daily-matrix__cell[data-v-a5368e74]{min-height:32px;display:inline-flex;align-items:center;justify-content:center;gap:2px;width:100%;color:var(--el-text-color-regular)}.daily-matrix__cell.is-clickable[data-v-a5368e74]{cursor:pointer}.daily-matrix__cell.is-empty[data-v-a5368e74]{color:var(--el-text-color-placeholder)}.daily-matrix__cell.is-high[data-v-a5368e74]{color:#dc2626;font-weight:700}.daily-matrix__cell.is-patient-self[data-v-a5368e74]{position:relative;background:linear-gradient(180deg,#8b5cf60a,#8b5cf61a);border-radius:4px}.daily-matrix__cell-up[data-v-a5368e74]{color:#dc2626;font-size:13px}.daily-matrix__cell-patient[data-v-a5368e74]{display:inline-block;margin-left:4px;padding:1px 6px;font-size:11px;font-weight:600;color:#6d28d9;background:#ede9fe;border:1px solid #ddd6fe;border-radius:999px;line-height:1.2;letter-spacing:.5px;white-space:nowrap}.daily-matrix__legend[data-v-a5368e74]{display:inline-flex;align-items:center;gap:6px;margin-right:12px;padding:2px 10px 2px 6px;background:#f8f6ff;border:1px dashed #ddd6fe;border-radius:999px}.daily-matrix__legend-text[data-v-a5368e74]{font-size:12px;color:#6d28d9;font-weight:500}.daily-matrix__todo[data-v-a5368e74]{margin-top:16px}.daily-matrix__section-title[data-v-a5368e74]{font-size:14px;font-weight:600;margin-bottom:12px;color:var(--el-text-color-primary)}.daily-matrix__tracking-existing[data-v-a5368e74]{width:100%;max-height:180px;overflow:auto;padding:8px 10px;border:1px solid var(--el-border-color);border-radius:6px;background:var(--el-fill-color-light)}.daily-matrix__tracking-line[data-v-a5368e74]{font-size:12.5px;line-height:1.6;color:var(--el-text-color-regular);word-break:break-word}.daily-matrix__tracking-preview[data-v-a5368e74]{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;width:100%;text-align:left}.daily-matrix__tracking-tooltip[data-v-a5368e74]{max-width:320px}.daily-matrix__tracking-tooltip-line[data-v-a5368e74]{font-size:12.5px;line-height:1.6;word-break:break-word}@media(max-width:768px){.daily-matrix[data-v-a5368e74],.daily-matrix__chart[data-v-a5368e74]{padding:12px}.daily-matrix__chart-canvas[data-v-a5368e74]{height:240px}}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.diagnosis-todo-list .toolbar[data-v-e71c3261]{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:12px}.diagnosis-todo-list .todo-table[data-v-e71c3261]{width:100%}.diagnosis-todo-list .pagination-wrap[data-v-e71c3261]{margin-top:12px;display:flex;justify-content:flex-end}.diagnosis-todo-list .text-danger[data-v-e71c3261]{color:var(--el-color-danger)}.diagnosis-todo-list .text-muted[data-v-e71c3261]{color:var(--el-text-color-placeholder)}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{_ as o}from"./GancaoSubmissionReconcileButton.vue_vue_type_script_setup_true_lang-CxutNvPm.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/runtime-core-C6bnekPw.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@vue/shared-mAAVTE9n.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./tcm-CdJxXEws.js";import"./index-dDVfDL1w.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";export{o as default};
|
||||
@@ -0,0 +1 @@
|
||||
import{_ as o}from"./GancaoSubmissionReconcileButton.vue_vue_type_script_setup_true_lang-BsDgX_Z_.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/runtime-core-C6bnekPw.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@vue/shared-mAAVTE9n.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./tcm-CSYiFMlc.js";import"./index-MKPKssyT.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";export{o as default};
|
||||
+1
@@ -0,0 +1 @@
|
||||
import{i as U,V as k,K as F,D,B as M,G,I as B,C as A}from"./element-plus-CWHdHlgZ.js";import{s as P}from"./@vue/runtime-dom-DDAG46FW.js";import{p as q}from"./tcm-CSYiFMlc.js";import{j as f}from"./index-MKPKssyT.js";import{f as T,as as K,ak as C,I as L,F as j,aP as z,G as N,aN as t,O as u,a as r,H as b,A as H}from"./@vue/runtime-core-C6bnekPw.js";import{n as g,r as W}from"./@vue/reactivity-DiY1c2vO.js";const h=T({__name:"GancaoSubmissionReconcileButton",props:{order:{}},emits:["resolved"],setup(v,{emit:V}){const d=v,y=V,w=H(()=>{var m,p,a;const i=String(((m=d.order)==null?void 0:m.pharmacy_claim_target)||"").trim().toLowerCase(),e=String(((p=d.order)==null?void 0:p.pharmacy_claim_status)||"").trim().toUpperCase(),n=Number(((a=d.order)==null?void 0:a.pharmacy_claim_lease_expires_at)||0),c=e==="PENDING"&&n>0&&n<=Math.floor(Date.now()/1e3);return i==="gancao"&&(c||["UNKNOWN","PENDING_RECONCILE"].includes(e))}),s=g(!1),_=g(!1),o=W({resolution:"CONFIRM_SUCCESS",remote_order_no:"",note:""});function I(){o.resolution="CONFIRM_SUCCESS",o.remote_order_no="",o.note="",s.value=!0}async function S(){var e;const i=Number((e=d.order)==null?void 0:e.id);if(i){if(o.resolution==="CONFIRM_SUCCESS"&&!o.remote_order_no.trim()){f.msgError("请填写甘草药方单号");return}if(!o.note.trim()){f.msgError("请填写甘草后台核对依据");return}_.value=!0;try{await q({id:i,resolution:o.resolution,remote_order_no:o.resolution==="CONFIRM_SUCCESS"?o.remote_order_no.trim():"",note:o.note.trim()}),f.msgSuccess("甘草提交核对已记录"),s.value=!1,y("resolved")}catch{}finally{_.value=!1}}}return(i,e)=>{const n=U,c=F,m=B,p=G,a=M,E=A,O=D,R=k,x=K("perms");return w.value?(C(),L(j,{key:0},[z((C(),N(n,{type:"danger",size:"small",plain:"",onClick:I},{default:t(()=>[...e[5]||(e[5]=[u("核对甘草提交",-1)])]),_:1})),[[x,["tcm.prescriptionOrder/confirmGancaoSubmission"]]]),r(R,{modelValue:s.value,"onUpdate:modelValue":e[4]||(e[4]=l=>s.value=l),title:"人工核对甘草提交",width:"min(92vw, 520px)","append-to-body":"","destroy-on-close":"","close-on-click-modal":!1},{footer:t(()=>[r(n,{onClick:e[3]||(e[3]=l=>s.value=!1)},{default:t(()=>[...e[8]||(e[8]=[u("取消",-1)])]),_:1}),r(n,{type:"primary",loading:_.value,onClick:S},{default:t(()=>[...e[9]||(e[9]=[u("确认并记录",-1)])]),_:1},8,["loading"])]),default:t(()=>[r(c,{title:"请先在甘草后台核对。本操作会写入不可变更的审计记录。",type:"warning",closable:!1,"show-icon":"",class:"mb-4"}),r(O,{"label-width":"100px",onSubmit:P(S,["prevent"])},{default:t(()=>[r(a,{label:"核对结果",required:""},{default:t(()=>[r(p,{modelValue:o.resolution,"onUpdate:modelValue":e[0]||(e[0]=l=>o.resolution=l)},{default:t(()=>[r(m,{label:"CONFIRM_SUCCESS"},{default:t(()=>[...e[6]||(e[6]=[u("确认已创建",-1)])]),_:1}),r(m,{label:"CONFIRM_NOT_CREATED"},{default:t(()=>[...e[7]||(e[7]=[u("确认未创建",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),o.resolution==="CONFIRM_SUCCESS"?(C(),N(a,{key:0,label:"甘草单号",required:""},{default:t(()=>[r(E,{modelValue:o.remote_order_no,"onUpdate:modelValue":e[1]||(e[1]=l=>o.remote_order_no=l),maxlength:"64",clearable:""},null,8,["modelValue"])]),_:1})):b("",!0),r(a,{label:"核对依据",required:""},{default:t(()=>[r(E,{modelValue:o.note,"onUpdate:modelValue":e[2]||(e[2]=l=>o.note=l),type:"textarea",rows:3,maxlength:"1000","show-word-limit":"",placeholder:"例如:核对时间、甘草后台查询条件及结果"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)):b("",!0)}}});export{h as _};
|
||||
+1
@@ -0,0 +1 @@
|
||||
import{i as U,V as k,K as F,D,B as M,G,I as B,C as A}from"./element-plus-CWHdHlgZ.js";import{s as P}from"./@vue/runtime-dom-DDAG46FW.js";import{p as q}from"./tcm-CdJxXEws.js";import{j as f}from"./index-dDVfDL1w.js";import{f as T,as as K,ak as C,I as L,F as j,aP as z,G as N,aN as t,O as u,a as r,H as b,A as H}from"./@vue/runtime-core-C6bnekPw.js";import{n as g,r as W}from"./@vue/reactivity-DiY1c2vO.js";const h=T({__name:"GancaoSubmissionReconcileButton",props:{order:{}},emits:["resolved"],setup(v,{emit:V}){const d=v,y=V,w=H(()=>{var m,p,a;const i=String(((m=d.order)==null?void 0:m.pharmacy_claim_target)||"").trim().toLowerCase(),e=String(((p=d.order)==null?void 0:p.pharmacy_claim_status)||"").trim().toUpperCase(),n=Number(((a=d.order)==null?void 0:a.pharmacy_claim_lease_expires_at)||0),c=e==="PENDING"&&n>0&&n<=Math.floor(Date.now()/1e3);return i==="gancao"&&(c||["UNKNOWN","PENDING_RECONCILE"].includes(e))}),s=g(!1),_=g(!1),o=W({resolution:"CONFIRM_SUCCESS",remote_order_no:"",note:""});function I(){o.resolution="CONFIRM_SUCCESS",o.remote_order_no="",o.note="",s.value=!0}async function S(){var e;const i=Number((e=d.order)==null?void 0:e.id);if(i){if(o.resolution==="CONFIRM_SUCCESS"&&!o.remote_order_no.trim()){f.msgError("请填写甘草药方单号");return}if(!o.note.trim()){f.msgError("请填写甘草后台核对依据");return}_.value=!0;try{await q({id:i,resolution:o.resolution,remote_order_no:o.resolution==="CONFIRM_SUCCESS"?o.remote_order_no.trim():"",note:o.note.trim()}),f.msgSuccess("甘草提交核对已记录"),s.value=!1,y("resolved")}catch{}finally{_.value=!1}}}return(i,e)=>{const n=U,c=F,m=B,p=G,a=M,E=A,O=D,R=k,x=K("perms");return w.value?(C(),L(j,{key:0},[z((C(),N(n,{type:"danger",size:"small",plain:"",onClick:I},{default:t(()=>[...e[5]||(e[5]=[u("核对甘草提交",-1)])]),_:1})),[[x,["tcm.prescriptionOrder/confirmGancaoSubmission"]]]),r(R,{modelValue:s.value,"onUpdate:modelValue":e[4]||(e[4]=l=>s.value=l),title:"人工核对甘草提交",width:"min(92vw, 520px)","append-to-body":"","destroy-on-close":"","close-on-click-modal":!1},{footer:t(()=>[r(n,{onClick:e[3]||(e[3]=l=>s.value=!1)},{default:t(()=>[...e[8]||(e[8]=[u("取消",-1)])]),_:1}),r(n,{type:"primary",loading:_.value,onClick:S},{default:t(()=>[...e[9]||(e[9]=[u("确认并记录",-1)])]),_:1},8,["loading"])]),default:t(()=>[r(c,{title:"请先在甘草后台核对。本操作会写入不可变更的审计记录。",type:"warning",closable:!1,"show-icon":"",class:"mb-4"}),r(O,{"label-width":"100px",onSubmit:P(S,["prevent"])},{default:t(()=>[r(a,{label:"核对结果",required:""},{default:t(()=>[r(p,{modelValue:o.resolution,"onUpdate:modelValue":e[0]||(e[0]=l=>o.resolution=l)},{default:t(()=>[r(m,{label:"CONFIRM_SUCCESS"},{default:t(()=>[...e[6]||(e[6]=[u("确认已创建",-1)])]),_:1}),r(m,{label:"CONFIRM_NOT_CREATED"},{default:t(()=>[...e[7]||(e[7]=[u("确认未创建",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),o.resolution==="CONFIRM_SUCCESS"?(C(),N(a,{key:0,label:"甘草单号",required:""},{default:t(()=>[r(E,{modelValue:o.remote_order_no,"onUpdate:modelValue":e[1]||(e[1]=l=>o.remote_order_no=l),maxlength:"64",clearable:""},null,8,["modelValue"])]),_:1})):b("",!0),r(a,{label:"核对依据",required:""},{default:t(()=>[r(E,{modelValue:o.note,"onUpdate:modelValue":e[2]||(e[2]=l=>o.note=l),type:"textarea",rows:3,maxlength:"1000","show-word-limit":"",placeholder:"例如:核对时间、甘草后台查询条件及结果"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)):b("",!0)}}});export{h as _};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{_ as o}from"./MediaSourceSelect.vue_vue_type_script_setup_true_lang-IK1V16Ju.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./lodash-D3kF6u-c.js";import"./@vue/runtime-core-C6bnekPw.js";import"./@vue/reactivity-DiY1c2vO.js";import"./@vue/shared-mAAVTE9n.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";export{o as default};
|
||||
+1
@@ -0,0 +1 @@
|
||||
import{Q as g,P as V}from"./element-plus-CWHdHlgZ.js";import{f as C,ak as o,G as s,aN as v,I as p,F as h,ap as B,H as k,A as m}from"./@vue/runtime-core-C6bnekPw.js";import{y as c}from"./@vue/reactivity-DiY1c2vO.js";import{p as w,o as S}from"./@vue/shared-mAAVTE9n.js";const N=C({__name:"MediaSourceSelect",props:{modelValue:{default:""},options:{},loading:{type:Boolean,default:!1},placeholder:{default:"请选择自媒体来源"},clearable:{type:Boolean,default:!0},filterable:{type:Boolean,default:!0},allowCreate:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},selectClass:{},selectStyle:{}},emits:["update:modelValue","change","visible-change"],setup(e,{emit:i}){const u=e,n=i,d=m(()=>(u.options||[]).map(l=>typeof l=="string"?{name:l}:{name:l.name,value:l.value})),f=m(()=>d.value.some(l=>l.name===u.modelValue)),b=l=>{n("visible-change",l)};return(l,t)=>{const r=g,y=V;return o(),s(y,{"model-value":e.modelValue,placeholder:e.placeholder,clearable:e.clearable,filterable:e.filterable,"allow-create":e.allowCreate,"default-first-option":e.allowCreate,disabled:e.disabled,loading:e.loading,class:S(e.selectClass),style:w(e.selectStyle),"onUpdate:modelValue":t[0]||(t[0]=a=>n("update:modelValue",a)),onChange:t[1]||(t[1]=a=>n("change",a)),onVisibleChange:b},{default:v(()=>[(o(!0),p(h,null,B(c(d),a=>(o(),s(r,{key:a.name,label:a.name,value:a.name},null,8,["label","value"]))),128)),e.modelValue&&!c(f)?(o(),s(r,{key:`__legacy_${e.modelValue}`,label:`${e.modelValue}(已停用)`,value:e.modelValue},null,8,["label","value"])):k("",!0)]),_:1},8,["model-value","placeholder","clearable","filterable","allow-create","default-first-option","disabled","loading","class","style"])}}});export{N as _};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.msg-bubble[data-v-80799394]{display:flex;gap:10px;padding:10px 20px;align-items:flex-start}.msg-bubble.is-staff[data-v-80799394]{flex-direction:row-reverse}.msg-bubble.is-staff .msg-body[data-v-80799394]{align-items:flex-end}.msg-bubble.is-staff .msg-content.bubble-text[data-v-80799394],.msg-bubble.is-staff .msg-content.bubble-file[data-v-80799394]{background:#95ec69;color:#000}.msg-bubble .msg-avatar[data-v-80799394]{flex-shrink:0;background:#d0d7de;color:#fff;font-size:12px}.msg-bubble .msg-body[data-v-80799394]{display:flex;flex-direction:column;gap:4px;max-width:65%;min-width:0}.msg-bubble .msg-meta[data-v-80799394]{display:flex;gap:8px;align-items:center;font-size:12px;color:#999}.msg-bubble .msg-sender[data-v-80799394]{font-weight:500;color:#555}.msg-bubble .msg-content[data-v-80799394]{padding:8px 12px;border-radius:6px;background:#fff;word-break:break-word;line-height:1.6;max-width:100%}.msg-bubble .msg-content.bubble-media[data-v-80799394]{padding:0;background:transparent}.msg-bubble .content-text[data-v-80799394]{white-space:pre-wrap}.msg-bubble .content-image[data-v-80799394]{max-width:300px;max-height:300px;border-radius:6px;display:block}.msg-bubble .content-video[data-v-80799394]{max-width:320px;max-height:320px;border-radius:6px;display:block}.msg-bubble .content-audio[data-v-80799394]{max-width:260px}.msg-bubble .content-file[data-v-80799394]{display:flex;gap:12px;align-items:center;min-width:220px;padding:4px 8px}.msg-bubble .content-file .file-meta[data-v-80799394]{flex:1;min-width:0}.msg-bubble .content-file .file-name[data-v-80799394]{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.msg-bubble .content-file .file-info[data-v-80799394]{font-size:12px;color:#888}.msg-bubble .content-pending[data-v-80799394]{display:flex;gap:6px;align-items:center;color:#999;font-size:13px}.msg-bubble .content-fallback .fallback-title[data-v-80799394]{font-size:13px;color:#666;margin-bottom:4px}.msg-bubble .content-fallback .fallback-desc[data-v-80799394]{font-size:14px;color:#333}
|
||||
@@ -0,0 +1,2 @@
|
||||
import{i as se,W as ne,C as le,V as ae,v as re,d as me,a as de}from"./element-plus-CWHdHlgZ.js";import{_ as pe}from"./picker-BLjenmJu.js";import{e as ue,c as ce,j as g,_ as ge}from"./index-dDVfDL1w.js";import{s as U}from"./@vue/runtime-dom-DDAG46FW.js";import{b as z,G as fe}from"./@element-plus/icons-vue-CbYn5zW9.js";import{a as P,d as ve}from"./patient-CM6Ecpu4.js";import{h as _e}from"./perm-CaVgB9g1.js";import{f as ye,w as he,ak as o,I as n,G as k,aN as r,O as M,H as p,a as l,J as m,F as w,ap as E,A as ke}from"./@vue/runtime-core-C6bnekPw.js";import{n as f,y as N}from"./@vue/reactivity-DiY1c2vO.js";import{Q as T}from"./@vue/shared-mAAVTE9n.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./lodash-D3kF6u-c.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./index-C7ezMv-n.js";import"./index-Dha7YAn3.js";import"./index.vue_vue_type_script_setup_true_lang-CmPbpooh.js";import"./index-R2JX164b.js";import"./index-DLpdFML6.js";import"./cos-js-sdk-v5-DSMN0LUT.js";import"./file-BwsCOSPj.js";import"./index.vue_vue_type_script_setup_true_lang-BHxYugPa.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./usePaging-DofycyjW.js";import"./vuedraggable-5bKFmC7X.js";import"./vue-BVs68q8v.js";import"./@vue/compiler-dom-CqayqxS7.js";import"./@vue/compiler-core-CvbQOXIO.js";import"./sortablejs-dsEAUXlE.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const we={class:"note-timeline-wrap"},Ie={key:0,class:"timeline-actions"},Ce={class:"upload-trigger"},xe={class:"upload-trigger"},Ve={key:1,class:"note-timeline"},Ee={class:"timeline-date"},Ne={class:"timeline-body"},be={key:0,class:"timeline-content"},Se={key:1,class:"timeline-images"},Ae={key:2,class:"timeline-images"},De={key:0,class:"thumb-wrap"},Be={key:1,class:"file-wrap"},Ue=["href","title"],ze={class:"file-name"},j=8e3,Pe=ye({__name:"NoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(d,{emit:O}){const u=d,I=O,X=ke(()=>_e(["doctor.appointment/addDoctorNote"])),v=f(!1),C=f(""),b=f(!1),H=ue(),_=t=>H.getImageUrl(t),S=f([]),A=f([]),y=f(0),h=f(0),J=["jpg","jpeg","png","gif","bmp","webp","svg"],D=t=>{var s;const e=((s=t.split(".").pop())==null?void 0:s.toLowerCase().split("?")[0])||"";return J.includes(e)},$=t=>{var s;const e=t.split("/");return decodeURIComponent(((s=e[e.length-1])==null?void 0:s.split("?")[0])||"文件")},Q=t=>t.filter(D).map(_),Z=(t,e)=>{const s=t.filter(D),x=t[e];return s.indexOf(x)},q=t=>t?t.split(`
|
||||
`).filter(Boolean):[],K=t=>{if(!u.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=y.value){y.value=e.length;return}const s=e.slice(y.value);y.value=e.length,s.length>0&&P({diagnosis_id:u.diagnosisId,tongue_images:s}).then(()=>{g.msgSuccess("舌苔照片已添加"),I("refresh")})},Y=t=>{if(!u.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=h.value){h.value=e.length;return}const s=e.slice(h.value);h.value=e.length,s.length>0&&P({diagnosis_id:u.diagnosisId,report_files:s}).then(()=>{g.msgSuccess("检查报告已添加"),I("refresh")})};he(()=>u.notes,()=>{S.value=[],A.value=[],y.value=0,h.value=0});const ee=async()=>{if(!u.diagnosisId){g.msgWarning("当前无诊单,无法添加备注");return}const t=C.value.trim();if(!t){g.msgWarning("请输入备注内容");return}b.value=!0;try{await P({diagnosis_id:u.diagnosisId,content:t}),g.msgSuccess("备注保存成功"),C.value="",v.value=!1,I("refresh")}catch(e){g.msgError((e==null?void 0:e.message)||"保存失败")}finally{b.value=!1}},B=async(t,e,s)=>{try{await de.confirm("确认删除?","提示",{type:"warning"})}catch{return}await ve({note_id:t,image_type:e,image_path:s}),g.msgSuccess("已删除"),I("refresh")};return(t,e)=>{const s=se,x=ce,F=pe,G=re,V=me,te=ne,ie=le,oe=ae;return o(),n("div",we,[!d.readonly&&d.diagnosisId?(o(),n("div",Ie,[X.value?(o(),k(s,{key:0,type:"primary",plain:"",size:"small",onClick:e[0]||(e[0]=i=>v.value=!0)},{default:r(()=>[...e[6]||(e[6]=[M(" 添加备注 ",-1)])]),_:1})):p("",!0),l(F,{modelValue:S.value,"onUpdate:modelValue":e[1]||(e[1]=i=>S.value=i),limit:99,type:"image","exclude-domain":!0,onChange:K},{upload:r(()=>[m("div",Ce,[l(x,{size:20,name:"el-icon-Plus"}),e[7]||(e[7]=m("span",null,"舌苔照片",-1))])]),_:1},8,["modelValue"]),l(F,{modelValue:A.value,"onUpdate:modelValue":e[2]||(e[2]=i=>A.value=i),limit:99,type:"file","exclude-domain":!0,onChange:Y},{upload:r(()=>[m("div",xe,[l(x,{size:20,name:"el-icon-Plus"}),e[8]||(e[8]=m("span",null,"检查报告",-1))])]),_:1},8,["modelValue"])])):p("",!0),d.notes.length?(o(),n("div",Ve,[(o(!0),n(w,null,E(d.notes,i=>{var L,R;return o(),n("div",{key:i.id,class:"timeline-node"},[e[11]||(e[11]=m("div",{class:"timeline-dot"},null,-1)),m("div",Ee,T(i.note_date),1),m("div",Ne,[i.content?(o(),n("div",be,[(o(!0),n(w,null,E(q(i.content),(a,c)=>(o(),n("div",{key:c,class:"content-line"},T(a),1))),128))])):p("",!0),(L=i.tongue_images)!=null&&L.length?(o(),n("div",Se,[e[9]||(e[9]=m("span",{class:"images-label"},"舌苔照片",-1)),(o(!0),n(w,null,E(i.tongue_images,(a,c)=>(o(),n("div",{key:c,class:"thumb-wrap"},[l(G,{src:_(a),"preview-src-list":i.tongue_images.map(_),"initial-index":c,"z-index":j,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),d.readonly?p("",!0):(o(),k(V,{key:0,class:"thumb-delete",onClick:U(W=>B(i.id,"tongue_images",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))]))),128))])):p("",!0),(R=i.report_files)!=null&&R.length?(o(),n("div",Ae,[e[10]||(e[10]=m("span",{class:"images-label"},"检查报告",-1)),(o(!0),n(w,null,E(i.report_files,(a,c)=>(o(),n(w,{key:c},[D(a)?(o(),n("div",De,[l(G,{src:_(a),"preview-src-list":Q(i.report_files),"initial-index":Z(i.report_files,c),"z-index":j,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),d.readonly?p("",!0):(o(),k(V,{key:0,class:"thumb-delete",onClick:U(W=>B(i.id,"report_files",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))])):(o(),n("div",Be,[m("a",{href:_(a),target:"_blank",class:"file-link",title:$(a)},[l(V,{size:20},{default:r(()=>[l(N(fe))]),_:1}),m("span",ze,T($(a)),1)],8,Ue),d.readonly?p("",!0):(o(),k(V,{key:0,class:"file-delete",onClick:U(W=>B(i.id,"report_files",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))]))],64))),128))])):p("",!0)])])}),128))])):p("",!0),!d.notes.length&&d.readonly?(o(),k(te,{key:2,description:"暂无备注","image-size":48})):p("",!0),l(oe,{modelValue:v.value,"onUpdate:modelValue":e[5]||(e[5]=i=>v.value=i),title:"添加备注",width:"480px","append-to-body":""},{footer:r(()=>[l(s,{onClick:e[4]||(e[4]=i=>v.value=!1)},{default:r(()=>[...e[12]||(e[12]=[M("取消",-1)])]),_:1}),l(s,{type:"primary",loading:b.value,onClick:ee},{default:r(()=>[...e[13]||(e[13]=[M("保存",-1)])]),_:1},8,["loading"])]),default:r(()=>[l(ie,{modelValue:C.value,"onUpdate:modelValue":e[3]||(e[3]=i=>C.value=i),type:"textarea",rows:4,placeholder:"输入今日备注...",maxlength:"500","show-word-limit":""},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),Mt=ge(Pe,[["__scopeId","data-v-e548427d"]]);export{Mt as default};
|
||||
@@ -0,0 +1 @@
|
||||
.timeline-actions[data-v-e548427d]{display:flex;flex-direction:column;align-items:flex-start;gap:12px;margin-bottom:12px;padding-bottom:12px;border-bottom:1px dashed #ebeef5}.upload-trigger[data-v-e548427d]{width:90px;height:90px;border:1px dashed #dcdfe6;border-radius:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;cursor:pointer;color:#909399;font-size:12px;transition:border-color .2s}.upload-trigger[data-v-e548427d]:hover{border-color:#409eff;color:#409eff}.note-timeline[data-v-e548427d]{position:relative;padding-left:22px}.note-timeline[data-v-e548427d]:before{content:"";position:absolute;left:6px;top:4px;bottom:4px;width:2px;background:#ebeef5;border-radius:1px}.timeline-node[data-v-e548427d]{position:relative;padding-bottom:16px}.timeline-node[data-v-e548427d]:last-child{padding-bottom:0}.timeline-dot[data-v-e548427d]{position:absolute;left:-19px;top:5px;width:10px;height:10px;border-radius:50%;background:#409eff;border:2px solid #ecf5ff}.timeline-date[data-v-e548427d]{font-size:13px;font-weight:600;color:#303133;margin-bottom:6px;font-family:IBM Plex Mono,Consolas,monospace}.timeline-body[data-v-e548427d]{display:flex;flex-direction:column;gap:6px}.timeline-content[data-v-e548427d]{display:flex;flex-direction:column;gap:2px}.content-line[data-v-e548427d]{font-size:12.5px;color:#606266;line-height:1.6;word-break:break-word}.timeline-images[data-v-e548427d]{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.images-label[data-v-e548427d]{font-size:12px;color:#909399;flex-shrink:0}.thumb-wrap[data-v-e548427d]{position:relative;display:inline-block}.timeline-thumb[data-v-e548427d]{width:64px;height:64px;border-radius:6px;border:1px solid #ebeef5;cursor:pointer;transition:transform .15s ease}.timeline-thumb[data-v-e548427d]:hover{transform:scale(1.05)}.thumb-delete[data-v-e548427d]{position:absolute;top:-6px;right:-6px;font-size:16px;color:#f56c6c;background:#fff;border-radius:50%;cursor:pointer;display:none}.thumb-wrap:hover .thumb-delete[data-v-e548427d]{display:block}.file-wrap[data-v-e548427d]{position:relative;display:inline-flex;align-items:center}.file-link[data-v-e548427d]{display:inline-flex;align-items:center;gap:4px;padding:6px 10px;border:1px solid #ebeef5;border-radius:6px;text-decoration:none;color:#409eff;font-size:12px;max-width:180px;transition:border-color .2s}.file-link[data-v-e548427d]:hover{border-color:#409eff}.file-name[data-v-e548427d]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}.file-delete[data-v-e548427d]{position:absolute;top:-6px;right:-6px;font-size:16px;color:#f56c6c;background:#fff;border-radius:50%;cursor:pointer;display:none}.file-wrap:hover .file-delete[data-v-e548427d]{display:block}
|
||||
@@ -0,0 +1,2 @@
|
||||
import{i as se,W as ne,C as le,V as ae,v as re,d as me,a as de}from"./element-plus-CWHdHlgZ.js";import{_ as pe}from"./picker-DHsMuf-G.js";import{e as ue,c as ce,j as g,_ as ge}from"./index-MKPKssyT.js";import{s as U}from"./@vue/runtime-dom-DDAG46FW.js";import{b as z,G as fe}from"./@element-plus/icons-vue-CbYn5zW9.js";import{a as P,d as ve}from"./patient-L2l0ImS9.js";import{h as _e}from"./perm-CV4h-gMd.js";import{f as ye,w as he,ak as o,I as n,G as k,aN as r,O as M,H as p,a as l,J as m,F as w,ap as E,A as ke}from"./@vue/runtime-core-C6bnekPw.js";import{n as f,y as N}from"./@vue/reactivity-DiY1c2vO.js";import{Q as T}from"./@vue/shared-mAAVTE9n.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./lodash-D3kF6u-c.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./index-Cf-TA1fk.js";import"./index-BQtV1Jt0.js";import"./index.vue_vue_type_script_setup_true_lang-CmPbpooh.js";import"./index-D4AKSG1L.js";import"./index-BOOuIgrt.js";import"./cos-js-sdk-v5-DSMN0LUT.js";import"./file-pgRi9w1O.js";import"./index.vue_vue_type_script_setup_true_lang-BHxYugPa.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./usePaging-DofycyjW.js";import"./vuedraggable-5bKFmC7X.js";import"./vue-BVs68q8v.js";import"./@vue/compiler-dom-CqayqxS7.js";import"./@vue/compiler-core-CvbQOXIO.js";import"./sortablejs-dsEAUXlE.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const we={class:"note-timeline-wrap"},Ie={key:0,class:"timeline-actions"},Ce={class:"upload-trigger"},xe={class:"upload-trigger"},Ve={key:1,class:"note-timeline"},Ee={class:"timeline-date"},Ne={class:"timeline-body"},be={key:0,class:"timeline-content"},Se={key:1,class:"timeline-images"},Ae={key:2,class:"timeline-images"},De={key:0,class:"thumb-wrap"},Be={key:1,class:"file-wrap"},Ue=["href","title"],ze={class:"file-name"},j=8e3,Pe=ye({__name:"NoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(d,{emit:O}){const u=d,I=O,X=ke(()=>_e(["doctor.appointment/addDoctorNote"])),v=f(!1),C=f(""),b=f(!1),H=ue(),_=t=>H.getImageUrl(t),S=f([]),A=f([]),y=f(0),h=f(0),J=["jpg","jpeg","png","gif","bmp","webp","svg"],D=t=>{var s;const e=((s=t.split(".").pop())==null?void 0:s.toLowerCase().split("?")[0])||"";return J.includes(e)},$=t=>{var s;const e=t.split("/");return decodeURIComponent(((s=e[e.length-1])==null?void 0:s.split("?")[0])||"文件")},Q=t=>t.filter(D).map(_),Z=(t,e)=>{const s=t.filter(D),x=t[e];return s.indexOf(x)},q=t=>t?t.split(`
|
||||
`).filter(Boolean):[],K=t=>{if(!u.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=y.value){y.value=e.length;return}const s=e.slice(y.value);y.value=e.length,s.length>0&&P({diagnosis_id:u.diagnosisId,tongue_images:s}).then(()=>{g.msgSuccess("舌苔照片已添加"),I("refresh")})},Y=t=>{if(!u.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=h.value){h.value=e.length;return}const s=e.slice(h.value);h.value=e.length,s.length>0&&P({diagnosis_id:u.diagnosisId,report_files:s}).then(()=>{g.msgSuccess("检查报告已添加"),I("refresh")})};he(()=>u.notes,()=>{S.value=[],A.value=[],y.value=0,h.value=0});const ee=async()=>{if(!u.diagnosisId){g.msgWarning("当前无诊单,无法添加备注");return}const t=C.value.trim();if(!t){g.msgWarning("请输入备注内容");return}b.value=!0;try{await P({diagnosis_id:u.diagnosisId,content:t}),g.msgSuccess("备注保存成功"),C.value="",v.value=!1,I("refresh")}catch(e){g.msgError((e==null?void 0:e.message)||"保存失败")}finally{b.value=!1}},B=async(t,e,s)=>{try{await de.confirm("确认删除?","提示",{type:"warning"})}catch{return}await ve({note_id:t,image_type:e,image_path:s}),g.msgSuccess("已删除"),I("refresh")};return(t,e)=>{const s=se,x=ce,F=pe,G=re,V=me,te=ne,ie=le,oe=ae;return o(),n("div",we,[!d.readonly&&d.diagnosisId?(o(),n("div",Ie,[X.value?(o(),k(s,{key:0,type:"primary",plain:"",size:"small",onClick:e[0]||(e[0]=i=>v.value=!0)},{default:r(()=>[...e[6]||(e[6]=[M(" 添加备注 ",-1)])]),_:1})):p("",!0),l(F,{modelValue:S.value,"onUpdate:modelValue":e[1]||(e[1]=i=>S.value=i),limit:99,type:"image","exclude-domain":!0,onChange:K},{upload:r(()=>[m("div",Ce,[l(x,{size:20,name:"el-icon-Plus"}),e[7]||(e[7]=m("span",null,"舌苔照片",-1))])]),_:1},8,["modelValue"]),l(F,{modelValue:A.value,"onUpdate:modelValue":e[2]||(e[2]=i=>A.value=i),limit:99,type:"file","exclude-domain":!0,onChange:Y},{upload:r(()=>[m("div",xe,[l(x,{size:20,name:"el-icon-Plus"}),e[8]||(e[8]=m("span",null,"检查报告",-1))])]),_:1},8,["modelValue"])])):p("",!0),d.notes.length?(o(),n("div",Ve,[(o(!0),n(w,null,E(d.notes,i=>{var L,R;return o(),n("div",{key:i.id,class:"timeline-node"},[e[11]||(e[11]=m("div",{class:"timeline-dot"},null,-1)),m("div",Ee,T(i.note_date),1),m("div",Ne,[i.content?(o(),n("div",be,[(o(!0),n(w,null,E(q(i.content),(a,c)=>(o(),n("div",{key:c,class:"content-line"},T(a),1))),128))])):p("",!0),(L=i.tongue_images)!=null&&L.length?(o(),n("div",Se,[e[9]||(e[9]=m("span",{class:"images-label"},"舌苔照片",-1)),(o(!0),n(w,null,E(i.tongue_images,(a,c)=>(o(),n("div",{key:c,class:"thumb-wrap"},[l(G,{src:_(a),"preview-src-list":i.tongue_images.map(_),"initial-index":c,"z-index":j,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),d.readonly?p("",!0):(o(),k(V,{key:0,class:"thumb-delete",onClick:U(W=>B(i.id,"tongue_images",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))]))),128))])):p("",!0),(R=i.report_files)!=null&&R.length?(o(),n("div",Ae,[e[10]||(e[10]=m("span",{class:"images-label"},"检查报告",-1)),(o(!0),n(w,null,E(i.report_files,(a,c)=>(o(),n(w,{key:c},[D(a)?(o(),n("div",De,[l(G,{src:_(a),"preview-src-list":Q(i.report_files),"initial-index":Z(i.report_files,c),"z-index":j,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),d.readonly?p("",!0):(o(),k(V,{key:0,class:"thumb-delete",onClick:U(W=>B(i.id,"report_files",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))])):(o(),n("div",Be,[m("a",{href:_(a),target:"_blank",class:"file-link",title:$(a)},[l(V,{size:20},{default:r(()=>[l(N(fe))]),_:1}),m("span",ze,T($(a)),1)],8,Ue),d.readonly?p("",!0):(o(),k(V,{key:0,class:"file-delete",onClick:U(W=>B(i.id,"report_files",a),["stop"])},{default:r(()=>[l(N(z))]),_:1},8,["onClick"]))]))],64))),128))])):p("",!0)])])}),128))])):p("",!0),!d.notes.length&&d.readonly?(o(),k(te,{key:2,description:"暂无备注","image-size":48})):p("",!0),l(oe,{modelValue:v.value,"onUpdate:modelValue":e[5]||(e[5]=i=>v.value=i),title:"添加备注",width:"480px","append-to-body":""},{footer:r(()=>[l(s,{onClick:e[4]||(e[4]=i=>v.value=!1)},{default:r(()=>[...e[12]||(e[12]=[M("取消",-1)])]),_:1}),l(s,{type:"primary",loading:b.value,onClick:ee},{default:r(()=>[...e[13]||(e[13]=[M("保存",-1)])]),_:1},8,["loading"])]),default:r(()=>[l(ie,{modelValue:C.value,"onUpdate:modelValue":e[3]||(e[3]=i=>C.value=i),type:"textarea",rows:4,placeholder:"输入今日备注...",maxlength:"500","show-word-limit":""},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),Mt=ge(Pe,[["__scopeId","data-v-e548427d"]]);export{Mt as default};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.form-grid[data-v-3c102918]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 14px}.form-tip[data-v-3c102918]{margin-left:10px;color:#8a95a6;font-size:12px}.danger-menu-item{color:var(--el-color-danger)!important}@media(max-width:720px){.form-grid[data-v-3c102918]{grid-template-columns:1fr}}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.card[data-v-a6ad7c86]{background:var(--rx-surface);border:1px solid var(--rx-line);border-radius:14px;padding:18px;display:flex;flex-direction:column;gap:14px;box-shadow:var(--rx-shadow-sm);transition:box-shadow .2s ease}.card[data-v-a6ad7c86]:hover{box-shadow:var(--rx-shadow)}.card-title[data-v-a6ad7c86]{font-size:15px;font-weight:700;color:var(--rx-ink);display:flex;align-items:center;gap:10px;padding-left:10px;position:relative}.card-title[data-v-a6ad7c86]:before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:16px;border-radius:2px;background:linear-gradient(180deg,#4f8cff,#2563eb)}.case-sub[data-v-a6ad7c86]{font-size:12px;font-weight:400;color:var(--rx-soft);font-family:var(--rx-font-data)}.grid-block[data-v-a6ad7c86]{display:flex;flex-direction:column;gap:10px;padding-top:12px;border-top:1px dashed var(--rx-line)}.grid-block[data-v-a6ad7c86]:first-of-type{border-top:none;padding-top:0}.grid-title[data-v-a6ad7c86]{font-size:13px;font-weight:600;color:var(--rx-accent-strong);letter-spacing:.02em;display:flex;align-items:center;gap:6px}.grid-title[data-v-a6ad7c86]:before{content:"";width:4px;height:4px;border-radius:50%;background:var(--rx-accent)}.kv-grid[data-v-a6ad7c86]{display:grid;gap:8px 16px}.kv-grid.one[data-v-a6ad7c86]{grid-template-columns:1fr}.kv-grid.two[data-v-a6ad7c86]{grid-template-columns:repeat(2,1fr)}.kv-grid.three[data-v-a6ad7c86]{grid-template-columns:repeat(3,1fr)}.kv-grid.four[data-v-a6ad7c86]{grid-template-columns:repeat(4,1fr)}[data-v-a6ad7c86] .kv-item{display:flex;gap:6px;font-size:12.5px;line-height:1.55;min-width:0}[data-v-a6ad7c86] .kv-item.multiline{flex-direction:column;gap:2px}[data-v-a6ad7c86] .kv-item .kv-label{color:var(--rx-soft);flex-shrink:0;min-width:58px}[data-v-a6ad7c86] .kv-item .kv-value{color:var(--rx-ink);word-break:break-word;flex:1;font-weight:500}[data-v-a6ad7c86] .kv-item.empty .kv-value{color:#c0c4cc;font-weight:400}[data-v-a6ad7c86] .kv-item.multiline .kv-value{white-space:pre-wrap;font-weight:400}[data-v-a6ad7c86] .metric-kv-item .metric-kv-value{display:inline-flex;align-items:center;gap:4px}[data-v-a6ad7c86] .metric-kv-item .metric-kv-value.high{color:#dc2626;font-weight:700}[data-v-a6ad7c86] .metric-up{font-size:14px;line-height:1;color:#dc2626}.rx-note[data-v-a6ad7c86]{font-size:13px;color:var(--rx-muted);line-height:1.6;padding:12px 14px;background:linear-gradient(135deg,#fafbfd,#f5f7fb);border-radius:8px;border-left:3px solid var(--rx-accent)}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.card[data-v-37de0c0b]{background:var(--rx-surface);border:1px solid var(--rx-line);border-radius:14px;padding:18px;display:flex;flex-direction:column;gap:14px;box-shadow:var(--rx-shadow-sm);transition:box-shadow .2s ease}.card[data-v-37de0c0b]:hover{box-shadow:var(--rx-shadow)}.card-title[data-v-37de0c0b]{font-size:15px;font-weight:700;color:var(--rx-ink);display:flex;align-items:center;gap:10px;padding-left:10px;position:relative}.card-title[data-v-37de0c0b]:before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:16px;border-radius:2px;background:linear-gradient(180deg,#4f8cff,#2563eb)}.patient-hero[data-v-37de0c0b]{background:linear-gradient(135deg,#f5f8ff,#eef3ff);border:1px solid #dde7ff;border-radius:12px;padding:16px 18px;display:flex;flex-direction:column;gap:6px;position:relative;overflow:hidden}.patient-hero[data-v-37de0c0b]:after{content:"";position:absolute;right:-20px;top:-20px;width:100px;height:100px;border-radius:50%;background:radial-gradient(circle,rgba(79,140,255,.08) 0%,transparent 70%)}.patient-name[data-v-37de0c0b]{font-size:22px;font-weight:700;color:var(--rx-ink);letter-spacing:-.01em}.patient-meta[data-v-37de0c0b]{color:var(--rx-muted);font-size:13px;line-height:1.7;display:flex;flex-direction:column;gap:2px;position:relative;z-index:1}
|
||||
@@ -0,0 +1 @@
|
||||
import{m as x,f as y,a as B}from"./diag-display-DCz_VAqj.js";import{f as w,ak as I,I as P,J as a,H as N}from"./@vue/runtime-core-C6bnekPw.js";import{Q as i}from"./@vue/shared-mAAVTE9n.js";import{y as e}from"./@vue/reactivity-DiY1c2vO.js";import{_ as V}from"./index-dDVfDL1w.js";import"./lodash-D3kF6u-c.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const b={class:"card patient-card"},D={class:"patient-hero"},E={class:"patient-name"},G={class:"patient-meta"},H={key:0},J=w({__name:"PatientInfoCard",props:{apt:{default:()=>({})},diag:{default:()=>({})}},setup(t){return(Q,o)=>{var m,r,n,d,p,s,c,l,g,f,u,h,v,k,C;return I(),P("div",b,[o[0]||(o[0]=a("div",{class:"card-title"},"患者信息",-1)),a("div",D,[a("div",E,i(((m=t.apt)==null?void 0:m.patient_name)||"—"),1),a("div",G,[a("div",null,i(e(x)((r=t.apt)==null?void 0:r.patient_phone))+" · "+i(e(y)((n=t.diag)==null?void 0:n.gender))+" · "+i(((d=t.diag)==null?void 0:d.age)!=null?t.diag.age+"岁":"—"),1),a("div",null,i((p=t.diag)!=null&&p.height?t.diag.height+"cm":"—")+" / "+i((s=t.diag)!=null&&s.weight?t.diag.weight+"kg":"—")+" · "+i(((c=t.diag)==null?void 0:c.region)||"—"),1),a("div",null," 预约:"+i((l=t.apt)==null?void 0:l.appointment_date)+" "+i((g=t.apt)==null?void 0:g.appointment_time)+" · "+i(e(B)((f=t.apt)==null?void 0:f.period)),1),a("div",null,"医生:"+i(((u=t.apt)==null?void 0:u.doctor_name)||"—")+" 客服:"+i(((h=t.apt)==null?void 0:h.assistant_name)||"—"),1),a("div",null," 状态:"+i(((v=t.apt)==null?void 0:v.status_desc)||"—")+" · "+i((k=t.apt)!=null&&k.has_prescription?"已开方":"未开方"),1),(C=t.apt)!=null&&C.remark?(I(),P("div",H,"备注:"+i(t.apt.remark),1)):N("",!0)])])])}}}),Ct=V(J,[["__scopeId","data-v-37de0c0b"]]);export{Ct as default};
|
||||
@@ -0,0 +1 @@
|
||||
import{m as x,f as y,a as B}from"./diag-display-DCz_VAqj.js";import{f as w,ak as I,I as P,J as a,H as N}from"./@vue/runtime-core-C6bnekPw.js";import{Q as i}from"./@vue/shared-mAAVTE9n.js";import{y as e}from"./@vue/reactivity-DiY1c2vO.js";import{_ as V}from"./index-MKPKssyT.js";import"./lodash-D3kF6u-c.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-QlpZ4wdW.js";import"./pinia-B8cvXbiZ.js";import"./axios-C80V62Fs.js";import"./element-plus-CWHdHlgZ.js";import"./@vue/runtime-dom-DDAG46FW.js";import"./@element-plus/icons-vue-CbYn5zW9.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./@vueuse/core-1S4fJlii.js";import"./@vueuse/shared-Cl3lVqjz.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CNLwa9wG.js";import"./tslib-BDyQ-Jie.js";import"./zrender-DRNXw7y3.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-C4onkBvW.js";const b={class:"card patient-card"},D={class:"patient-hero"},E={class:"patient-name"},G={class:"patient-meta"},H={key:0},J=w({__name:"PatientInfoCard",props:{apt:{default:()=>({})},diag:{default:()=>({})}},setup(t){return(Q,o)=>{var m,r,n,d,p,s,c,l,g,f,u,h,v,k,C;return I(),P("div",b,[o[0]||(o[0]=a("div",{class:"card-title"},"患者信息",-1)),a("div",D,[a("div",E,i(((m=t.apt)==null?void 0:m.patient_name)||"—"),1),a("div",G,[a("div",null,i(e(x)((r=t.apt)==null?void 0:r.patient_phone))+" · "+i(e(y)((n=t.diag)==null?void 0:n.gender))+" · "+i(((d=t.diag)==null?void 0:d.age)!=null?t.diag.age+"岁":"—"),1),a("div",null,i((p=t.diag)!=null&&p.height?t.diag.height+"cm":"—")+" / "+i((s=t.diag)!=null&&s.weight?t.diag.weight+"kg":"—")+" · "+i(((c=t.diag)==null?void 0:c.region)||"—"),1),a("div",null," 预约:"+i((l=t.apt)==null?void 0:l.appointment_date)+" "+i((g=t.apt)==null?void 0:g.appointment_time)+" · "+i(e(B)((f=t.apt)==null?void 0:f.period)),1),a("div",null,"医生:"+i(((u=t.apt)==null?void 0:u.doctor_name)||"—")+" 客服:"+i(((h=t.apt)==null?void 0:h.assistant_name)||"—"),1),a("div",null," 状态:"+i(((v=t.apt)==null?void 0:v.status_desc)||"—")+" · "+i((k=t.apt)!=null&&k.has_prescription?"已开方":"未开方"),1),(C=t.apt)!=null&&C.remark?(I(),P("div",H,"备注:"+i(t.apt.remark),1)):N("",!0)])])])}}}),Ct=V(J,[["__scopeId","data-v-37de0c0b"]]);export{Ct as default};
|
||||
@@ -0,0 +1 @@
|
||||
.patient-order-list[data-v-dab792c2]{padding:4px 0}.po-empty-tip[data-v-dab792c2]{padding:24px 0}.po-revisit-offset-bar[data-v-dab792c2]{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 14px;border:1px solid var(--el-border-color-lighter);border-radius:8px;background:var(--el-fill-color-lighter)}.po-revisit-offset-bar__main[data-v-dab792c2]{display:flex;align-items:center;flex-wrap:wrap;gap:4px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.batch-dialog-body[data-v-e1699253]{display:flex;flex-direction:column;gap:16px;min-height:260px}.loading-state[data-v-e1699253],.load-error-state[data-v-e1699253]{padding:28px 12px}.state-description[data-v-e1699253]{max-width:520px;margin:0 auto 14px;color:var(--el-text-color-secondary);line-height:1.6}.overview-panel[data-v-e1699253],.progress-panel[data-v-e1699253],.pending-panel[data-v-e1699253],.issues-panel[data-v-e1699253]{border:1px solid var(--el-border-color-lighter);border-radius:10px;background:var(--el-bg-color)}.overview-panel[data-v-e1699253]{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 18px}.overview-panel strong[data-v-e1699253]{margin-left:10px;color:var(--el-color-primary);font-size:28px;line-height:1}.overview-label[data-v-e1699253],.overview-unit[data-v-e1699253],.overview-meta[data-v-e1699253],.pending-count[data-v-e1699253],.footer-tip[data-v-e1699253]{color:var(--el-text-color-secondary)}.overview-unit[data-v-e1699253]{margin-left:5px}.overview-meta[data-v-e1699253]{display:flex;align-items:center;gap:10px;font-size:13px}.truncated-alert[data-v-e1699253],.stop-alert[data-v-e1699253]{flex-shrink:0}.refresh-error[data-v-e1699253]{display:flex;align-items:center;gap:12px}.refresh-error[data-v-e1699253] .el-alert{flex:1}.progress-panel[data-v-e1699253],.pending-panel[data-v-e1699253],.issues-panel[data-v-e1699253]{padding:18px}.progress-heading[data-v-e1699253],.section-heading[data-v-e1699253],.dialog-footer[data-v-e1699253]{display:flex;align-items:center;justify-content:space-between;gap:16px}.progress-heading[data-v-e1699253],.section-heading[data-v-e1699253]{margin-bottom:14px}.section-kicker[data-v-e1699253]{display:block;margin-bottom:3px;color:var(--el-text-color-secondary);font-size:12px}.progress-heading strong[data-v-e1699253],.section-heading strong[data-v-e1699253]{font-size:16px}.current-prescription[data-v-e1699253]{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:10px;margin-top:14px;padding:12px 14px;border-radius:8px;background:var(--el-fill-color-light)}.current-prescription span[data-v-e1699253],.current-prescription small[data-v-e1699253]{color:var(--el-text-color-secondary)}.counter-grid[data-v-e1699253]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:14px}.counter-item[data-v-e1699253]{padding:12px;border-radius:8px;background:var(--el-fill-color-light)}.counter-item span[data-v-e1699253]{display:block;margin-bottom:5px;color:var(--el-text-color-secondary);font-size:12px}.counter-item strong[data-v-e1699253]{font-size:22px}.counter-success strong[data-v-e1699253]{color:var(--el-color-success)}.counter-partial strong[data-v-e1699253]{color:var(--el-color-warning)}.counter-failed strong[data-v-e1699253]{color:var(--el-color-danger)}.stop-alert[data-v-e1699253]{margin-top:14px}.issue-name[data-v-e1699253]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.issues-panel small[data-v-e1699253]{color:var(--el-text-color-secondary)}.dialog-footer[data-v-e1699253]{width:100%}.footer-tip[data-v-e1699253]{font-size:12px}@media(max-width:640px){.overview-panel[data-v-e1699253],.overview-meta[data-v-e1699253],.refresh-error[data-v-e1699253],.dialog-footer[data-v-e1699253]{align-items:flex-start;flex-direction:column}.counter-grid[data-v-e1699253]{grid-template-columns:repeat(2,minmax(0,1fr))}.current-prescription[data-v-e1699253]{grid-template-columns:1fr}}
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user