更新
This commit is contained in:
@@ -45,6 +45,14 @@ export interface PromotionAutomationConfig {
|
|||||||
welcome_schedule: WelcomeSlot[]
|
welcome_schedule: WelcomeSlot[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PromotionAutomationSaveConfig = Omit<PromotionAutomationConfig,
|
||||||
|
'tags_enabled' | 'remark_enabled' | 'description_enabled' | 'welcome_schedule_enabled'> & {
|
||||||
|
tags_enabled: 0 | 1
|
||||||
|
remark_enabled: 0 | 1
|
||||||
|
description_enabled: 0 | 1
|
||||||
|
welcome_schedule_enabled: 0 | 1
|
||||||
|
}
|
||||||
|
|
||||||
export const weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
|
export const weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
|
||||||
export const templateTokens = [
|
export const templateTokens = [
|
||||||
{ label: '客户昵称', value: '{customer_name}' },
|
{ label: '客户昵称', value: '{customer_name}' },
|
||||||
@@ -93,6 +101,17 @@ export function cloneAutomationConfig(source?: Partial<PromotionAutomationConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Keep the save payload compatible with backends and transports that use 0/1 switches. */
|
||||||
|
export function serializeAutomationConfig(config: PromotionAutomationConfig): PromotionAutomationSaveConfig {
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
tags_enabled: config.tags_enabled ? 1 : 0,
|
||||||
|
remark_enabled: config.remark_enabled ? 1 : 0,
|
||||||
|
description_enabled: config.description_enabled ? 1 : 0,
|
||||||
|
welcome_schedule_enabled: config.welcome_schedule_enabled ? 1 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function previewTemplate(template: string, employee = '小陈', limit?: number): string {
|
export function previewTemplate(template: string, employee = '小陈', limit?: number): string {
|
||||||
const date = new Intl.DateTimeFormat('en-CA', {
|
const date = new Intl.DateTimeFormat('en-CA', {
|
||||||
timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit'
|
timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit'
|
||||||
|
|||||||
@@ -474,7 +474,7 @@
|
|||||||
:disabled="accessForm.action === 'grant' && !operator.can_grant"
|
:disabled="accessForm.action === 'grant' && !operator.can_grant"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<span class="form-tip">添加时仅可选择已启用且拥有本页面权限的账号;失效账号仍可用于移除历史授权。</span>
|
<span class="form-tip">添加时可选择当前管理范围内的启用账号;授权后账号会自动获得本页面入口,且只能访问已授权方案。</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="accessDialogPools.length" class="access-pool-preview">
|
<div v-if="accessDialogPools.length" class="access-pool-preview">
|
||||||
<strong>当前授权</strong>
|
<strong>当前授权</strong>
|
||||||
@@ -538,7 +538,7 @@ import type { WecomPromotionCustomerChatStatus } from '@/api/first_visit'
|
|||||||
|
|
||||||
import WecomFloatingWidgetBuilder from './components/WecomFloatingWidgetBuilder.vue'
|
import WecomFloatingWidgetBuilder from './components/WecomFloatingWidgetBuilder.vue'
|
||||||
import PromotionAutomationForm from './components/PromotionAutomationForm.vue'
|
import PromotionAutomationForm from './components/PromotionAutomationForm.vue'
|
||||||
import { cloneAutomationConfig, defaultAutomationConfig, isWebUrl, validateAutomationConfig } from './components/promotion-automation'
|
import { cloneAutomationConfig, defaultAutomationConfig, isWebUrl, serializeAutomationConfig, validateAutomationConfig } from './components/promotion-automation'
|
||||||
|
|
||||||
type TabName = 'links' | 'customer-stats' | 'configuration' | 'install'
|
type TabName = 'links' | 'customer-stats' | 'configuration' | 'install'
|
||||||
|
|
||||||
@@ -734,9 +734,7 @@ function operatorOptionLabel(operator: PromotionOperatorOption) {
|
|||||||
const departments = Array.isArray(operator.dept_names) && operator.dept_names.length
|
const departments = Array.isArray(operator.dept_names) && operator.dept_names.length
|
||||||
? operator.dept_names.join(' / ')
|
? operator.dept_names.join(' / ')
|
||||||
: '未分部门'
|
: '未分部门'
|
||||||
const unavailable = Number(operator.disable) === 1
|
const unavailable = Number(operator.disable) === 1 ? ' · 已禁用' : ''
|
||||||
? ' · 已禁用'
|
|
||||||
: (!operator.can_grant ? ' · 无页面权限' : '')
|
|
||||||
return `${operator.name} · ${departments}${unavailable}`
|
return `${operator.name} · ${departments}${unavailable}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,7 +804,7 @@ async function savePool() {
|
|||||||
...base,
|
...base,
|
||||||
name: poolForm.name.trim(),
|
name: poolForm.name.trim(),
|
||||||
fallback_url: poolForm.fallback_url.trim(),
|
fallback_url: poolForm.fallback_url.trim(),
|
||||||
...(overview.automation_installed ? { automation_config: automation } : {})
|
...(overview.automation_installed ? { automation_config: serializeAutomationConfig(automation) } : {})
|
||||||
})
|
})
|
||||||
poolDialogVisible.value = false
|
poolDialogVisible.value = false
|
||||||
await loadOverview()
|
await loadOverview()
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ __version__ = "1.2.0"
|
|||||||
|
|
||||||
# 调试模式开启时,登录页显示“演示模式”和“服务器设置”。
|
# 调试模式开启时,登录页显示“演示模式”和“服务器设置”。
|
||||||
# 正式发布请保持 False;此时程序只使用下面配置的线上域名。
|
# 正式发布请保持 False;此时程序只使用下面配置的线上域名。
|
||||||
DEBUG_MODE = False
|
DEBUG_MODE = True
|
||||||
ONLINE_API_BASE_URL = "https://admin.zhenyangtang.com.cn"
|
ONLINE_API_BASE_URL = "https://admin.zhenyangtang.com.cn"
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
"""Confirmation and optional doctor note for completing an appointment."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from PySide6.QtCore import Qt, Signal
|
||||||
|
from PySide6.QtGui import QCloseEvent
|
||||||
|
from PySide6.QtWidgets import (
|
||||||
|
QDialog,
|
||||||
|
QDialogButtonBox,
|
||||||
|
QLabel,
|
||||||
|
QPlainTextEdit,
|
||||||
|
QVBoxLayout,
|
||||||
|
QWidget,
|
||||||
|
)
|
||||||
|
|
||||||
|
from ..theme import mark_business_dialog
|
||||||
|
from ..widgets import MessageBanner
|
||||||
|
|
||||||
|
COMPLETION_NOTE_LIMIT = 500
|
||||||
|
|
||||||
|
|
||||||
|
class AppointmentCompleteDialog(QDialog):
|
||||||
|
"""Keep an unsaved note available if completion or note saving fails."""
|
||||||
|
|
||||||
|
submitted = Signal(str)
|
||||||
|
|
||||||
|
def __init__(self, *, can_note: bool, parent: QWidget | None = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
self._can_note = can_note
|
||||||
|
self._busy = False
|
||||||
|
self._completed = False
|
||||||
|
self.setWindowTitle("完成问诊")
|
||||||
|
self.resize(460, 350 if can_note else 230)
|
||||||
|
self.setMinimumWidth(420)
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
layout.setContentsMargins(24, 22, 24, 18)
|
||||||
|
layout.setSpacing(10)
|
||||||
|
title = QLabel("完成问诊", self)
|
||||||
|
title.setProperty("dialogRole", "title")
|
||||||
|
layout.addWidget(title)
|
||||||
|
prompt = QLabel("是否添加医生备注?" if can_note else "确认完成该挂号吗?", self)
|
||||||
|
layout.addWidget(prompt)
|
||||||
|
self.note_edit = QPlainTextEdit(self)
|
||||||
|
self.note_edit.setObjectName("AppointmentCompleteNote")
|
||||||
|
self.note_edit.setAccessibleName("完成问诊医生备注")
|
||||||
|
self.note_edit.setPlaceholderText("填写完成备注,将追加到医生备注时间轴")
|
||||||
|
self.note_edit.setMinimumHeight(100)
|
||||||
|
self.note_edit.setVisible(can_note)
|
||||||
|
self.note_edit.textChanged.connect(self._limit_note)
|
||||||
|
layout.addWidget(self.note_edit)
|
||||||
|
self.note_counter = QLabel(f"0 / {COMPLETION_NOTE_LIMIT}", self)
|
||||||
|
self.note_counter.setObjectName("AppointmentCompleteNoteCounter")
|
||||||
|
self.note_counter.setProperty("dialogRole", "subtitle")
|
||||||
|
self.note_counter.setAlignment(Qt.AlignmentFlag.AlignRight)
|
||||||
|
self.note_counter.setVisible(can_note)
|
||||||
|
layout.addWidget(self.note_counter)
|
||||||
|
hint = QLabel("系统会再次核对服务端挂号状态;完成后不可撤销。", self)
|
||||||
|
hint.setProperty("dialogRole", "subtitle")
|
||||||
|
hint.setWordWrap(True)
|
||||||
|
layout.addWidget(hint)
|
||||||
|
self.banner = MessageBanner(parent=self)
|
||||||
|
layout.addWidget(self.banner)
|
||||||
|
self.buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, self
|
||||||
|
)
|
||||||
|
self.confirm_button = self.buttons.button(QDialogButtonBox.StandardButton.Ok)
|
||||||
|
self.confirm_button.setText("确认完成")
|
||||||
|
self.confirm_button.setProperty("variant", "primary")
|
||||||
|
self.confirm_button.setAutoDefault(False)
|
||||||
|
self.cancel_button = self.buttons.button(QDialogButtonBox.StandardButton.Cancel)
|
||||||
|
self.cancel_button.setText("取消")
|
||||||
|
self.cancel_button.setAutoDefault(False)
|
||||||
|
self.buttons.accepted.connect(self._submit)
|
||||||
|
self.buttons.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(self.buttons)
|
||||||
|
mark_business_dialog(self, "AppointmentCompleteDialog")
|
||||||
|
|
||||||
|
def _limit_note(self) -> None:
|
||||||
|
text = self.note_edit.toPlainText()
|
||||||
|
if len(text) > COMPLETION_NOTE_LIMIT:
|
||||||
|
text = text[:COMPLETION_NOTE_LIMIT]
|
||||||
|
cursor_position = self.note_edit.textCursor().position()
|
||||||
|
self.note_edit.blockSignals(True)
|
||||||
|
self.note_edit.setPlainText(text)
|
||||||
|
cursor = self.note_edit.textCursor()
|
||||||
|
cursor.setPosition(min(cursor_position, self.note_edit.document().characterCount() - 1))
|
||||||
|
self.note_edit.setTextCursor(cursor)
|
||||||
|
self.note_edit.blockSignals(False)
|
||||||
|
self.note_counter.setText(f"{len(text)} / {COMPLETION_NOTE_LIMIT}")
|
||||||
|
|
||||||
|
def _submit(self) -> None:
|
||||||
|
if not self._busy and not self._completed:
|
||||||
|
self.submitted.emit(self.note_edit.toPlainText().strip() if self._can_note else "")
|
||||||
|
|
||||||
|
def set_busy(self, busy: bool) -> None:
|
||||||
|
self._busy = busy
|
||||||
|
self.note_edit.setReadOnly(busy or self._completed)
|
||||||
|
self.confirm_button.setEnabled(not busy and not self._completed)
|
||||||
|
self.confirm_button.setText("正在完成…" if busy else "确认完成")
|
||||||
|
self.cancel_button.setEnabled(not busy)
|
||||||
|
if busy:
|
||||||
|
self.banner.clear()
|
||||||
|
|
||||||
|
def show_error(self, message: str) -> None:
|
||||||
|
self.set_busy(False)
|
||||||
|
self.banner.show_message(message, "danger")
|
||||||
|
|
||||||
|
def show_completed_warning(self, message: str) -> None:
|
||||||
|
self._completed = True
|
||||||
|
self.set_busy(False)
|
||||||
|
self.confirm_button.hide()
|
||||||
|
self.cancel_button.setText("关闭")
|
||||||
|
self.banner.show_message(f"{message}。可复制上方备注,稍后在医生备注中补录。", "warning")
|
||||||
|
|
||||||
|
def reject(self) -> None:
|
||||||
|
if not self._busy:
|
||||||
|
super().reject()
|
||||||
|
|
||||||
|
def closeEvent(self, event: QCloseEvent) -> None: # noqa: N802 - Qt API
|
||||||
|
if self._busy:
|
||||||
|
event.ignore()
|
||||||
|
else:
|
||||||
|
super().closeEvent(event)
|
||||||
@@ -4,10 +4,12 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Callable, Mapping
|
from collections.abc import Callable, Mapping
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from html import escape
|
||||||
|
from math import ceil
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from PySide6.QtCore import QDateTime, QRectF, QSize, Qt
|
from PySide6.QtCore import QDateTime, QModelIndex, QRectF, QSize, Qt
|
||||||
from PySide6.QtGui import QColor, QFont, QIcon, QPainter, QPen, QPixmap
|
from PySide6.QtGui import QColor, QFont, QIcon, QPainter, QPen, QPixmap, QTextDocument, QTextOption
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QComboBox,
|
QComboBox,
|
||||||
QDateTimeEdit,
|
QDateTimeEdit,
|
||||||
@@ -23,6 +25,9 @@ from PySide6.QtWidgets import (
|
|||||||
QMessageBox,
|
QMessageBox,
|
||||||
QPushButton,
|
QPushButton,
|
||||||
QStackedWidget,
|
QStackedWidget,
|
||||||
|
QStyle,
|
||||||
|
QStyledItemDelegate,
|
||||||
|
QStyleOptionViewItem,
|
||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
QWidget,
|
QWidget,
|
||||||
)
|
)
|
||||||
@@ -381,26 +386,81 @@ def _formula(value: Any) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _order_warnings(row: Any) -> list[str]:
|
def _order_warnings(row: Any) -> list[str]:
|
||||||
if not _truthy(first_value(row, "has_prescription_order", default=False)):
|
"""Match the PC list's linked-order checks, including blank herb rows."""
|
||||||
|
|
||||||
|
raw = getattr(row, "raw", None)
|
||||||
|
source = raw if isinstance(raw, Mapping) and raw else row
|
||||||
|
try:
|
||||||
|
has_order = float(get_value(source, "has_prescription_order", 0) or 0) == 1
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
has_order = False
|
||||||
|
if not has_order:
|
||||||
return []
|
return []
|
||||||
herbs = get_value(row, "herbs", None) or []
|
herbs = get_value(source, "herbs", None)
|
||||||
if not isinstance(herbs, (list, tuple)) or not herbs:
|
herbs = herbs if isinstance(herbs, (list, tuple)) else []
|
||||||
|
names = [str(get_value(herb, "name", "") or "").strip() for herb in herbs]
|
||||||
|
names = [name for name in names if name]
|
||||||
|
if not names:
|
||||||
return ["请开方,当前处方药材为空白"]
|
return ["请开方,当前处方药材为空白"]
|
||||||
seen: set[str] = set()
|
seen: set[str] = set()
|
||||||
duplicate: list[str] = []
|
duplicate: list[str] = []
|
||||||
for herb in herbs:
|
for name in names:
|
||||||
name = str(first_value(herb, "name", "medicine_name", default="")).strip()
|
|
||||||
key = "".join(name.split()).lower()
|
key = "".join(name.split()).lower()
|
||||||
if key and key in seen and name not in duplicate:
|
if key and key in seen and name not in duplicate:
|
||||||
duplicate.append(name)
|
duplicate.append(name)
|
||||||
seen.add(key)
|
seen.add(key)
|
||||||
return [f"已有关联业务订单,存在重复药材:{'、'.join(duplicate)}"] if duplicate else []
|
return [f"已有关联业务订单,当前处方存在重复药材:{'、'.join(duplicate)}"] if duplicate else []
|
||||||
|
|
||||||
|
|
||||||
def _sn_cell(_value: Any, row: Any) -> str:
|
def _sn_cell(_value: Any, row: Any) -> str:
|
||||||
return str(first_value(row, "sn", "prescription_no", "id", default="—"))
|
return str(first_value(row, "sn", "prescription_no", "id", default="—"))
|
||||||
|
|
||||||
|
|
||||||
|
class _PrescriptionNumberDelegate(QStyledItemDelegate):
|
||||||
|
"""Paint visible PC-style reminders without changing the sortable SN value."""
|
||||||
|
|
||||||
|
def document(self, option: QStyleOptionViewItem, index: QModelIndex, width: int) -> QTextDocument:
|
||||||
|
row = index.data(Qt.ItemDataRole.UserRole)
|
||||||
|
number = str(index.data(Qt.ItemDataRole.DisplayRole) or "—")
|
||||||
|
record_id = display_text(first_value(row, "id", "prescription_id", default="—"))
|
||||||
|
document = QTextDocument()
|
||||||
|
document.setDocumentMargin(0)
|
||||||
|
document.setDefaultFont(option.font)
|
||||||
|
text_option = document.defaultTextOption()
|
||||||
|
text_option.setWrapMode(QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere)
|
||||||
|
document.setDefaultTextOption(text_option)
|
||||||
|
paragraphs = [
|
||||||
|
f'<p style="margin:0;color:#315CF4;font-size:12px;font-weight:600">{escape(number)}</p>',
|
||||||
|
f'<p style="margin:2px 0 0;color:#7481A3;font-size:11px;font-weight:400">ID: {escape(record_id)}</p>',
|
||||||
|
]
|
||||||
|
paragraphs.extend(
|
||||||
|
'<p style="margin:2px 0 0;color:#DC2626;font-size:12px;font-weight:400">'
|
||||||
|
+ escape(warning)
|
||||||
|
+ "</p>"
|
||||||
|
for warning in _order_warnings(row)
|
||||||
|
)
|
||||||
|
document.setHtml("".join(paragraphs))
|
||||||
|
document.setTextWidth(max(1, width - 16))
|
||||||
|
return document
|
||||||
|
|
||||||
|
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None:
|
||||||
|
styled = QStyleOptionViewItem(option)
|
||||||
|
self.initStyleOption(styled, index)
|
||||||
|
styled.text = ""
|
||||||
|
self.parent().style().drawControl(QStyle.ControlElement.CE_ItemViewItem, styled, painter)
|
||||||
|
document = self.document(option, index, option.rect.width())
|
||||||
|
painter.save()
|
||||||
|
painter.setClipRect(option.rect)
|
||||||
|
painter.translate(option.rect.left() + 8, option.rect.top() + 6)
|
||||||
|
document.drawContents(painter)
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
|
def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize: # noqa: N802
|
||||||
|
width = self.parent().columnWidth(index.column())
|
||||||
|
document = self.document(option, index, width)
|
||||||
|
return QSize(width, max(36, ceil(document.size().height()) + 12))
|
||||||
|
|
||||||
|
|
||||||
def _patient_cell(_value: Any, row: Any) -> str:
|
def _patient_cell(_value: Any, row: Any) -> str:
|
||||||
gender = first_value(row, "gender", default=None)
|
gender = first_value(row, "gender", default=None)
|
||||||
gender_text = "男" if gender in (1, "1") else "女" if gender in (0, "0") else "未知"
|
gender_text = "男" if gender in (1, "1") else "女" if gender in (0, "0") else "未知"
|
||||||
@@ -698,7 +758,7 @@ class PrescriptionsPage(QWidget):
|
|||||||
self.table = SortableTable(
|
self.table = SortableTable(
|
||||||
[
|
[
|
||||||
TableColumn("__selected__", "", 46, lambda _value, _row: ""),
|
TableColumn("__selected__", "", 46, lambda _value, _row: ""),
|
||||||
TableColumn("sn", "处方编号", 174, _sn_cell),
|
TableColumn("sn", "处方编号", 260, _sn_cell),
|
||||||
TableColumn("__actions__", "操作", 150, lambda _value, _row: ""),
|
TableColumn("__actions__", "操作", 150, lambda _value, _row: ""),
|
||||||
TableColumn("prescription_type", "处方类型", 96),
|
TableColumn("prescription_type", "处方类型", 96),
|
||||||
TableColumn("is_system_auto", "来源", 88, _source_cell),
|
TableColumn("is_system_auto", "来源", 88, _source_cell),
|
||||||
@@ -713,6 +773,9 @@ class PrescriptionsPage(QWidget):
|
|||||||
self.table.verticalHeader().setDefaultSectionSize(36)
|
self.table.verticalHeader().setDefaultSectionSize(36)
|
||||||
self.table.horizontalHeader().setFixedHeight(38)
|
self.table.horizontalHeader().setFixedHeight(38)
|
||||||
self.table.setWordWrap(False)
|
self.table.setWordWrap(False)
|
||||||
|
self.table.setItemDelegateForColumn(1, _PrescriptionNumberDelegate(self.table))
|
||||||
|
self.table.horizontalHeader().sectionResized.connect(self._number_column_resized)
|
||||||
|
self.table.model().layoutChanged.connect(self.table.resizeRowsToContents)
|
||||||
self.table.horizontalHeaderItem(0).setIcon(_painted_icon("checkbox", "#AEB9D4", 14))
|
self.table.horizontalHeaderItem(0).setIcon(_painted_icon("checkbox", "#AEB9D4", 14))
|
||||||
self.table.horizontalHeaderItem(0).setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
self.table.horizontalHeaderItem(0).setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
self.table.itemSelectionChanged.connect(self._selection_changed)
|
self.table.itemSelectionChanged.connect(self._selection_changed)
|
||||||
@@ -729,6 +792,10 @@ class PrescriptionsPage(QWidget):
|
|||||||
layout.addWidget(self.stack, 1)
|
layout.addWidget(self.stack, 1)
|
||||||
return card
|
return card
|
||||||
|
|
||||||
|
def _number_column_resized(self, column: int, _old_size: int, _new_size: int) -> None:
|
||||||
|
if column == 1:
|
||||||
|
self.table.resizeRowsToContents()
|
||||||
|
|
||||||
def _action_button(
|
def _action_button(
|
||||||
self,
|
self,
|
||||||
text: str,
|
text: str,
|
||||||
@@ -910,8 +977,11 @@ class PrescriptionsPage(QWidget):
|
|||||||
font.setWeight(QFont.Weight.DemiBold)
|
font.setWeight(QFont.Weight.DemiBold)
|
||||||
sn_item.setFont(font)
|
sn_item.setFont(font)
|
||||||
warnings = _order_warnings(row)
|
warnings = _order_warnings(row)
|
||||||
if warnings:
|
description = "\n".join(
|
||||||
sn_item.setToolTip("\n".join(warnings))
|
[sn_item.text(), f"ID: {first_value(row, 'id', 'prescription_id', default='—')}", *warnings]
|
||||||
|
)
|
||||||
|
sn_item.setToolTip(description)
|
||||||
|
sn_item.setData(Qt.ItemDataRole.AccessibleTextRole, description)
|
||||||
|
|
||||||
prescription_type = display_text(
|
prescription_type = display_text(
|
||||||
first_value(row, "prescription_type", default="—")
|
first_value(row, "prescription_type", default="—")
|
||||||
@@ -1002,6 +1072,7 @@ class PrescriptionsPage(QWidget):
|
|||||||
actions.addStretch(1)
|
actions.addStretch(1)
|
||||||
self.table.setCellWidget(row_index, 2, actions_host)
|
self.table.setCellWidget(row_index, 2, actions_host)
|
||||||
self._sync_row_mutation_actions()
|
self._sync_row_mutation_actions()
|
||||||
|
self.table.resizeRowsToContents()
|
||||||
|
|
||||||
def _run_row_action(self, row: Any, callback: Callable[[], None]) -> None:
|
def _run_row_action(self, row: Any, callback: Callable[[], None]) -> None:
|
||||||
target_id = _int(first_value(row, "id", "prescription_id", default=None), 0)
|
target_id = _int(first_value(row, "id", "prescription_id", default=None), 0)
|
||||||
|
|||||||
@@ -34,10 +34,12 @@ from PySide6.QtGui import (
|
|||||||
QFont,
|
QFont,
|
||||||
QFontMetrics,
|
QFontMetrics,
|
||||||
QIcon,
|
QIcon,
|
||||||
|
QKeySequence,
|
||||||
QPainter,
|
QPainter,
|
||||||
QPainterPath,
|
QPainterPath,
|
||||||
QPen,
|
QPen,
|
||||||
QPixmap,
|
QPixmap,
|
||||||
|
QShortcut,
|
||||||
QTextCursor,
|
QTextCursor,
|
||||||
QTextLayout,
|
QTextLayout,
|
||||||
QTextOption,
|
QTextOption,
|
||||||
@@ -72,6 +74,7 @@ from ..diagnosis_drawer import DailyRecordPanel
|
|||||||
from ..diagnosis_editors import FlowLayout
|
from ..diagnosis_editors import FlowLayout
|
||||||
from ..dialogs import DiagnosisDialog
|
from ..dialogs import DiagnosisDialog
|
||||||
from ..dialogs.ai_consult import present_ai_consult
|
from ..dialogs.ai_consult import present_ai_consult
|
||||||
|
from ..dialogs.appointment_complete import COMPLETION_NOTE_LIMIT, AppointmentCompleteDialog
|
||||||
from ..dialogs.prescription_ai import (
|
from ..dialogs.prescription_ai import (
|
||||||
can_open_diagnosis_ai_report,
|
can_open_diagnosis_ai_report,
|
||||||
can_use_diagnosis_ai_assistant,
|
can_use_diagnosis_ai_assistant,
|
||||||
@@ -112,6 +115,12 @@ _AI_AUTOMATIC_REQUEST_SLOTS = BoundedSemaphore(2)
|
|||||||
_AI_GENERATION_POOL = QThreadPool()
|
_AI_GENERATION_POOL = QThreadPool()
|
||||||
_AI_GENERATION_POOL.setMaxThreadCount(4)
|
_AI_GENERATION_POOL.setMaxThreadCount(4)
|
||||||
_AI_GENERATION_POOL.setExpiryTimeout(30_000)
|
_AI_GENERATION_POOL.setExpiryTimeout(30_000)
|
||||||
|
# Keep explicit recovery reads independent of automatic analysis workers.
|
||||||
|
_RECEPTION_REFRESH_POOL = QThreadPool()
|
||||||
|
_RECEPTION_REFRESH_POOL.setMaxThreadCount(3)
|
||||||
|
_RECEPTION_REFRESH_POOL.setExpiryTimeout(30_000)
|
||||||
|
_REFRESH_TIMEOUT_MS = 30_000
|
||||||
|
_REFRESH_COOLDOWN_MS = 1_500
|
||||||
AI_MEDICAL_DISCLAIMER = (
|
AI_MEDICAL_DISCLAIMER = (
|
||||||
"仅供临床辅助参考,不可替代医生诊断,不得直接用于开方、用药调整或其他医疗决策。"
|
"仅供临床辅助参考,不可替代医生诊断,不得直接用于开方、用药调整或其他医疗决策。"
|
||||||
"系统未对舌像、报告附件或视频画面进行视觉诊断;仅分析已录入、归档或转写的文字及附件元数据。"
|
"系统未对舌像、报告附件或视频画面进行视觉诊断;仅分析已录入、归档或转写的文字及附件元数据。"
|
||||||
@@ -157,6 +166,32 @@ QCalendarWidget#ReceptionDateCalendar {
|
|||||||
border: 1px solid #DDE5FA;
|
border: 1px solid #DDE5FA;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionRefreshButton {
|
||||||
|
min-height: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
padding: 0;
|
||||||
|
color: #5469F0;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border: 1px solid #E4E9F6;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionRefreshButton:enabled:hover {
|
||||||
|
background-color: #EEF1FF;
|
||||||
|
border-color: #C5CEFF;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionRefreshButton:enabled:pressed {
|
||||||
|
background-color: #E2E7FF;
|
||||||
|
border-color: #9EACFF;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionRefreshButton:focus {
|
||||||
|
border-color: #5469F0;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionRefreshButton:disabled {
|
||||||
|
color: #8A93A8;
|
||||||
|
background-color: #F7F8FB;
|
||||||
|
border-color: #E4E9F6;
|
||||||
|
}
|
||||||
QWidget#ReceptionPage QPushButton[receptionQueueChip="true"] {
|
QWidget#ReceptionPage QPushButton[receptionQueueChip="true"] {
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
max-height: 32px;
|
max-height: 32px;
|
||||||
@@ -306,6 +341,24 @@ QWidget#ReceptionPage QPushButton#ReceptionCompleteButton {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionCompleteButton:enabled:hover {
|
||||||
|
color: #CF4656;
|
||||||
|
background-color: #FFF0F2;
|
||||||
|
border-color: #EFA3AD;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionCompleteButton:enabled:pressed {
|
||||||
|
color: #BF3949;
|
||||||
|
background-color: #FFE4E8;
|
||||||
|
border-color: #E58A98;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionCompleteButton:enabled:focus {
|
||||||
|
border-color: #CF4656;
|
||||||
|
}
|
||||||
|
QWidget#ReceptionPage QPushButton#ReceptionCompleteButton:disabled {
|
||||||
|
color: #A8AFBF;
|
||||||
|
background-color: #F7F8FB;
|
||||||
|
border-color: #E5E8EF;
|
||||||
|
}
|
||||||
QWidget#ReceptionPage QTabBar#ReceptionDetailTabs {
|
QWidget#ReceptionPage QTabBar#ReceptionDetailTabs {
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
border-bottom: 1px solid #E6EAF5;
|
border-bottom: 1px solid #E6EAF5;
|
||||||
@@ -2090,6 +2143,26 @@ def _is_local_material_reference(value: str) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _ReceptionCompleteButton(QPushButton):
|
||||||
|
"""Completion action with a pointer only while it can be activated."""
|
||||||
|
|
||||||
|
def __init__(self, parent: QWidget | None = None) -> None:
|
||||||
|
super().__init__("结束问诊", parent)
|
||||||
|
self.setObjectName("ReceptionCompleteButton")
|
||||||
|
self.setIcon(_painted_reception_action_icon("stop", "#F15B67"))
|
||||||
|
self.setIconSize(QSize(14, 14))
|
||||||
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
|
||||||
|
def changeEvent(self, event: QEvent) -> None: # noqa: N802 - Qt API
|
||||||
|
super().changeEvent(event)
|
||||||
|
if event.type() == QEvent.Type.EnabledChange:
|
||||||
|
self.setCursor(
|
||||||
|
Qt.CursorShape.PointingHandCursor
|
||||||
|
if self.isEnabled()
|
||||||
|
else Qt.CursorShape.ArrowCursor
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _NoteAttachmentPreview(QPushButton):
|
class _NoteAttachmentPreview(QPushButton):
|
||||||
"""Responsive inline thumbnail that remains clickable for a full preview."""
|
"""Responsive inline thumbnail that remains clickable for a full preview."""
|
||||||
|
|
||||||
@@ -3587,6 +3660,8 @@ class ReceptionPage(QWidget):
|
|||||||
self._queue_query: dict[str, Any] | None = None
|
self._queue_query: dict[str, Any] | None = None
|
||||||
self._queue_query_key: tuple[Any, ...] | None = None
|
self._queue_query_key: tuple[Any, ...] | None = None
|
||||||
self._detail_loading = False
|
self._detail_loading = False
|
||||||
|
self._completion_pending = False
|
||||||
|
self._completion_dialog: AppointmentCompleteDialog | None = None
|
||||||
self._detail_requests: set[tuple[int, int]] = set()
|
self._detail_requests: set[tuple[int, int]] = set()
|
||||||
self._detail_cancel_events: dict[tuple[int, int], Event] = {}
|
self._detail_cancel_events: dict[tuple[int, int], Event] = {}
|
||||||
self._detail_failed_requests: set[tuple[int, int]] = set()
|
self._detail_failed_requests: set[tuple[int, int]] = set()
|
||||||
@@ -3679,6 +3754,12 @@ class ReceptionPage(QWidget):
|
|||||||
self.poll_timer = QTimer(self)
|
self.poll_timer = QTimer(self)
|
||||||
self.poll_timer.setInterval(5_000)
|
self.poll_timer.setInterval(5_000)
|
||||||
self.poll_timer.timeout.connect(self._poll_queue)
|
self.poll_timer.timeout.connect(self._poll_queue)
|
||||||
|
self._refresh_cooldown = QTimer(self)
|
||||||
|
self._refresh_cooldown.setSingleShot(True)
|
||||||
|
self._refresh_cooldown.timeout.connect(self._finish_refresh_cooldown)
|
||||||
|
self.refresh_shortcut = QShortcut(QKeySequence("F5"), self)
|
||||||
|
self.refresh_shortcut.setContext(Qt.ShortcutContext.WidgetWithChildrenShortcut)
|
||||||
|
self.refresh_shortcut.activated.connect(self._refresh_workspace)
|
||||||
|
|
||||||
def _ensure_diagnosis_dialog(self) -> DiagnosisDialog:
|
def _ensure_diagnosis_dialog(self) -> DiagnosisDialog:
|
||||||
dialog = getattr(self, "diagnosis_dialog", None)
|
dialog = getattr(self, "diagnosis_dialog", None)
|
||||||
@@ -3705,6 +3786,14 @@ class ReceptionPage(QWidget):
|
|||||||
title.setObjectName("ReceptionQueueTitle")
|
title.setObjectName("ReceptionQueueTitle")
|
||||||
header_layout.addWidget(title)
|
header_layout.addWidget(title)
|
||||||
header_layout.addStretch(1)
|
header_layout.addStretch(1)
|
||||||
|
self.refresh_button = QPushButton("刷新", header)
|
||||||
|
self.refresh_button.setObjectName("ReceptionRefreshButton")
|
||||||
|
self.refresh_button.setFixedWidth(58)
|
||||||
|
self.refresh_button.setAccessibleName("刷新接诊台")
|
||||||
|
self.refresh_button.setToolTip("刷新队列、当前患者和已保存的 AI 报告(F5)")
|
||||||
|
self.refresh_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
self.refresh_button.clicked.connect(self._refresh_workspace)
|
||||||
|
header_layout.addWidget(self.refresh_button)
|
||||||
self.queue_date_button = _ReceptionDateButton(self._queue_date, header)
|
self.queue_date_button = _ReceptionDateButton(self._queue_date, header)
|
||||||
self.queue_date_button.setObjectName("ReceptionDateButton")
|
self.queue_date_button.setObjectName("ReceptionDateButton")
|
||||||
self.queue_date_button.setFixedWidth(118)
|
self.queue_date_button.setFixedWidth(118)
|
||||||
@@ -3756,7 +3845,7 @@ class ReceptionPage(QWidget):
|
|||||||
self.queue_list.verticalScrollBar().valueChanged.connect(self._on_queue_scroll)
|
self.queue_list.verticalScrollBar().valueChanged.connect(self._on_queue_scroll)
|
||||||
self.queue_stack.addWidget(self.queue_list)
|
self.queue_stack.addWidget(self.queue_list)
|
||||||
self.queue_empty = EmptyState("队列为空", "当前筛选下没有待处理患者。", "重新加载")
|
self.queue_empty = EmptyState("队列为空", "当前筛选下没有待处理患者。", "重新加载")
|
||||||
self.queue_empty.action_requested.connect(lambda: self.refresh())
|
self.queue_empty.action_requested.connect(self._refresh_workspace)
|
||||||
self.queue_stack.addWidget(self.queue_empty)
|
self.queue_stack.addWidget(self.queue_empty)
|
||||||
layout.addWidget(self.queue_stack, 1)
|
layout.addWidget(self.queue_stack, 1)
|
||||||
self.queue_loading_indicator = _ReceptionQueueLoading(panel)
|
self.queue_loading_indicator = _ReceptionQueueLoading(panel)
|
||||||
@@ -3827,10 +3916,7 @@ class ReceptionPage(QWidget):
|
|||||||
patient_head.addLayout(identity, 1)
|
patient_head.addLayout(identity, 1)
|
||||||
patient_head.addStretch(1)
|
patient_head.addStretch(1)
|
||||||
|
|
||||||
self.complete_button = QPushButton("结束问诊", hero)
|
self.complete_button = _ReceptionCompleteButton(hero)
|
||||||
self.complete_button.setObjectName("ReceptionCompleteButton")
|
|
||||||
self.complete_button.setIcon(_painted_reception_action_icon("stop", "#F15B67"))
|
|
||||||
self.complete_button.setIconSize(QSize(14, 14))
|
|
||||||
self.complete_button.clicked.connect(self._complete_appointment)
|
self.complete_button.clicked.connect(self._complete_appointment)
|
||||||
self.complete_button.setVisible(self._can_complete)
|
self.complete_button.setVisible(self._can_complete)
|
||||||
patient_head.addWidget(self.complete_button)
|
patient_head.addWidget(self.complete_button)
|
||||||
@@ -5267,6 +5353,7 @@ class ReceptionPage(QWidget):
|
|||||||
appointment_id: int,
|
appointment_id: int,
|
||||||
diagnosis_id: int | None,
|
diagnosis_id: int | None,
|
||||||
force: bool,
|
force: bool,
|
||||||
|
read_only_refresh: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
if not force and _same_id(patient_id, self._ai_analysis_patient_id):
|
if not force and _same_id(patient_id, self._ai_analysis_patient_id):
|
||||||
qwen_state = self._ai_analysis_model_states["qwen"]
|
qwen_state = self._ai_analysis_model_states["qwen"]
|
||||||
@@ -5313,7 +5400,7 @@ class ReceptionPage(QWidget):
|
|||||||
self._patient_ai_list_requests.discard(cancelled_key)
|
self._patient_ai_list_requests.discard(cancelled_key)
|
||||||
self._patient_ai_list_cancel_events.pop(cancelled_key, None)
|
self._patient_ai_list_cancel_events.pop(cancelled_key, None)
|
||||||
self._patient_ai_list_epochs.pop(cancelled_key, None)
|
self._patient_ai_list_epochs.pop(cancelled_key, None)
|
||||||
if self._patient_ai_request_pending(patient_id, "qwen"):
|
if not read_only_refresh and self._patient_ai_request_pending(patient_id, "qwen"):
|
||||||
self._sync_ai_analysis_view()
|
self._sync_ai_analysis_view()
|
||||||
return
|
return
|
||||||
request_key = (request_generation, appointment_id, patient_id)
|
request_key = (request_generation, appointment_id, patient_id)
|
||||||
@@ -5333,8 +5420,10 @@ class ReceptionPage(QWidget):
|
|||||||
patient_id,
|
patient_id,
|
||||||
) or cancel_event.is_set():
|
) or cancel_event.is_set():
|
||||||
return _ASYNC_REQUEST_CANCELLED
|
return _ASYNC_REQUEST_CANCELLED
|
||||||
automatic_slot = _AI_AUTOMATIC_REQUEST_SLOTS.acquire(blocking=False)
|
automatic_slot = not read_only_refresh and _AI_AUTOMATIC_REQUEST_SLOTS.acquire(
|
||||||
if not automatic_slot:
|
blocking=False
|
||||||
|
)
|
||||||
|
if not read_only_refresh and not automatic_slot:
|
||||||
return _ASYNC_REQUEST_DEFERRED
|
return _ASYNC_REQUEST_DEFERRED
|
||||||
try:
|
try:
|
||||||
self._patient_ai_list_started.add(request_key)
|
self._patient_ai_list_started.add(request_key)
|
||||||
@@ -5347,15 +5436,18 @@ class ReceptionPage(QWidget):
|
|||||||
return _ASYNC_REQUEST_CANCELLED
|
return _ASYNC_REQUEST_CANCELLED
|
||||||
return method(patient_id)
|
return method(patient_id)
|
||||||
finally:
|
finally:
|
||||||
_AI_AUTOMATIC_REQUEST_SLOTS.release()
|
if automatic_slot:
|
||||||
|
_AI_AUTOMATIC_REQUEST_SLOTS.release()
|
||||||
|
|
||||||
run_async(
|
runner = self._run_refresh_read if read_only_refresh else run_async
|
||||||
|
runner(
|
||||||
request,
|
request,
|
||||||
on_success=lambda result: self._apply_patient_ai_report_list(
|
on_success=lambda result: self._apply_patient_ai_report_list(
|
||||||
result,
|
result,
|
||||||
request_generation,
|
request_generation,
|
||||||
appointment_id,
|
appointment_id,
|
||||||
patient_id,
|
patient_id,
|
||||||
|
read_only_refresh=read_only_refresh,
|
||||||
),
|
),
|
||||||
on_error=lambda error: self._patient_ai_report_list_error(
|
on_error=lambda error: self._patient_ai_report_list_error(
|
||||||
error,
|
error,
|
||||||
@@ -5377,6 +5469,8 @@ class ReceptionPage(QWidget):
|
|||||||
request_generation: int,
|
request_generation: int,
|
||||||
appointment_id: int,
|
appointment_id: int,
|
||||||
patient_id: int,
|
patient_id: int,
|
||||||
|
*,
|
||||||
|
read_only_refresh: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
request_key = (request_generation, appointment_id, patient_id)
|
request_key = (request_generation, appointment_id, patient_id)
|
||||||
authoritative = request_key in self._patient_ai_list_requests
|
authoritative = request_key in self._patient_ai_list_requests
|
||||||
@@ -5426,6 +5520,12 @@ class ReceptionPage(QWidget):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if read_only_refresh:
|
||||||
|
self._set_ai_analysis_state(
|
||||||
|
"missing", "暂无已保存的患者报告;刷新不会自动生成,可点击重新分析。"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
if not self._can_ai_regenerate:
|
if not self._can_ai_regenerate:
|
||||||
self._set_ai_analysis_state(
|
self._set_ai_analysis_state(
|
||||||
"missing",
|
"missing",
|
||||||
@@ -6217,14 +6317,111 @@ class ReceptionPage(QWidget):
|
|||||||
self._reset_queue_state()
|
self._reset_queue_state()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
def refresh(self, silent: bool = False) -> None:
|
def _run_refresh_read(
|
||||||
|
self,
|
||||||
|
function: Any,
|
||||||
|
*,
|
||||||
|
on_success: Any,
|
||||||
|
on_error: Any,
|
||||||
|
on_finished: Any,
|
||||||
|
priority: int = 0,
|
||||||
|
) -> None:
|
||||||
|
"""Bound GUI waiting; a timed-out worker may finish but cannot apply data.
|
||||||
|
|
||||||
|
Running HTTP calls are not forcibly terminated. The fixed-size pool
|
||||||
|
bounds concurrency, and expired queued reads never call the backend.
|
||||||
|
"""
|
||||||
|
|
||||||
|
settled = Event()
|
||||||
|
timer = QTimer(self)
|
||||||
|
timer.setSingleShot(True)
|
||||||
|
timer.destroyed.connect(lambda _object=None: settled.set())
|
||||||
|
|
||||||
|
def settle(callback: Any, result: Any) -> None:
|
||||||
|
if settled.is_set():
|
||||||
|
return
|
||||||
|
settled.set()
|
||||||
|
timer.stop()
|
||||||
|
timer.deleteLater()
|
||||||
|
try:
|
||||||
|
callback(result)
|
||||||
|
finally:
|
||||||
|
on_finished()
|
||||||
|
|
||||||
|
def request() -> Any:
|
||||||
|
if settled.is_set():
|
||||||
|
return _ASYNC_REQUEST_CANCELLED
|
||||||
|
return function()
|
||||||
|
|
||||||
|
timer.timeout.connect(
|
||||||
|
lambda: settle(on_error, TimeoutError("刷新超时,请检查网络后再次点击刷新。"))
|
||||||
|
)
|
||||||
|
timer.start(_REFRESH_TIMEOUT_MS)
|
||||||
|
run_async(
|
||||||
|
request,
|
||||||
|
on_success=lambda result: settle(on_success, result),
|
||||||
|
on_error=lambda error: settle(on_error, error),
|
||||||
|
on_finished=lambda: settle(
|
||||||
|
on_error, RuntimeError("刷新未返回有效结果,请重试。")
|
||||||
|
),
|
||||||
|
pool=_RECEPTION_REFRESH_POOL,
|
||||||
|
priority=priority,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _cancel_patient_ai_reads(self, patient_id: int | None) -> None:
|
||||||
|
# Reads are normally shared across selection generations. Explicit
|
||||||
|
# refresh revokes their authority, but never forgets an in-flight POST.
|
||||||
|
for key in list(self._patient_ai_list_requests):
|
||||||
|
if patient_id is not None and not _same_id(key[2], patient_id):
|
||||||
|
continue
|
||||||
|
cancel_event = self._patient_ai_list_cancel_events.pop(key, None)
|
||||||
|
if cancel_event is not None:
|
||||||
|
cancel_event.set()
|
||||||
|
self._patient_ai_list_requests.discard(key)
|
||||||
|
self._patient_ai_list_epochs.pop(key, None)
|
||||||
|
self._patient_ai_list_started.discard(key)
|
||||||
|
|
||||||
|
def _refresh_workspace(self) -> None:
|
||||||
|
"""Recover reads without replaying writes or clearing the doctor's draft."""
|
||||||
|
|
||||||
|
if self._refresh_cooldown.isActive():
|
||||||
|
return
|
||||||
|
if self._note_busy or self._completion_pending:
|
||||||
|
show_toast(self, "正在提交,请等待提交结束后再刷新。", "warning")
|
||||||
|
return
|
||||||
|
if self._completion_dialog is not None and self._completion_dialog.isVisible():
|
||||||
|
show_toast(self, "请先关闭完成问诊窗口,再刷新接诊台。", "warning")
|
||||||
|
return
|
||||||
|
if self._selected_appointment_id is not None and not self.notify_button.isEnabled():
|
||||||
|
show_toast(self, "正在通知医助,请稍后刷新。", "warning")
|
||||||
|
return
|
||||||
|
self.refresh_button.setEnabled(False)
|
||||||
|
self.refresh_button.setCursor(Qt.CursorShape.ArrowCursor)
|
||||||
|
self._refresh_cooldown.start(_REFRESH_COOLDOWN_MS)
|
||||||
|
context = self._selection_context()
|
||||||
|
self._cancel_patient_ai_reads(context[3] if context is not None else None)
|
||||||
|
# Invalidate a pending daily-range result before the fresh detail arrives.
|
||||||
|
self._daily_generation += 1
|
||||||
|
self._daily_loading = False
|
||||||
|
self.daily_panel.set_loading(False)
|
||||||
|
record = self._selected_record
|
||||||
|
if record is not None:
|
||||||
|
self._load_detail(record, clear=False, read_only_refresh=True)
|
||||||
|
# A stuck queue must not prevent refreshing the selected patient's detail.
|
||||||
|
self.refresh(workspace_refresh=True)
|
||||||
|
|
||||||
|
def _finish_refresh_cooldown(self) -> None:
|
||||||
|
self.refresh_button.setEnabled(True)
|
||||||
|
self.refresh_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
|
||||||
|
def refresh(self, silent: bool = False, *, workspace_refresh: bool = False) -> None:
|
||||||
"""Replace the queue with page one using a GUI-thread query snapshot."""
|
"""Replace the queue with page one using a GUI-thread query snapshot."""
|
||||||
|
|
||||||
if silent and self._queue_loading:
|
if silent and self._queue_loading and not workspace_refresh:
|
||||||
return
|
return
|
||||||
selected_date = self._queue_date or date.today().isoformat()
|
selected_date = self._queue_date or date.today().isoformat()
|
||||||
page_size = self._queue_page_size
|
page_size = self._queue_page_size
|
||||||
if silent:
|
if silent or workspace_refresh:
|
||||||
loaded = max(len(self._queue_records), self._queue_page * self._queue_page_size)
|
loaded = max(len(self._queue_records), self._queue_page * self._queue_page_size)
|
||||||
if loaded > page_size:
|
if loaded > page_size:
|
||||||
page_size = loaded
|
page_size = loaded
|
||||||
@@ -6239,12 +6436,15 @@ class ReceptionPage(QWidget):
|
|||||||
}
|
}
|
||||||
query_key = self._query_key(query)
|
query_key = self._query_key(query)
|
||||||
if query_key != self._queue_query_key:
|
if query_key != self._queue_query_key:
|
||||||
self._clear_selection()
|
if not workspace_refresh:
|
||||||
|
self._clear_selection()
|
||||||
self._reset_queue_state()
|
self._reset_queue_state()
|
||||||
self._queue_query = dict(query)
|
self._queue_query = dict(query)
|
||||||
self._queue_query["page_size"] = self._queue_page_size
|
self._queue_query["page_size"] = self._queue_page_size
|
||||||
self._queue_query_key = query_key
|
self._queue_query_key = query_key
|
||||||
self._request_queue_page(query, append=False, silent=silent)
|
self._request_queue_page(
|
||||||
|
query, append=False, silent=silent, workspace_refresh=workspace_refresh
|
||||||
|
)
|
||||||
|
|
||||||
def _poll_queue(self) -> None:
|
def _poll_queue(self) -> None:
|
||||||
"""Do not let the timer supersede an explicit or slower queue request."""
|
"""Do not let the timer supersede an explicit or slower queue request."""
|
||||||
@@ -6401,6 +6601,7 @@ class ReceptionPage(QWidget):
|
|||||||
*,
|
*,
|
||||||
append: bool,
|
append: bool,
|
||||||
silent: bool,
|
silent: bool,
|
||||||
|
workspace_refresh: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._queue_generation += 1
|
self._queue_generation += 1
|
||||||
generation = self._queue_generation
|
generation = self._queue_generation
|
||||||
@@ -6412,12 +6613,18 @@ class ReceptionPage(QWidget):
|
|||||||
frozen_query = dict(query)
|
frozen_query = dict(query)
|
||||||
page_no = int(frozen_query["page_no"])
|
page_no = int(frozen_query["page_no"])
|
||||||
query_key = self._query_key(frozen_query)
|
query_key = self._query_key(frozen_query)
|
||||||
run_async(
|
def request() -> Any:
|
||||||
lambda frozen_query=frozen_query: invoke(
|
if generation != self._queue_generation:
|
||||||
|
return _ASYNC_REQUEST_CANCELLED
|
||||||
|
return invoke(
|
||||||
self.repository,
|
self.repository,
|
||||||
"list_appointments",
|
"list_appointments",
|
||||||
**frozen_query,
|
**frozen_query,
|
||||||
),
|
)
|
||||||
|
|
||||||
|
runner = self._run_refresh_read if workspace_refresh else run_async
|
||||||
|
runner(
|
||||||
|
request,
|
||||||
on_success=lambda result: self._apply_queue(
|
on_success=lambda result: self._apply_queue(
|
||||||
result,
|
result,
|
||||||
generation,
|
generation,
|
||||||
@@ -6425,6 +6632,7 @@ class ReceptionPage(QWidget):
|
|||||||
append=append,
|
append=append,
|
||||||
query_key=query_key,
|
query_key=query_key,
|
||||||
silent=silent,
|
silent=silent,
|
||||||
|
workspace_refresh=workspace_refresh,
|
||||||
),
|
),
|
||||||
on_error=lambda error: self._queue_error(error, generation, silent=silent),
|
on_error=lambda error: self._queue_error(error, generation, silent=silent),
|
||||||
on_finished=lambda: self._queue_finished(generation),
|
on_finished=lambda: self._queue_finished(generation),
|
||||||
@@ -6439,6 +6647,7 @@ class ReceptionPage(QWidget):
|
|||||||
append: bool = False,
|
append: bool = False,
|
||||||
query_key: tuple[Any, ...] | None = None,
|
query_key: tuple[Any, ...] | None = None,
|
||||||
silent: bool = False,
|
silent: bool = False,
|
||||||
|
workspace_refresh: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
if generation != self._queue_generation or query_key not in (None, self._queue_query_key):
|
if generation != self._queue_generation or query_key not in (None, self._queue_query_key):
|
||||||
return
|
return
|
||||||
@@ -6480,27 +6689,38 @@ class ReceptionPage(QWidget):
|
|||||||
),
|
),
|
||||||
-1,
|
-1,
|
||||||
)
|
)
|
||||||
if row_to_select < 0 and records:
|
preserve_selection = (workspace_refresh or silent) and selected_id is not None
|
||||||
|
if row_to_select < 0 and records and not preserve_selection:
|
||||||
row_to_select = 0
|
row_to_select = 0
|
||||||
self.queue_list.blockSignals(True)
|
self.queue_list.blockSignals(True)
|
||||||
self._sync_queue_rows(records, append=append)
|
self._sync_queue_rows(records, append=append)
|
||||||
if row_to_select >= 0 and self.queue_list.currentRow() != row_to_select:
|
if row_to_select >= 0 and self.queue_list.currentRow() != row_to_select:
|
||||||
self.queue_list.setCurrentRow(row_to_select)
|
self.queue_list.setCurrentRow(row_to_select)
|
||||||
|
elif row_to_select < 0:
|
||||||
|
self.queue_list.setCurrentRow(-1)
|
||||||
self.queue_list.blockSignals(False)
|
self.queue_list.blockSignals(False)
|
||||||
self._sync_queue_row_selection()
|
self._sync_queue_row_selection()
|
||||||
self.queue_summary.setText(f"已加载 {len(records)} / 共 {self._queue_total} 位患者")
|
self.queue_summary.setText(f"已加载 {len(records)} / 共 {self._queue_total} 位患者")
|
||||||
self.queue_stack.setCurrentIndex(0 if records else 1)
|
self.queue_stack.setCurrentIndex(0 if records else 1)
|
||||||
self.queue_banner.clear()
|
self.queue_banner.clear()
|
||||||
if not records:
|
if row_to_select < 0:
|
||||||
self._clear_selection()
|
# The patient may have left the queue. Keep the detail and unsaved
|
||||||
|
# draft attached to that patient until the doctor selects another.
|
||||||
|
if preserve_selection:
|
||||||
|
self.queue_banner.show_message(
|
||||||
|
"当前患者已不在筛选队列,已保留详情与未保存内容,可手动选择其他患者。",
|
||||||
|
"info",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._clear_selection()
|
||||||
return
|
return
|
||||||
chosen = records[row_to_select]
|
chosen = records[row_to_select]
|
||||||
if selected_id is not None and _same_id(_record_id(chosen), selected_id):
|
if selected_id is not None and _same_id(_record_id(chosen), selected_id):
|
||||||
self._selected_record = chosen
|
self._selected_record = chosen
|
||||||
if not append and not silent:
|
if not append and not silent and not workspace_refresh:
|
||||||
self._load_detail(chosen, silent=True, clear=False)
|
self._load_detail(chosen, silent=True, clear=False)
|
||||||
else:
|
else:
|
||||||
self._select_record(chosen, silent=True)
|
self._select_record(chosen, silent=True, read_only_refresh=workspace_refresh)
|
||||||
|
|
||||||
def _update_queue_filter_counts(self, result: Any, records: list[Any]) -> None:
|
def _update_queue_filter_counts(self, result: Any, records: list[Any]) -> None:
|
||||||
extend = get_value(result, "extend", None)
|
extend = get_value(result, "extend", None)
|
||||||
@@ -6573,7 +6793,9 @@ class ReceptionPage(QWidget):
|
|||||||
if isinstance(row, QueueRow):
|
if isinstance(row, QueueRow):
|
||||||
row.set_selected(item is current)
|
row.set_selected(item is current)
|
||||||
|
|
||||||
def _select_record(self, record: Any, *, silent: bool = False) -> None:
|
def _select_record(
|
||||||
|
self, record: Any, *, silent: bool = False, read_only_refresh: bool = False
|
||||||
|
) -> None:
|
||||||
appointment_id = _record_id(record)
|
appointment_id = _record_id(record)
|
||||||
if appointment_id is None:
|
if appointment_id is None:
|
||||||
self._clear_selection()
|
self._clear_selection()
|
||||||
@@ -6589,9 +6811,16 @@ class ReceptionPage(QWidget):
|
|||||||
self._selected_record = record
|
self._selected_record = record
|
||||||
self._selected_appointment_id = appointment_id
|
self._selected_appointment_id = appointment_id
|
||||||
self._selected_detail = None
|
self._selected_detail = None
|
||||||
self._load_detail(record, silent=silent, clear=True)
|
self._load_detail(record, silent=silent, clear=True, read_only_refresh=read_only_refresh)
|
||||||
|
|
||||||
def _load_detail(self, record: Any, silent: bool = False, *, clear: bool = True) -> None:
|
def _load_detail(
|
||||||
|
self,
|
||||||
|
record: Any,
|
||||||
|
silent: bool = False,
|
||||||
|
*,
|
||||||
|
clear: bool = True,
|
||||||
|
read_only_refresh: bool = False,
|
||||||
|
) -> None:
|
||||||
"""Start a new detail generation even while an older request is running."""
|
"""Start a new detail generation even while an older request is running."""
|
||||||
|
|
||||||
appointment_id = _record_id(record)
|
appointment_id = _record_id(record)
|
||||||
@@ -6614,9 +6843,12 @@ class ReceptionPage(QWidget):
|
|||||||
self.detail_banner.show_message("正在加载患者详情…", "info")
|
self.detail_banner.show_message("正在加载患者详情…", "info")
|
||||||
self._detail_loading = True
|
self._detail_loading = True
|
||||||
self._detail_requests.add(request_key)
|
self._detail_requests.add(request_key)
|
||||||
run_async(
|
runner = self._run_refresh_read if read_only_refresh else run_async
|
||||||
|
runner(
|
||||||
lambda: self._fetch_detail_bundle(record, appointment_id, cancel_event),
|
lambda: self._fetch_detail_bundle(record, appointment_id, cancel_event),
|
||||||
on_success=lambda bundle: self._apply_detail(bundle, generation, appointment_id),
|
on_success=lambda bundle: self._apply_detail(
|
||||||
|
bundle, generation, appointment_id, read_only_refresh=read_only_refresh
|
||||||
|
),
|
||||||
on_error=lambda error: self._detail_error(error, generation, appointment_id),
|
on_error=lambda error: self._detail_error(error, generation, appointment_id),
|
||||||
on_finished=lambda: self._detail_finished(generation, appointment_id),
|
on_finished=lambda: self._detail_finished(generation, appointment_id),
|
||||||
priority=generation,
|
priority=generation,
|
||||||
@@ -6877,7 +7109,12 @@ class ReceptionPage(QWidget):
|
|||||||
self.daily_panel.set_loading(False)
|
self.daily_panel.set_loading(False)
|
||||||
|
|
||||||
def _apply_detail(
|
def _apply_detail(
|
||||||
self, bundle: Any, generation: int, appointment_id: int | None = None
|
self,
|
||||||
|
bundle: Any,
|
||||||
|
generation: int,
|
||||||
|
appointment_id: int | None = None,
|
||||||
|
*,
|
||||||
|
read_only_refresh: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
expected_id = appointment_id or self._selected_appointment_id
|
expected_id = appointment_id or self._selected_appointment_id
|
||||||
if (
|
if (
|
||||||
@@ -6966,7 +7203,9 @@ class ReceptionPage(QWidget):
|
|||||||
supports_patient_reports = self._can_patient_ai_read and callable(
|
supports_patient_reports = self._can_patient_ai_read and callable(
|
||||||
getattr(self.repository, "list_patient_ai_reports", None)
|
getattr(self.repository, "list_patient_ai_reports", None)
|
||||||
) and callable(getattr(self.repository, "generate_patient_ai_report", None))
|
) and callable(getattr(self.repository, "generate_patient_ai_report", None))
|
||||||
if patient_id is None and supports_patient_reports:
|
if read_only_refresh:
|
||||||
|
self._refresh_saved_ai_reports(expected_id, diagnosis_id, patient_id)
|
||||||
|
elif patient_id is None and supports_patient_reports:
|
||||||
self._ai_analysis_generation += 1
|
self._ai_analysis_generation += 1
|
||||||
self._ai_analysis_loading = False
|
self._ai_analysis_loading = False
|
||||||
self._ai_analysis_diagnosis_id = None
|
self._ai_analysis_diagnosis_id = None
|
||||||
@@ -6988,6 +7227,37 @@ class ReceptionPage(QWidget):
|
|||||||
patient_id=patient_id,
|
patient_id=patient_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _refresh_saved_ai_reports(
|
||||||
|
self, appointment_id: int, diagnosis_id: int | None, patient_id: int | None
|
||||||
|
) -> None:
|
||||||
|
self._cancel_patient_ai_reads(patient_id)
|
||||||
|
if self._can_patient_ai_read and patient_id is not None and callable(
|
||||||
|
getattr(self.repository, "list_patient_ai_reports", None)
|
||||||
|
):
|
||||||
|
# A generation is a write with an uncertain outcome while running.
|
||||||
|
# Keep its single-flight identity and do not race it with an older GET.
|
||||||
|
if any(
|
||||||
|
self._patient_ai_request_pending(patient_id, model)
|
||||||
|
for model in AI_ANALYSIS_MODELS
|
||||||
|
):
|
||||||
|
self._ai_analysis_operation_error = "报告生成任务仍在处理中,刷新不会重复生成。"
|
||||||
|
self._sync_ai_analysis_view()
|
||||||
|
return
|
||||||
|
self._load_patient_ai_reports(
|
||||||
|
patient_id,
|
||||||
|
appointment_id=appointment_id,
|
||||||
|
diagnosis_id=diagnosis_id,
|
||||||
|
force=True,
|
||||||
|
read_only_refresh=True,
|
||||||
|
)
|
||||||
|
elif not self._can_ai_analysis:
|
||||||
|
self._set_ai_analysis_state("permission")
|
||||||
|
elif not self._ai_analysis_payloads and not self._ai_analysis_requests:
|
||||||
|
# The legacy analysis endpoint is a POST despite its get_* name.
|
||||||
|
self._set_ai_analysis_state(
|
||||||
|
"error", "当前数据源无法只读刷新 AI 报告;如需生成分析,请点击重试。"
|
||||||
|
)
|
||||||
|
|
||||||
def _render_identity(self, appointment: Any, patient: Any, diagnosis: Any) -> None:
|
def _render_identity(self, appointment: Any, patient: Any, diagnosis: Any) -> None:
|
||||||
patient_name = first_value(
|
patient_name = first_value(
|
||||||
appointment,
|
appointment,
|
||||||
@@ -8168,7 +8438,10 @@ class ReceptionPage(QWidget):
|
|||||||
self.history_button.setEnabled(appointment_id is not None)
|
self.history_button.setEnabled(appointment_id is not None)
|
||||||
self.more_button.setEnabled(appointment_id is not None)
|
self.more_button.setEnabled(appointment_id is not None)
|
||||||
self.complete_button.setEnabled(
|
self.complete_button.setEnabled(
|
||||||
self._can_complete and appointment_id is not None and status in RECEPTION_STATUSES
|
self._can_complete
|
||||||
|
and not self._completion_pending
|
||||||
|
and appointment_id is not None
|
||||||
|
and status in RECEPTION_STATUSES
|
||||||
)
|
)
|
||||||
note_enabled = self._can_note and diagnosis_id is not None and not self._note_busy
|
note_enabled = self._can_note and diagnosis_id is not None and not self._note_busy
|
||||||
self.note_edit.setEnabled(note_enabled)
|
self.note_edit.setEnabled(note_enabled)
|
||||||
@@ -8180,6 +8453,10 @@ class ReceptionPage(QWidget):
|
|||||||
self, error: Exception, generation: int, appointment_id: int | None = None
|
self, error: Exception, generation: int, appointment_id: int | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
expected_id = appointment_id or self._selected_appointment_id
|
expected_id = appointment_id or self._selected_appointment_id
|
||||||
|
if expected_id is not None:
|
||||||
|
cancel_event = self._detail_cancel_events.get((generation, expected_id))
|
||||||
|
if cancel_event is not None:
|
||||||
|
cancel_event.set()
|
||||||
if (
|
if (
|
||||||
generation == self._detail_generation
|
generation == self._detail_generation
|
||||||
and expected_id is not None
|
and expected_id is not None
|
||||||
@@ -8734,6 +9011,12 @@ class ReceptionPage(QWidget):
|
|||||||
self._load_detail(self._selected_record, silent=True, clear=False)
|
self._load_detail(self._selected_record, silent=True, clear=False)
|
||||||
|
|
||||||
def _complete_appointment(self) -> None:
|
def _complete_appointment(self) -> None:
|
||||||
|
if self._completion_pending:
|
||||||
|
return
|
||||||
|
if self._completion_dialog is not None:
|
||||||
|
self._completion_dialog.raise_()
|
||||||
|
self._completion_dialog.activateWindow()
|
||||||
|
return
|
||||||
if not self._can_complete:
|
if not self._can_complete:
|
||||||
show_toast(self, "当前账号没有完成接诊权限。", "danger")
|
show_toast(self, "当前账号没有完成接诊权限。", "danger")
|
||||||
return
|
return
|
||||||
@@ -8748,24 +9031,75 @@ class ReceptionPage(QWidget):
|
|||||||
if status not in RECEPTION_STATUSES:
|
if status not in RECEPTION_STATUSES:
|
||||||
show_toast(self, "仅待接诊或已过号记录可以完成接诊。", "danger")
|
show_toast(self, "仅待接诊或已过号记录可以完成接诊。", "danger")
|
||||||
return
|
return
|
||||||
answer = QMessageBox.question(
|
dialog = AppointmentCompleteDialog(can_note=self._can_note, parent=self)
|
||||||
self,
|
self._completion_dialog = dialog
|
||||||
"确认完成接诊",
|
dialog.submitted.connect(
|
||||||
"系统会再次核对服务端挂号状态;完成后不可撤销。确认继续吗?",
|
lambda note: self._submit_completion(dialog, generation, appointment_id, note)
|
||||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel,
|
|
||||||
QMessageBox.StandardButton.Cancel,
|
|
||||||
)
|
)
|
||||||
if answer != QMessageBox.StandardButton.Yes:
|
dialog.finished.connect(lambda _result: self._close_completion_dialog(dialog))
|
||||||
|
dialog.open()
|
||||||
|
|
||||||
|
def _close_completion_dialog(self, dialog: AppointmentCompleteDialog) -> None:
|
||||||
|
if self._completion_dialog is dialog:
|
||||||
|
self._completion_dialog = None
|
||||||
|
dialog.deleteLater()
|
||||||
|
|
||||||
|
def _submit_completion(
|
||||||
|
self,
|
||||||
|
dialog: AppointmentCompleteDialog,
|
||||||
|
generation: int,
|
||||||
|
appointment_id: int,
|
||||||
|
note: str,
|
||||||
|
) -> None:
|
||||||
|
if self._completion_pending or self._completion_dialog is not dialog:
|
||||||
return
|
return
|
||||||
|
if not self._context_current(generation, appointment_id):
|
||||||
|
dialog.show_error("当前患者已切换或详情已更新,请关闭窗口后重新操作。")
|
||||||
|
return
|
||||||
|
self._completion_pending = True
|
||||||
|
dialog.set_busy(True)
|
||||||
self.complete_button.setEnabled(False)
|
self.complete_button.setEnabled(False)
|
||||||
run_async(
|
run_async(
|
||||||
lambda: self._complete_after_revalidation(appointment_id),
|
lambda: self._complete_after_revalidation(appointment_id, note),
|
||||||
on_success=lambda _result: self._appointment_completed(generation, appointment_id),
|
on_success=lambda warning: self._completion_succeeded(
|
||||||
on_error=lambda error: show_toast(self, friendly_error(error), "danger", 4200),
|
dialog, generation, appointment_id, warning
|
||||||
on_finished=lambda: self._restore_action_state(generation, appointment_id),
|
),
|
||||||
|
on_error=lambda error: self._completion_failed(dialog, error),
|
||||||
|
on_finished=self._completion_finished,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _complete_after_revalidation(self, appointment_id: int) -> Any:
|
def _completion_succeeded(
|
||||||
|
self,
|
||||||
|
dialog: AppointmentCompleteDialog,
|
||||||
|
generation: int,
|
||||||
|
appointment_id: int,
|
||||||
|
warning: str,
|
||||||
|
) -> None:
|
||||||
|
if self._completion_dialog is dialog:
|
||||||
|
if warning:
|
||||||
|
dialog.show_completed_warning(warning)
|
||||||
|
else:
|
||||||
|
dialog.set_busy(False)
|
||||||
|
dialog.accept()
|
||||||
|
self._appointment_completed(generation, appointment_id, warning)
|
||||||
|
|
||||||
|
def _completion_failed(self, dialog: AppointmentCompleteDialog, error: Exception) -> None:
|
||||||
|
if self._completion_dialog is dialog:
|
||||||
|
dialog.show_error(friendly_error(error))
|
||||||
|
|
||||||
|
def _completion_finished(self) -> None:
|
||||||
|
self._completion_pending = False
|
||||||
|
if self._selected_appointment_id is not None:
|
||||||
|
self._restore_action_state(self._detail_generation, self._selected_appointment_id)
|
||||||
|
|
||||||
|
def _complete_after_revalidation(self, appointment_id: int, note: str = "") -> str:
|
||||||
|
if not self._can_complete:
|
||||||
|
raise ValueError("当前账号没有完成接诊权限。")
|
||||||
|
note = note.strip()
|
||||||
|
if note and not self._can_note:
|
||||||
|
raise ValueError("当前账号没有添加医生备注权限。")
|
||||||
|
if len(note) > COMPLETION_NOTE_LIMIT:
|
||||||
|
raise ValueError(f"备注不能超过 {COMPLETION_NOTE_LIMIT} 字。")
|
||||||
detail = invoke(
|
detail = invoke(
|
||||||
self.repository,
|
self.repository,
|
||||||
"reception_detail",
|
"reception_detail",
|
||||||
@@ -8784,15 +9118,35 @@ class ReceptionPage(QWidget):
|
|||||||
raise ValueError("服务端挂号记录与当前患者不一致,已停止完成操作")
|
raise ValueError("服务端挂号记录与当前患者不一致,已停止完成操作")
|
||||||
if status not in RECEPTION_STATUSES:
|
if status not in RECEPTION_STATUSES:
|
||||||
raise ValueError("挂号状态已变化,请刷新队列后重试")
|
raise ValueError("挂号状态已变化,请刷新队列后重试")
|
||||||
return invoke(
|
invoke(
|
||||||
self.repository,
|
self.repository,
|
||||||
"complete_appointment",
|
"complete_appointment",
|
||||||
appointment_id=appointment_id,
|
appointment_id=appointment_id,
|
||||||
id=appointment_id,
|
id=appointment_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _appointment_completed(self, generation: int, appointment_id: int) -> None:
|
if note:
|
||||||
show_toast(self, "接诊已完成。", "success")
|
# Use the freshly validated diagnosis, never the patient's ID or
|
||||||
|
# mutable selection: notes belong to the diagnosis timeline.
|
||||||
|
diagnosis = get_value(detail, "diagnosis", None) or {}
|
||||||
|
diagnosis_id = _as_int(first_value(diagnosis, "id", "diagnosis_id", default=None))
|
||||||
|
if diagnosis_id is None or diagnosis_id <= 0:
|
||||||
|
return "问诊已完成,但该预约没有关联诊单,备注未保存"
|
||||||
|
try:
|
||||||
|
invoke(
|
||||||
|
self.repository,
|
||||||
|
"add_doctor_note",
|
||||||
|
diagnosis_id=diagnosis_id,
|
||||||
|
content=note,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return "问诊已完成,但备注未保存"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def _appointment_completed(
|
||||||
|
self, generation: int, appointment_id: int, warning: str = ""
|
||||||
|
) -> None:
|
||||||
|
show_toast(self, warning or "接诊已完成。", "warning" if warning else "success")
|
||||||
if self._context_current(generation, appointment_id):
|
if self._context_current(generation, appointment_id):
|
||||||
self._clear_selection()
|
self._clear_selection()
|
||||||
self.refresh(silent=True)
|
self.refresh(silent=True)
|
||||||
|
|||||||
@@ -0,0 +1,306 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
from doctor_workstation.core import PermissionSet
|
||||||
|
from doctor_workstation.ui.dialogs.appointment_complete import (
|
||||||
|
COMPLETION_NOTE_LIMIT,
|
||||||
|
AppointmentCompleteDialog,
|
||||||
|
)
|
||||||
|
from doctor_workstation.ui.pages import reception as reception_module
|
||||||
|
from doctor_workstation.ui.pages.reception import ReceptionPage
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def application() -> QApplication:
|
||||||
|
return QApplication.instance() or QApplication([])
|
||||||
|
|
||||||
|
|
||||||
|
class CompletionRepository:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.calls: list[tuple[Any, ...]] = []
|
||||||
|
self.fail_complete = False
|
||||||
|
self.fail_note = False
|
||||||
|
self.detail: dict[str, Any] = {
|
||||||
|
"appointment": {"id": 51, "patient_id": 251, "status": 1},
|
||||||
|
"diagnosis": {"id": 251, "patient_id": 151},
|
||||||
|
"patient": {"id": 151},
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_reception(self, appointment_id: int) -> dict[str, Any]:
|
||||||
|
self.calls.append(("revalidate", appointment_id))
|
||||||
|
return self.detail
|
||||||
|
|
||||||
|
def complete_appointment(self, appointment_id: int) -> dict[str, bool]:
|
||||||
|
self.calls.append(("complete", appointment_id))
|
||||||
|
if self.fail_complete:
|
||||||
|
raise RuntimeError("完成接口失败")
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
def add_doctor_note(self, diagnosis_id: int, content: str) -> dict[str, bool]:
|
||||||
|
self.calls.append(("note", diagnosis_id, content))
|
||||||
|
if self.fail_note:
|
||||||
|
raise RuntimeError("备注接口失败")
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def harness(application: QApplication, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
jobs: list[dict[str, Any]] = []
|
||||||
|
toasts: list[tuple[str, str]] = []
|
||||||
|
refreshes: list[bool] = []
|
||||||
|
|
||||||
|
def queue(function: Any, **options: Any) -> object:
|
||||||
|
jobs.append({"function": function, **options})
|
||||||
|
return object()
|
||||||
|
|
||||||
|
monkeypatch.setattr(reception_module, "run_async", queue)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
reception_module,
|
||||||
|
"show_toast",
|
||||||
|
lambda _parent, text, kind, *_args: toasts.append((text, kind)),
|
||||||
|
)
|
||||||
|
repository = CompletionRepository()
|
||||||
|
page = ReceptionPage(
|
||||||
|
repository,
|
||||||
|
PermissionSet(["doctor.appointment/complete", "doctor.appointment/addDoctorNote"]),
|
||||||
|
)
|
||||||
|
page._selected_appointment_id = 51
|
||||||
|
page._selected_record = dict(repository.detail["appointment"])
|
||||||
|
page._selected_detail = repository.detail
|
||||||
|
page._update_action_state(repository.detail["appointment"], repository.detail["diagnosis"])
|
||||||
|
monkeypatch.setattr(page, "refresh", lambda *, silent=False: refreshes.append(silent))
|
||||||
|
yield page, repository, jobs, toasts, refreshes
|
||||||
|
if page._completion_dialog is not None:
|
||||||
|
page._completion_dialog.set_busy(False)
|
||||||
|
page._completion_dialog.reject()
|
||||||
|
page.close()
|
||||||
|
application.processEvents()
|
||||||
|
|
||||||
|
|
||||||
|
def finish_job(job: dict[str, Any]) -> None:
|
||||||
|
try:
|
||||||
|
result = job["function"]()
|
||||||
|
except Exception as error:
|
||||||
|
job["on_error"](error)
|
||||||
|
else:
|
||||||
|
job["on_success"](result)
|
||||||
|
finally:
|
||||||
|
job["on_finished"]()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("can_note", [True, False])
|
||||||
|
def test_completion_dialog_optional_note_limit_and_busy_state(
|
||||||
|
application: QApplication, can_note: bool
|
||||||
|
) -> None:
|
||||||
|
dialog = AppointmentCompleteDialog(can_note=can_note)
|
||||||
|
submitted: list[str] = []
|
||||||
|
dialog.submitted.connect(submitted.append)
|
||||||
|
dialog.show()
|
||||||
|
application.processEvents()
|
||||||
|
try:
|
||||||
|
assert dialog.windowTitle() == "完成问诊"
|
||||||
|
assert dialog.note_edit.isVisible() is can_note
|
||||||
|
assert dialog.note_counter.isVisible() is can_note
|
||||||
|
assert dialog.note_counter.text() == "0 / 500"
|
||||||
|
dialog.note_edit.setPlainText("字" * 501)
|
||||||
|
assert dialog.note_edit.toPlainText() == "字" * COMPLETION_NOTE_LIMIT
|
||||||
|
assert dialog.note_counter.text() == "500 / 500"
|
||||||
|
dialog.note_edit.insertPlainText("额外内容")
|
||||||
|
assert len(dialog.note_edit.toPlainText()) == COMPLETION_NOTE_LIMIT
|
||||||
|
dialog.note_edit.setPlainText(" 测试备注\n第二行 ")
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
assert submitted == ["测试备注\n第二行" if can_note else ""]
|
||||||
|
dialog.set_busy(True)
|
||||||
|
assert dialog.note_edit.isReadOnly()
|
||||||
|
assert not dialog.cancel_button.isEnabled()
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
dialog.reject()
|
||||||
|
dialog.close()
|
||||||
|
assert len(submitted) == 1
|
||||||
|
assert dialog.isVisible()
|
||||||
|
dialog.show_error("提交失败,请重试")
|
||||||
|
assert dialog.note_edit.toPlainText() == " 测试备注\n第二行 "
|
||||||
|
assert dialog.confirm_button.isEnabled()
|
||||||
|
dialog.cancel_button.click()
|
||||||
|
assert not dialog.isVisible()
|
||||||
|
finally:
|
||||||
|
dialog.set_busy(False)
|
||||||
|
dialog.close()
|
||||||
|
|
||||||
|
|
||||||
|
def test_cancel_completion_does_not_make_requests(harness: Any) -> None:
|
||||||
|
page, repository, jobs, _toasts, _refreshes = harness
|
||||||
|
page.complete_button.click()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
assert isinstance(dialog, AppointmentCompleteDialog)
|
||||||
|
page._complete_appointment()
|
||||||
|
assert page._completion_dialog is dialog
|
||||||
|
assert jobs == []
|
||||||
|
dialog.note_edit.setPlainText("取消后不应保存")
|
||||||
|
dialog.cancel_button.click()
|
||||||
|
assert page._completion_dialog is None
|
||||||
|
assert repository.calls == []
|
||||||
|
assert jobs == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("note", ["", " \n ", " 测试备注\n补充内容 ", "字" * 500])
|
||||||
|
def test_complete_then_append_note_and_refresh_without_duplicate_submission(
|
||||||
|
harness: Any, note: str
|
||||||
|
) -> None:
|
||||||
|
page, repository, jobs, toasts, refreshes = harness
|
||||||
|
page.complete_button.click()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
dialog.note_edit.setPlainText(note)
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
assert page._completion_pending
|
||||||
|
assert not page.complete_button.isEnabled()
|
||||||
|
assert len(jobs) == 1
|
||||||
|
# Polling and direct handler calls cannot enable/dispatch a second request.
|
||||||
|
page._update_action_state(repository.detail["appointment"], repository.detail["diagnosis"])
|
||||||
|
assert not page.complete_button.isEnabled()
|
||||||
|
page._complete_appointment()
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
assert len(jobs) == 1
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
expected = [("revalidate", 51), ("complete", 51)]
|
||||||
|
if note.strip():
|
||||||
|
expected.append(("note", 251, note.strip()))
|
||||||
|
assert repository.calls == expected
|
||||||
|
assert page._completion_dialog is None
|
||||||
|
assert not page._completion_pending
|
||||||
|
assert page._selected_appointment_id is None
|
||||||
|
assert toasts[-1] == ("接诊已完成。", "success")
|
||||||
|
assert refreshes == [True]
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_without_note_permission_does_not_submit_hidden_note(harness: Any) -> None:
|
||||||
|
page, repository, jobs, _toasts, _refreshes = harness
|
||||||
|
page._can_note = False
|
||||||
|
page._complete_appointment()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
assert dialog.note_edit.isHidden()
|
||||||
|
dialog.note_edit.setPlainText("不可提交")
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
assert repository.calls == [("revalidate", 51), ("complete", 51)]
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_failure_preserves_note_and_allows_explicit_retry(harness: Any) -> None:
|
||||||
|
page, repository, jobs, toasts, refreshes = harness
|
||||||
|
repository.fail_complete = True
|
||||||
|
page._complete_appointment()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
dialog.note_edit.setPlainText("需要保留的备注")
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
assert repository.calls == [("revalidate", 51), ("complete", 51)]
|
||||||
|
assert page._completion_dialog is dialog
|
||||||
|
assert dialog.isVisible()
|
||||||
|
assert dialog.note_edit.toPlainText() == "需要保留的备注"
|
||||||
|
assert dialog.confirm_button.isEnabled()
|
||||||
|
assert "完成接口失败" in dialog.banner.label.text()
|
||||||
|
assert not page._completion_pending
|
||||||
|
assert page.complete_button.isEnabled()
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert toasts == []
|
||||||
|
assert refreshes == []
|
||||||
|
repository.fail_complete = False
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
assert repository.calls[-1] == ("note", 251, "需要保留的备注")
|
||||||
|
assert page._completion_dialog is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("missing_diagnosis", [True, False])
|
||||||
|
def test_note_failure_is_partial_success_and_keeps_note_for_copying(
|
||||||
|
harness: Any, missing_diagnosis: bool
|
||||||
|
) -> None:
|
||||||
|
page, repository, jobs, toasts, refreshes = harness
|
||||||
|
if missing_diagnosis:
|
||||||
|
repository.detail["diagnosis"] = {}
|
||||||
|
else:
|
||||||
|
repository.fail_note = True
|
||||||
|
page._complete_appointment()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
dialog.note_edit.setPlainText("备注不能丢失")
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
assert [call[0] for call in repository.calls] == (
|
||||||
|
["revalidate", "complete"] if missing_diagnosis else ["revalidate", "complete", "note"]
|
||||||
|
)
|
||||||
|
assert page._selected_appointment_id is None
|
||||||
|
assert refreshes == [True]
|
||||||
|
assert toasts[-1][1] == "warning"
|
||||||
|
assert "问诊已完成" in dialog.banner.label.text()
|
||||||
|
assert "备注未保存" in dialog.banner.label.text()
|
||||||
|
assert dialog.note_edit.toPlainText() == "备注不能丢失"
|
||||||
|
assert dialog.note_edit.isReadOnly()
|
||||||
|
assert dialog.confirm_button.isHidden()
|
||||||
|
assert not dialog.confirm_button.isEnabled()
|
||||||
|
assert dialog.cancel_button.text() == "关闭"
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
assert jobs == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("changed_id", [True, False])
|
||||||
|
def test_completion_revalidation_rejects_changed_record_before_any_write(
|
||||||
|
harness: Any, changed_id: bool
|
||||||
|
) -> None:
|
||||||
|
page, repository, _jobs, _toasts, _refreshes = harness
|
||||||
|
if changed_id:
|
||||||
|
repository.detail["appointment"]["id"] = 52
|
||||||
|
else:
|
||||||
|
repository.detail["appointment"]["status"] = 3
|
||||||
|
with pytest.raises(ValueError, match="不一致|状态已变化"):
|
||||||
|
page._complete_after_revalidation(51, "测试备注")
|
||||||
|
assert repository.calls == [("revalidate", 51)]
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_checks_permissions_and_note_length_before_requests(harness: Any) -> None:
|
||||||
|
page, repository, jobs, _toasts, _refreshes = harness
|
||||||
|
with pytest.raises(ValueError, match="500"):
|
||||||
|
page._complete_after_revalidation(51, "字" * 501)
|
||||||
|
page._can_note = False
|
||||||
|
with pytest.raises(ValueError, match="备注权限"):
|
||||||
|
page._complete_after_revalidation(51, "测试备注")
|
||||||
|
page._can_complete = False
|
||||||
|
page._complete_appointment()
|
||||||
|
assert page._completion_dialog is None
|
||||||
|
with pytest.raises(ValueError, match="完成接诊权限"):
|
||||||
|
page._complete_after_revalidation(51)
|
||||||
|
assert repository.calls == []
|
||||||
|
assert jobs == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("switch_before_confirm", [True, False])
|
||||||
|
def test_completion_does_not_mutate_or_clear_a_new_selection(
|
||||||
|
harness: Any, switch_before_confirm: bool
|
||||||
|
) -> None:
|
||||||
|
page, repository, jobs, _toasts, _refreshes = harness
|
||||||
|
page._complete_appointment()
|
||||||
|
dialog = page._completion_dialog
|
||||||
|
dialog.note_edit.setPlainText("原患者的备注")
|
||||||
|
if not switch_before_confirm:
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
page._selected_appointment_id = 52
|
||||||
|
page._selected_record = {"id": 52, "status": 1}
|
||||||
|
page._selected_detail = {"appointment": page._selected_record, "diagnosis": {"id": 252}}
|
||||||
|
page._detail_generation += 1
|
||||||
|
page._update_action_state(page._selected_record, {"id": 252})
|
||||||
|
if switch_before_confirm:
|
||||||
|
dialog.confirm_button.click()
|
||||||
|
assert jobs == []
|
||||||
|
assert repository.calls == []
|
||||||
|
assert "已切换" in dialog.banner.label.text()
|
||||||
|
else:
|
||||||
|
finish_job(jobs.pop())
|
||||||
|
assert repository.calls[-1] == ("note", 251, "原患者的备注")
|
||||||
|
assert page.complete_button.isEnabled()
|
||||||
|
assert page._selected_appointment_id == 52
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from PySide6.QtCore import QPoint, Qt
|
||||||
|
from PySide6.QtTest import QTest
|
||||||
|
from PySide6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QWidget
|
||||||
|
|
||||||
|
from doctor_workstation.ui.pages.reception import RECEPTION_QSS, _ReceptionCompleteButton
|
||||||
|
from doctor_workstation.ui.theme import apply_theme
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def controls():
|
||||||
|
app = QApplication.instance() or QApplication([])
|
||||||
|
old_stylesheet, old_font, old_palette = app.styleSheet(), app.font(), app.palette()
|
||||||
|
old_style = app.style().objectName()
|
||||||
|
apply_theme(app)
|
||||||
|
host = QWidget()
|
||||||
|
host.setObjectName("ReceptionPage")
|
||||||
|
host.setStyleSheet(RECEPTION_QSS)
|
||||||
|
layout = QHBoxLayout(host)
|
||||||
|
layout.setContentsMargins(20, 20, 20, 20)
|
||||||
|
layout.setSpacing(12)
|
||||||
|
button = _ReceptionCompleteButton(host)
|
||||||
|
neighbor = QPushButton("通知医助", host)
|
||||||
|
neighbor.setObjectName("ReceptionNotifyButton")
|
||||||
|
layout.addWidget(button)
|
||||||
|
layout.addWidget(neighbor)
|
||||||
|
host.show()
|
||||||
|
host.activateWindow()
|
||||||
|
button.clearFocus()
|
||||||
|
neighbor.clearFocus()
|
||||||
|
QTest.mouseMove(host, QPoint(1, 1))
|
||||||
|
app.processEvents()
|
||||||
|
yield app, host, button, neighbor
|
||||||
|
host.close()
|
||||||
|
host.deleteLater()
|
||||||
|
app.processEvents()
|
||||||
|
app.setStyle(old_style)
|
||||||
|
app.setFont(old_font)
|
||||||
|
app.setPalette(old_palette)
|
||||||
|
app.setStyleSheet(old_stylesheet)
|
||||||
|
|
||||||
|
|
||||||
|
def surface_color(button: QPushButton, *, border: bool = False) -> str:
|
||||||
|
image = button.grab().toImage()
|
||||||
|
scale = image.devicePixelRatio()
|
||||||
|
return image.pixelColor(
|
||||||
|
round((0 if border else 7) * scale), round(button.height() / 2 * scale)
|
||||||
|
).name()
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_hover_press_and_leave_have_feedback_without_layout_shift(controls):
|
||||||
|
app, host, button, neighbor = controls
|
||||||
|
geometry, neighbor_geometry = button.geometry(), neighbor.geometry()
|
||||||
|
clicked: list[bool] = []
|
||||||
|
button.clicked.connect(lambda: clicked.append(True))
|
||||||
|
assert surface_color(button) == "#fff7f8"
|
||||||
|
assert button.cursor().shape() == Qt.CursorShape.PointingHandCursor
|
||||||
|
|
||||||
|
QTest.mouseMove(button, button.rect().center())
|
||||||
|
app.processEvents()
|
||||||
|
assert button.underMouse()
|
||||||
|
assert surface_color(button) == "#fff0f2"
|
||||||
|
assert button.geometry() == geometry
|
||||||
|
assert neighbor.geometry() == neighbor_geometry
|
||||||
|
|
||||||
|
QTest.mousePress(button, Qt.MouseButton.LeftButton, pos=button.rect().center())
|
||||||
|
app.processEvents()
|
||||||
|
assert surface_color(button) == "#ffe4e8"
|
||||||
|
assert button.geometry() == geometry
|
||||||
|
assert neighbor.geometry() == neighbor_geometry
|
||||||
|
# Dragging outside and releasing must not activate the completion action.
|
||||||
|
QTest.mouseMove(button, QPoint(-5, -5))
|
||||||
|
QTest.mouseRelease(button, Qt.MouseButton.LeftButton, pos=QPoint(-5, -5))
|
||||||
|
QTest.mouseMove(host, QPoint(1, 1))
|
||||||
|
button.clearFocus()
|
||||||
|
app.processEvents()
|
||||||
|
assert clicked == []
|
||||||
|
assert surface_color(button) == "#fff7f8"
|
||||||
|
assert button.geometry() == geometry
|
||||||
|
assert neighbor.geometry() == neighbor_geometry
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_disabled_hover_does_not_look_or_act_enabled(controls):
|
||||||
|
app, _host, button, _neighbor = controls
|
||||||
|
clicked: list[bool] = []
|
||||||
|
button.clicked.connect(lambda: clicked.append(True))
|
||||||
|
button.setEnabled(False)
|
||||||
|
QTest.mouseMove(button, button.rect().center())
|
||||||
|
app.processEvents()
|
||||||
|
assert surface_color(button) == "#f7f8fb"
|
||||||
|
assert button.cursor().shape() == Qt.CursorShape.ArrowCursor
|
||||||
|
QTest.mouseClick(button, Qt.MouseButton.LeftButton)
|
||||||
|
assert clicked == []
|
||||||
|
button.setEnabled(True)
|
||||||
|
app.processEvents()
|
||||||
|
assert button.cursor().shape() == Qt.CursorShape.PointingHandCursor
|
||||||
|
assert surface_color(button) != "#f7f8fb"
|
||||||
|
|
||||||
|
|
||||||
|
def test_completion_keyboard_focus_is_visible_without_resizing(controls):
|
||||||
|
app, _host, button, neighbor = controls
|
||||||
|
geometry, neighbor_geometry = button.geometry(), neighbor.geometry()
|
||||||
|
neighbor.setFocus(Qt.FocusReason.TabFocusReason)
|
||||||
|
app.processEvents()
|
||||||
|
border_before = surface_color(button, border=True)
|
||||||
|
button.setFocus(Qt.FocusReason.TabFocusReason)
|
||||||
|
app.processEvents()
|
||||||
|
assert button.hasFocus()
|
||||||
|
assert surface_color(button, border=True) == "#cf4656"
|
||||||
|
assert surface_color(button, border=True) != border_before
|
||||||
|
assert button.geometry() == geometry
|
||||||
|
assert neighbor.geometry() == neighbor_geometry
|
||||||
|
QTest.mouseMove(button, button.rect().center())
|
||||||
|
app.processEvents()
|
||||||
|
assert surface_color(button) == "#fff0f2"
|
||||||
|
assert surface_color(button, border=True) == "#cf4656"
|
||||||
@@ -2579,7 +2579,7 @@ def test_completion_revalidates_server_status_before_write(
|
|||||||
assert completed == []
|
assert completed == []
|
||||||
|
|
||||||
repository.status = 4
|
repository.status = 4
|
||||||
assert page._complete_after_revalidation(51) == {"ok": True}
|
assert page._complete_after_revalidation(51) == ""
|
||||||
assert completed == [51]
|
assert completed == [51]
|
||||||
page.close()
|
page.close()
|
||||||
application.processEvents()
|
application.processEvents()
|
||||||
|
|||||||
@@ -0,0 +1,413 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from copy import deepcopy
|
||||||
|
from threading import Event
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from PySide6.QtCore import QCoreApplication, QEvent, Qt, QTimer
|
||||||
|
from PySide6.QtTest import QTest
|
||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
from doctor_workstation.core import PermissionSet
|
||||||
|
from doctor_workstation.ui.pages import reception as reception_module
|
||||||
|
from doctor_workstation.ui.pages.reception import ReceptionPage
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def application() -> QApplication:
|
||||||
|
return QApplication.instance() or QApplication([])
|
||||||
|
|
||||||
|
|
||||||
|
class RefreshRepository:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.calls: list[tuple[str, Any]] = []
|
||||||
|
self.detail = {
|
||||||
|
"appointment": {"id": 51, "patient_name": "刷新测试患者", "status": 1},
|
||||||
|
"diagnosis": {"id": 251, "patient_id": 151, "symptoms": "原病历"},
|
||||||
|
"patient": {"id": 151},
|
||||||
|
}
|
||||||
|
self.rows = [deepcopy(self.detail["appointment"])]
|
||||||
|
self.reports: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
def list_appointments(self, **query: Any) -> dict[str, Any]:
|
||||||
|
self.calls.append(("queue", query))
|
||||||
|
return {"lists": deepcopy(self.rows), "count": len(self.rows)}
|
||||||
|
|
||||||
|
def get_reception(self, appointment_id: int) -> dict[str, Any]:
|
||||||
|
self.calls.append(("detail", appointment_id))
|
||||||
|
return deepcopy(self.detail)
|
||||||
|
|
||||||
|
def list_patient_ai_reports(self, patient_id: int) -> dict[str, Any]:
|
||||||
|
self.calls.append(("reports", patient_id))
|
||||||
|
return {"patient_id": patient_id, "reports": deepcopy(self.reports)}
|
||||||
|
|
||||||
|
def generate_patient_ai_report(self, patient_id: int, **_options: Any) -> None:
|
||||||
|
self.calls.append(("POST", patient_id))
|
||||||
|
raise AssertionError("刷新不得生成 AI 报告")
|
||||||
|
|
||||||
|
def get_diagnosis_ai_analysis(self, diagnosis_id: int, **_options: Any) -> None:
|
||||||
|
self.calls.append(("legacy_POST", diagnosis_id))
|
||||||
|
raise AssertionError("刷新不得调用名称为 get 的旧版生成接口")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def harness(application: QApplication, monkeypatch: pytest.MonkeyPatch):
|
||||||
|
jobs: list[dict[str, Any]] = []
|
||||||
|
toasts: list[str] = []
|
||||||
|
|
||||||
|
def queue(function: Any, **options: Any) -> object:
|
||||||
|
jobs.append({"function": function, **options})
|
||||||
|
return object()
|
||||||
|
|
||||||
|
monkeypatch.setattr(reception_module, "run_async", queue)
|
||||||
|
monkeypatch.setattr(reception_module, "_AI_AUTOMATIC_GENERATION_SETTLE_SECONDS", 0)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
reception_module, "show_toast", lambda _parent, text, *_args: toasts.append(text)
|
||||||
|
)
|
||||||
|
repository = RefreshRepository()
|
||||||
|
page = ReceptionPage(
|
||||||
|
repository,
|
||||||
|
PermissionSet(
|
||||||
|
[
|
||||||
|
"doctor.appointment/addDoctorNote",
|
||||||
|
"doctor.appointment/complete",
|
||||||
|
"tcm.diagnosis/patientAiReports",
|
||||||
|
"tcm.diagnosis/generatePatientAiReport",
|
||||||
|
"tcm.diagnosis/aiAnalysis",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
page._selected_appointment_id = 51
|
||||||
|
page._selected_record = deepcopy(repository.detail["appointment"])
|
||||||
|
page._selected_detail = deepcopy(repository.detail)
|
||||||
|
page._update_action_state(repository.detail["appointment"], repository.detail["diagnosis"])
|
||||||
|
yield page, repository, jobs, toasts
|
||||||
|
page.close()
|
||||||
|
page.deleteLater()
|
||||||
|
QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete)
|
||||||
|
|
||||||
|
|
||||||
|
def finish(job: dict[str, Any]) -> None:
|
||||||
|
try:
|
||||||
|
result = job["function"]()
|
||||||
|
except Exception as error:
|
||||||
|
job["on_error"](error)
|
||||||
|
else:
|
||||||
|
job["on_success"](result)
|
||||||
|
finally:
|
||||||
|
job["on_finished"]()
|
||||||
|
|
||||||
|
|
||||||
|
def expire_cooldown(page: ReceptionPage) -> None:
|
||||||
|
page._refresh_cooldown.stop()
|
||||||
|
page._refresh_cooldown.timeout.emit()
|
||||||
|
|
||||||
|
|
||||||
|
def snapshot(version: int) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"id": version,
|
||||||
|
"patient_id": 151,
|
||||||
|
"model_key": "qwen",
|
||||||
|
"version": version,
|
||||||
|
"generated_at": f"2026-08-31 10:{version:02}:00",
|
||||||
|
"report": {"diagnosis": f"测试报告第 {version} 版", "treatment_advice": "测试建议"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_manual_refresh_supersedes_hung_queue_and_detail_independently(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page.refresh(workspace_refresh=True)
|
||||||
|
old_queue = jobs.pop()
|
||||||
|
page._load_detail(page._selected_record, clear=False)
|
||||||
|
old_detail = jobs.pop()
|
||||||
|
old_generation = page._detail_generation
|
||||||
|
|
||||||
|
page.refresh_button.click()
|
||||||
|
|
||||||
|
assert len(jobs) == 2
|
||||||
|
assert page._detail_generation > old_generation
|
||||||
|
assert page._queue_loading and page._detail_loading
|
||||||
|
# A slow queue cannot hold the new detail back.
|
||||||
|
finish(jobs[0])
|
||||||
|
assert repository.calls == [("detail", 51)]
|
||||||
|
assert not page._detail_loading
|
||||||
|
assert page._queue_loading
|
||||||
|
assert len(jobs) == 3 # exactly one fresh saved-report read
|
||||||
|
finish(jobs[1])
|
||||||
|
assert len(jobs) == 3 # queue must not duplicate detail work
|
||||||
|
finish(jobs[2])
|
||||||
|
old_queue["on_success"]({"lists": [{"id": 999, "patient_name": "迟到队列"}]})
|
||||||
|
old_queue["on_finished"]()
|
||||||
|
old_detail["on_success"]({"detail": {"appointment": {"id": 51, "patient_name": "旧详情"}}})
|
||||||
|
old_detail["on_finished"]()
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert page.patient_name_label.text() == "刷新测试患者"
|
||||||
|
assert not page._queue_loading and not page._detail_loading
|
||||||
|
assert [call[0] for call in repository.calls] == ["detail", "queue", "reports"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_preserves_query_loaded_pages_selection_and_drafts(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page._queue_date = "2026-08-03"
|
||||||
|
page._queue_filter_status = None
|
||||||
|
page.search_edit.blockSignals(True)
|
||||||
|
page.search_edit.setText(" 测试 ")
|
||||||
|
page.search_edit.blockSignals(False)
|
||||||
|
page._queue_page = 3
|
||||||
|
page._queue_records = [dict(id=index) for index in range(1, 46)]
|
||||||
|
page.note_edit.setPlainText("尚未保存的备注")
|
||||||
|
page._pending_tongue_images.append("draft-image.png")
|
||||||
|
page._pending_report_files.append("draft-report.pdf")
|
||||||
|
page.detail_tabs.setCurrentIndex(4)
|
||||||
|
# The current patient is no longer in this queue: don't silently select another.
|
||||||
|
repository.rows = [{"id": 52, "patient_name": "其他测试患者", "status": 1}]
|
||||||
|
page._refresh_workspace()
|
||||||
|
finish(jobs[1])
|
||||||
|
query = repository.calls[-1][1]
|
||||||
|
assert query == {
|
||||||
|
"status": None,
|
||||||
|
"start_date": "2026-08-03",
|
||||||
|
"end_date": "2026-08-03",
|
||||||
|
"patient_name": "测试",
|
||||||
|
"page_no": 1,
|
||||||
|
"page_size": 45,
|
||||||
|
"include_status_counts": 1,
|
||||||
|
}
|
||||||
|
finish(jobs[0])
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert page.queue_list.currentRow() == -1
|
||||||
|
assert page.note_edit.toPlainText() == "尚未保存的备注"
|
||||||
|
assert page._pending_tongue_images == ["draft-image.png"]
|
||||||
|
assert page._pending_report_files == ["draft-report.pdf"]
|
||||||
|
assert page.detail_tabs.currentIndex() == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_can_retry_while_old_requests_never_finish(harness) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
page._refresh_workspace()
|
||||||
|
page._refresh_workspace()
|
||||||
|
assert len(jobs) == 2
|
||||||
|
assert not page.refresh_button.isEnabled()
|
||||||
|
expire_cooldown(page)
|
||||||
|
page.refresh_button.click()
|
||||||
|
assert len(jobs) == 4
|
||||||
|
# Superseded queued work never goes to the server.
|
||||||
|
assert jobs[0]["function"]() == {"cancelled": True}
|
||||||
|
assert jobs[1]["function"]() is reception_module._ASYNC_REQUEST_CANCELLED
|
||||||
|
jobs[0]["on_finished"]()
|
||||||
|
jobs[1]["on_finished"]()
|
||||||
|
assert page._queue_loading and page._detail_loading
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("empty", [True, False])
|
||||||
|
def test_automatic_polls_after_refresh_keep_missing_patient_and_draft(harness, empty) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page.note_edit.setPlainText("不能因轮询丢失的备注")
|
||||||
|
page._pending_tongue_images.append("draft-image.png")
|
||||||
|
repository.rows = [] if empty else [{"id": 52, "patient_name": "其他患者", "status": 1}]
|
||||||
|
page._refresh_workspace()
|
||||||
|
finish(jobs[0])
|
||||||
|
finish(jobs[1])
|
||||||
|
finish(jobs[2])
|
||||||
|
for _ in range(3):
|
||||||
|
before = len(jobs)
|
||||||
|
page._poll_queue()
|
||||||
|
assert len(jobs) == before + 1
|
||||||
|
finish(jobs[-1])
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert page.note_edit.toPlainText() == "不能因轮询丢失的备注"
|
||||||
|
assert page._pending_tongue_images == ["draft-image.png"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_destroyed_page_ignores_every_late_refresh_callback(harness) -> None:
|
||||||
|
_page, repository, jobs, _toasts = harness
|
||||||
|
closed_page = ReceptionPage(repository, PermissionSet([]))
|
||||||
|
closed_page._refresh_workspace()
|
||||||
|
job = jobs[-1]
|
||||||
|
closed_page.deleteLater()
|
||||||
|
QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete)
|
||||||
|
job["on_success"]({"lists": []})
|
||||||
|
job["on_error"](RuntimeError("迟到异常"))
|
||||||
|
job["on_finished"]()
|
||||||
|
assert job["function"]() is reception_module._ASYNC_REQUEST_CANCELLED
|
||||||
|
assert not repository.calls
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("busy_flag", ["_note_busy", "_completion_pending"])
|
||||||
|
def test_refresh_does_not_disturb_business_submission(harness, busy_flag: str) -> None:
|
||||||
|
page, _repository, jobs, toasts = harness
|
||||||
|
setattr(page, busy_flag, True)
|
||||||
|
generation = page._detail_generation
|
||||||
|
page._refresh_workspace()
|
||||||
|
assert not jobs
|
||||||
|
assert page._detail_generation == generation
|
||||||
|
assert getattr(page, busy_flag)
|
||||||
|
assert "正在提交" in toasts[-1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_invalidates_in_flight_ai_read_and_rejects_late_result(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page._load_patient_ai_reports(151, appointment_id=51, diagnosis_id=251, force=True)
|
||||||
|
old_read = jobs.pop()
|
||||||
|
old_key = next(iter(page._patient_ai_list_requests))
|
||||||
|
page._patient_ai_list_started.add(old_key)
|
||||||
|
cancel = page._patient_ai_list_cancel_events[old_key]
|
||||||
|
repository.reports = [snapshot(2)]
|
||||||
|
page._refresh_workspace()
|
||||||
|
assert cancel.is_set()
|
||||||
|
assert old_key not in page._patient_ai_list_requests
|
||||||
|
finish(jobs[0])
|
||||||
|
finish(jobs[2])
|
||||||
|
assert page._ai_analysis_payloads["qwen"]["version"] == 2
|
||||||
|
old_read["on_success"]({"patient_id": 151, "reports": [snapshot(1)]})
|
||||||
|
old_read["on_finished"]()
|
||||||
|
assert page._ai_analysis_payloads["qwen"]["version"] == 2
|
||||||
|
assert not page._ai_analysis_loading
|
||||||
|
|
||||||
|
|
||||||
|
def test_manual_ai_read_does_not_need_automatic_slots_or_generate_missing_reports(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
slots = reception_module._AI_AUTOMATIC_REQUEST_SLOTS
|
||||||
|
assert slots.acquire(blocking=False)
|
||||||
|
assert slots.acquire(blocking=False)
|
||||||
|
try:
|
||||||
|
page._refresh_workspace()
|
||||||
|
finish(jobs[0])
|
||||||
|
finish(jobs[2])
|
||||||
|
assert ("reports", 151) in repository.calls
|
||||||
|
assert page._ai_analysis_state == "missing"
|
||||||
|
assert not page._ai_analysis_loading
|
||||||
|
assert not slots.acquire(blocking=False) # GUI must not release others' slots
|
||||||
|
finally:
|
||||||
|
slots.release()
|
||||||
|
slots.release()
|
||||||
|
assert not any("POST" in call[0] for call in repository.calls)
|
||||||
|
assert page.ai_analysis_regenerate_button.isEnabled()
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_keeps_started_generation_single_flight(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
key = (1, 51, 151, "qwen")
|
||||||
|
page._patient_ai_generation_requests.add(key)
|
||||||
|
page._patient_ai_generation_started.add(key)
|
||||||
|
cancel = Event()
|
||||||
|
page._patient_ai_generation_cancel_events[key] = cancel
|
||||||
|
page._refresh_workspace()
|
||||||
|
finish(jobs[0])
|
||||||
|
assert len(jobs) == 2
|
||||||
|
assert key in page._patient_ai_generation_requests
|
||||||
|
assert key in page._patient_ai_generation_started
|
||||||
|
assert not cancel.is_set()
|
||||||
|
assert "不会重复生成" in page._ai_analysis_operation_error
|
||||||
|
assert not any(call[0] in {"POST", "reports"} for call in repository.calls)
|
||||||
|
|
||||||
|
|
||||||
|
def test_legacy_ai_refresh_never_invokes_post_endpoint(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page._can_patient_ai_read = False
|
||||||
|
page._refresh_workspace()
|
||||||
|
finish(jobs[0])
|
||||||
|
assert len(jobs) == 2
|
||||||
|
assert repository.calls == [("detail", 51)]
|
||||||
|
assert "无法只读刷新" in page.ai_analysis_state_label.text()
|
||||||
|
|
||||||
|
|
||||||
|
def test_first_selection_from_manual_refresh_is_read_only(harness) -> None:
|
||||||
|
page, repository, jobs, _toasts = harness
|
||||||
|
page._clear_selection()
|
||||||
|
page._refresh_workspace()
|
||||||
|
assert len(jobs) == 1
|
||||||
|
finish(jobs[0])
|
||||||
|
finish(jobs[1])
|
||||||
|
finish(jobs[2])
|
||||||
|
assert [call[0] for call in repository.calls] == ["queue", "detail", "reports"]
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert page._ai_analysis_state == "missing"
|
||||||
|
|
||||||
|
|
||||||
|
def test_late_refresh_cannot_switch_back_to_previous_patient(harness) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
page._refresh_workspace()
|
||||||
|
second = {"id": 52, "patient_name": "新选择的测试患者", "status": 1}
|
||||||
|
page._select_record(second)
|
||||||
|
assert page._selected_appointment_id == 52
|
||||||
|
jobs[0]["on_success"]({"detail": {"appointment": {"id": 51, "patient_name": "旧患者"}}})
|
||||||
|
jobs[1]["on_success"]({"lists": [{"id": 51, "patient_name": "旧患者"}]})
|
||||||
|
assert page._selected_appointment_id == 52
|
||||||
|
assert page.patient_name_label.text() == "新选择的测试患者"
|
||||||
|
assert page._detail_loading # stale finished must not clear patient B's loading
|
||||||
|
|
||||||
|
|
||||||
|
def test_ai_read_timeout_is_retryable_and_cannot_install_late_snapshot(
|
||||||
|
harness, monkeypatch
|
||||||
|
) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
page._refresh_workspace()
|
||||||
|
monkeypatch.setattr(reception_module, "_REFRESH_TIMEOUT_MS", 10)
|
||||||
|
finish(jobs[0])
|
||||||
|
finish(jobs[1])
|
||||||
|
assert len(jobs) == 3
|
||||||
|
QTest.qWait(60)
|
||||||
|
assert not page._ai_analysis_loading
|
||||||
|
assert page._ai_analysis_state == "error"
|
||||||
|
assert page.ai_analysis_retry_button.isEnabled()
|
||||||
|
jobs[2]["on_success"]({"patient_id": 151, "reports": [snapshot(1)]})
|
||||||
|
assert not page._ai_analysis_payloads
|
||||||
|
assert not page._patient_ai_list_requests
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_timeout_stops_loading_and_ignores_late_success(harness, monkeypatch) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
monkeypatch.setattr(reception_module, "_REFRESH_TIMEOUT_MS", 10)
|
||||||
|
monkeypatch.setattr(reception_module, "_REFRESH_COOLDOWN_MS", 10)
|
||||||
|
page._refresh_workspace()
|
||||||
|
QTest.qWait(60)
|
||||||
|
assert not page._queue_loading and not page._detail_loading
|
||||||
|
assert page.refresh_button.isEnabled()
|
||||||
|
assert "刷新超时" in page.queue_banner.label.text()
|
||||||
|
assert "刷新超时" in page.detail_banner.label.text()
|
||||||
|
jobs[0]["on_success"]({"detail": {"appointment": {"id": 51, "patient_name": "迟到详情"}}})
|
||||||
|
jobs[1]["on_success"]({"lists": []})
|
||||||
|
assert page._selected_appointment_id == 51
|
||||||
|
assert page.patient_name_label.text() != "迟到详情"
|
||||||
|
assert "刷新超时" in page.detail_banner.label.text()
|
||||||
|
assert jobs[0]["function"]() is reception_module._ASYNC_REQUEST_CANCELLED
|
||||||
|
page._refresh_workspace()
|
||||||
|
assert len(jobs) == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_read_error_and_missing_callback_are_terminal(harness) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
page._refresh_workspace()
|
||||||
|
jobs[0]["on_error"](RuntimeError("测试断网"))
|
||||||
|
jobs[0]["on_finished"]()
|
||||||
|
jobs[1]["on_finished"]()
|
||||||
|
assert not page._queue_loading and not page._detail_loading
|
||||||
|
assert "测试断网" in page.detail_banner.label.text()
|
||||||
|
assert "未返回有效结果" in page.queue_banner.label.text()
|
||||||
|
|
||||||
|
|
||||||
|
def test_refresh_button_visible_and_f5_uses_same_debounce(harness, application) -> None:
|
||||||
|
page, _repository, jobs, _toasts = harness
|
||||||
|
page._queue_records = [page._selected_record] # prevent showEvent's initial fetch
|
||||||
|
page.resize(1440, 1000)
|
||||||
|
page.show()
|
||||||
|
page.activateWindow()
|
||||||
|
page.poll_timer.stop()
|
||||||
|
application.processEvents()
|
||||||
|
assert page.refresh_button.isVisible()
|
||||||
|
assert page.refresh_button.text() == "刷新"
|
||||||
|
assert page.refresh_button.width() >= 50
|
||||||
|
assert page.refresh_button.geometry().right() < page.queue_date_button.geometry().left()
|
||||||
|
page.note_edit.setFocus()
|
||||||
|
application.processEvents()
|
||||||
|
QTest.keyClick(page.note_edit, Qt.Key.Key_F5)
|
||||||
|
assert len(jobs) == 2
|
||||||
|
QTest.keyClick(page.note_edit, Qt.Key.Key_F5)
|
||||||
|
assert len(jobs) == 2
|
||||||
|
assert page._refresh_cooldown.isActive()
|
||||||
|
assert page._refresh_cooldown in page.findChildren(QTimer)
|
||||||
@@ -5,16 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace app\adminapi\controller\firstvisit;
|
namespace app\adminapi\controller\firstvisit;
|
||||||
|
|
||||||
use app\adminapi\controller\BaseAdminController;
|
use app\adminapi\controller\BaseAdminController;
|
||||||
use app\adminapi\logic\auth\AuthLogic;
|
|
||||||
use app\adminapi\logic\firstvisit\WecomAcquisitionCustomerLogic;
|
use app\adminapi\logic\firstvisit\WecomAcquisitionCustomerLogic;
|
||||||
use app\adminapi\logic\firstvisit\WecomPromotionLogic;
|
use app\adminapi\logic\firstvisit\WecomPromotionLogic;
|
||||||
use app\common\service\qywx\QywxPromotionContactApiService;
|
use app\common\service\qywx\QywxPromotionContactApiService;
|
||||||
use app\common\service\qywx\QywxPromotionMediaService;
|
use app\common\service\qywx\QywxPromotionMediaService;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
|
|
||||||
class WecomPromotionController extends BaseAdminController
|
class WecomPromotionController extends BaseAdminController
|
||||||
{
|
{
|
||||||
private const PAGE_PERMISSION = 'firstvisit.wecomPromotion/overview';
|
|
||||||
|
|
||||||
public function tagOptions()
|
public function tagOptions()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasPagePermission()) {
|
||||||
@@ -25,7 +23,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function createTag()
|
public function createTag()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
if (!$this->request->isPost()) {
|
if (!$this->request->isPost()) {
|
||||||
@@ -68,9 +66,13 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasPagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
|
$params = $this->request->post();
|
||||||
|
if ((int) ($params['id'] ?? 0) <= 0 && !$this->hasBasePagePermission()) {
|
||||||
|
return $this->fail('共享操作人只能编辑已授权方案,不能新建分流方案');
|
||||||
|
}
|
||||||
|
|
||||||
return $this->run(fn () => $this->success('分流方案已保存', WecomPromotionLogic::savePool(
|
return $this->run(fn () => $this->success('分流方案已保存', WecomPromotionLogic::savePool(
|
||||||
$this->request->post(),
|
$params,
|
||||||
$this->adminId,
|
$this->adminId,
|
||||||
$this->adminInfo
|
$this->adminInfo
|
||||||
)));
|
)));
|
||||||
@@ -91,7 +93,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function batchSetOperators()
|
public function batchSetOperators()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +106,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function deletePool()
|
public function deletePool()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
$id = (int) $this->request->post('id', 0);
|
$id = (int) $this->request->post('id', 0);
|
||||||
@@ -158,7 +160,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function checkApiPermission()
|
public function checkApiPermission()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +169,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function syncRemoteLinks()
|
public function syncRemoteLinks()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
$poolId = (int) $this->request->post('pool_id', 0);
|
$poolId = (int) $this->request->post('pool_id', 0);
|
||||||
@@ -195,7 +197,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function deleteRemoteLink()
|
public function deleteRemoteLink()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
$id = (int) $this->request->post('id', 0);
|
$id = (int) $this->request->post('id', 0);
|
||||||
@@ -250,7 +252,7 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
public function deleteLink()
|
public function deleteLink()
|
||||||
{
|
{
|
||||||
if (!$this->hasPagePermission()) {
|
if (!$this->hasBasePagePermission()) {
|
||||||
return $this->fail('权限不足');
|
return $this->fail('权限不足');
|
||||||
}
|
}
|
||||||
$id = (int) $this->request->post('id', 0);
|
$id = (int) $this->request->post('id', 0);
|
||||||
@@ -273,10 +275,11 @@ class WecomPromotionController extends BaseAdminController
|
|||||||
|
|
||||||
private function hasPagePermission(): bool
|
private function hasPagePermission(): bool
|
||||||
{
|
{
|
||||||
if ((int) ($this->adminInfo['root'] ?? 0) === 1) {
|
return QywxPromotionOperatorAccess::hasPagePermission($this->adminId, $this->adminInfo);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return in_array(self::PAGE_PERMISSION, AuthLogic::getAuthByAdminId($this->adminId), true);
|
private function hasBasePagePermission(): bool
|
||||||
|
{
|
||||||
|
return QywxPromotionOperatorAccess::hasBasePagePermission($this->adminId, $this->adminInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace app\adminapi\http\middleware;
|
|||||||
|
|
||||||
use app\adminapi\logic\LoginLogic;
|
use app\adminapi\logic\LoginLogic;
|
||||||
use app\common\service\pharmacy\PharmacyUploadPermissionAlias;
|
use app\common\service\pharmacy\PharmacyUploadPermissionAlias;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
use app\common\{
|
use app\common\{
|
||||||
cache\AdminAuthCache,
|
cache\AdminAuthCache,
|
||||||
service\JsonService
|
service\JsonService
|
||||||
@@ -71,6 +72,19 @@ class AuthMiddleware
|
|||||||
|
|
||||||
// 当前访问路径
|
// 当前访问路径
|
||||||
$accessUri = strtolower($request->controller() . '/' . $request->action());
|
$accessUri = strtolower($request->controller() . '/' . $request->action());
|
||||||
|
|
||||||
|
// 获客助手的子接口多数不是独立菜单权限。整组动作统一绑定页面权限,
|
||||||
|
// 共享操作人的动态页面权限也必须先经过这一层,再由业务层校验具体方案。
|
||||||
|
if (str_starts_with($accessUri, 'firstvisit.wecompromotion/')) {
|
||||||
|
$adminUris = $this->formatUrl($adminAuthCache->getAdminUri() ?? []);
|
||||||
|
if ($this->isKnownWecomPromotionAction($accessUri)
|
||||||
|
&& in_array(strtolower(QywxPromotionOperatorAccess::PAGE_PERMISSION), $adminUris, true)) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonService::fail('权限不足,无法访问或操作');
|
||||||
|
}
|
||||||
|
|
||||||
// 全部路由
|
// 全部路由
|
||||||
$allUri = $this->formatUrl($adminAuthCache->getAllUri());
|
$allUri = $this->formatUrl($adminAuthCache->getAllUri());
|
||||||
|
|
||||||
@@ -205,6 +219,31 @@ class AuthMiddleware
|
|||||||
], true);
|
], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function isKnownWecomPromotionAction(string $accessUri): bool
|
||||||
|
{
|
||||||
|
return in_array($accessUri, [
|
||||||
|
'firstvisit.wecompromotion/tagoptions',
|
||||||
|
'firstvisit.wecompromotion/createtag',
|
||||||
|
'firstvisit.wecompromotion/uploadwelcomemedia',
|
||||||
|
'firstvisit.wecompromotion/overview',
|
||||||
|
'firstvisit.wecompromotion/savepool',
|
||||||
|
'firstvisit.wecompromotion/savewidget',
|
||||||
|
'firstvisit.wecompromotion/batchsetoperators',
|
||||||
|
'firstvisit.wecompromotion/deletepool',
|
||||||
|
'firstvisit.wecompromotion/savelink',
|
||||||
|
'firstvisit.wecompromotion/savemember',
|
||||||
|
'firstvisit.wecompromotion/togglemember',
|
||||||
|
'firstvisit.wecompromotion/checkapipermission',
|
||||||
|
'firstvisit.wecompromotion/syncremotelinks',
|
||||||
|
'firstvisit.wecompromotion/remotelinkdetail',
|
||||||
|
'firstvisit.wecompromotion/deleteremotelink',
|
||||||
|
'firstvisit.wecompromotion/synccustomers',
|
||||||
|
'firstvisit.wecompromotion/customerstatistics',
|
||||||
|
'firstvisit.wecompromotion/togglelink',
|
||||||
|
'firstvisit.wecompromotion/deletelink',
|
||||||
|
], true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处方库 lists:与开方、处方库维护菜单权限互通(避免开方页「从处方库导入」403)
|
* 处方库 lists:与开方、处方库维护菜单权限互通(避免开方页「从处方库导入」403)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use app\common\model\auth\Admin;
|
|||||||
use app\common\model\auth\AdminRole;
|
use app\common\model\auth\AdminRole;
|
||||||
use app\common\model\auth\SystemMenu;
|
use app\common\model\auth\SystemMenu;
|
||||||
use app\common\model\auth\SystemRoleMenu;
|
use app\common\model\auth\SystemRoleMenu;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,11 +75,9 @@ class AuthLogic
|
|||||||
->column('perms');
|
->column('perms');
|
||||||
|
|
||||||
$hasAllAuth = array_diff($allAuth, $roleAuth);
|
$hasAllAuth = array_diff($allAuth, $roleAuth);
|
||||||
if (empty($hasAllAuth)) {
|
$permissions = empty($hasAllAuth) ? ['*'] : $roleAuth;
|
||||||
return ['*'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $roleAuth;
|
return self::appendSharedPromotionPermission($permissions, (int) ($admin['id'] ?? 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,12 +93,28 @@ class AuthLogic
|
|||||||
$roleIds = AdminRole::where('admin_id', $adminId)->column('role_id');
|
$roleIds = AdminRole::where('admin_id', $adminId)->column('role_id');
|
||||||
$menuId = SystemRoleMenu::whereIn('role_id', $roleIds)->column('menu_id');
|
$menuId = SystemRoleMenu::whereIn('role_id', $roleIds)->column('menu_id');
|
||||||
|
|
||||||
return SystemMenu::distinct(true)
|
$permissions = SystemMenu::distinct(true)
|
||||||
->where([
|
->where([
|
||||||
['is_disable', '=', 0],
|
['is_disable', '=', 0],
|
||||||
['perms', '<>', ''],
|
['perms', '<>', ''],
|
||||||
['id', 'in', array_unique($menuId)],
|
['id', 'in', array_unique($menuId)],
|
||||||
])
|
])
|
||||||
->column('perms');
|
->column('perms');
|
||||||
|
|
||||||
|
return self::appendSharedPromotionPermission($permissions, $adminId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function appendSharedPromotionPermission(array $permissions, int $adminId): array
|
||||||
|
{
|
||||||
|
if (in_array('*', $permissions, true)
|
||||||
|
|| in_array(QywxPromotionOperatorAccess::PAGE_PERMISSION, $permissions, true)
|
||||||
|
|| !QywxPromotionOperatorAccess::hasSharedPagePermission($adminId)) {
|
||||||
|
return $permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
$permissions[] = QywxPromotionOperatorAccess::PAGE_PERMISSION;
|
||||||
|
|
||||||
|
return array_values(array_unique($permissions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ use app\common\logic\BaseLogic;
|
|||||||
use app\common\model\auth\Admin;
|
use app\common\model\auth\Admin;
|
||||||
use app\common\model\auth\SystemMenu;
|
use app\common\model\auth\SystemMenu;
|
||||||
use app\common\model\auth\SystemRoleMenu;
|
use app\common\model\auth\SystemRoleMenu;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,6 +52,12 @@ class MenuLogic extends BaseLogic
|
|||||||
|
|
||||||
if ($admin['root'] != 1) {
|
if ($admin['root'] != 1) {
|
||||||
$roleMenu = SystemRoleMenu::whereIn('role_id', $admin['role_id'])->column('menu_id');
|
$roleMenu = SystemRoleMenu::whereIn('role_id', $admin['role_id'])->column('menu_id');
|
||||||
|
if (QywxPromotionOperatorAccess::hasSharedPagePermission((int) $adminId)) {
|
||||||
|
$roleMenu = array_values(array_unique(array_merge(
|
||||||
|
array_map('intval', $roleMenu),
|
||||||
|
self::sharedPromotionMenuIds()
|
||||||
|
)));
|
||||||
|
}
|
||||||
$where[] = ['id', 'in', $roleMenu];
|
$where[] = ['id', 'in', $roleMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +69,45 @@ class MenuLogic extends BaseLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @return list<int> */
|
||||||
|
private static function sharedPromotionMenuIds(): array
|
||||||
|
{
|
||||||
|
$menus = SystemMenu::where('is_disable', 0)
|
||||||
|
->field('id,pid,perms')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
$byId = [];
|
||||||
|
$pageIds = [];
|
||||||
|
foreach ($menus as $menu) {
|
||||||
|
$id = (int) ($menu['id'] ?? 0);
|
||||||
|
if ($id <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$byId[$id] = $menu;
|
||||||
|
if ((string) ($menu['perms'] ?? '') === QywxPromotionOperatorAccess::PAGE_PERMISSION) {
|
||||||
|
$pageIds[] = $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($pageIds as $pageId) {
|
||||||
|
$chain = [];
|
||||||
|
$currentId = $pageId;
|
||||||
|
while ($currentId > 0) {
|
||||||
|
if (!isset($byId[$currentId])) {
|
||||||
|
$chain = [];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$chain[] = $currentId;
|
||||||
|
$currentId = (int) ($byId[$currentId]['pid'] ?? 0);
|
||||||
|
}
|
||||||
|
$result = array_merge($result, $chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_unique($result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notes 添加菜单
|
* @notes 添加菜单
|
||||||
* @param array $params
|
* @param array $params
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace app\adminapi\logic\firstvisit;
|
|||||||
|
|
||||||
use app\common\service\DataScope\DataScopeService;
|
use app\common\service\DataScope\DataScopeService;
|
||||||
use app\common\service\qywx\QywxCustomerAcquisitionCustomerService;
|
use app\common\service\qywx\QywxCustomerAcquisitionCustomerService;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ class WecomAcquisitionCustomerLogic
|
|||||||
self::applyScope(
|
self::applyScope(
|
||||||
$query,
|
$query,
|
||||||
'l',
|
'l',
|
||||||
DataScopeService::getVisibleAdminIds($adminId, $adminInfo),
|
QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo),
|
||||||
self::operatorPoolIds($adminId)
|
self::operatorPoolIds($adminId)
|
||||||
);
|
);
|
||||||
if ($localLinkId > 0) {
|
if ($localLinkId > 0) {
|
||||||
@@ -60,7 +61,8 @@ class WecomAcquisitionCustomerLogic
|
|||||||
{
|
{
|
||||||
$page = max(1, (int) ($params['page_no'] ?? $params['page'] ?? 1));
|
$page = max(1, (int) ($params['page_no'] ?? $params['page'] ?? 1));
|
||||||
$pageSize = min(100, max(1, (int) ($params['page_size'] ?? 20)));
|
$pageSize = min(100, max(1, (int) ($params['page_size'] ?? 20)));
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$hasBasePagePermission = QywxPromotionOperatorAccess::hasBasePagePermission($adminId, $adminInfo);
|
||||||
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
$operatorPoolIds = self::operatorPoolIds($adminId);
|
$operatorPoolIds = self::operatorPoolIds($adminId);
|
||||||
$base = self::customerQuery($params, $visibleIds, $operatorPoolIds);
|
$base = self::customerQuery($params, $visibleIds, $operatorPoolIds);
|
||||||
$total = (int) (clone $base)->count();
|
$total = (int) (clone $base)->count();
|
||||||
@@ -87,7 +89,9 @@ class WecomAcquisitionCustomerLogic
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'scope_label' => DataScopeService::scopeLabel(DataScopeService::getEffectiveScope($adminInfo)),
|
'scope_label' => $hasBasePagePermission
|
||||||
|
? DataScopeService::scopeLabel(DataScopeService::getEffectiveScope($adminInfo))
|
||||||
|
: '仅共享方案',
|
||||||
'generated_at' => date('Y-m-d H:i:s'),
|
'generated_at' => date('Y-m-d H:i:s'),
|
||||||
],
|
],
|
||||||
'summary' => [
|
'summary' => [
|
||||||
@@ -188,18 +192,7 @@ class WecomAcquisitionCustomerLogic
|
|||||||
/** @return list<int> */
|
/** @return list<int> */
|
||||||
private static function operatorPoolIds(int $adminId): array
|
private static function operatorPoolIds(int $adminId): array
|
||||||
{
|
{
|
||||||
if ($adminId <= 0) {
|
return QywxPromotionOperatorAccess::activePoolIds($adminId);
|
||||||
return [];
|
|
||||||
}
|
|
||||||
$ids = Db::name('qywx_promotion_pool_operator')
|
|
||||||
->where('admin_id', $adminId)
|
|
||||||
->whereNull('delete_time')
|
|
||||||
->column('pool_id');
|
|
||||||
|
|
||||||
return array_values(array_unique(array_filter(array_map(
|
|
||||||
static fn ($value): int => (int) $value,
|
|
||||||
$ids
|
|
||||||
), static fn (int $value): bool => $value > 0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function maskIdentifier(string $value): string
|
private static function maskIdentifier(string $value): string
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace app\adminapi\logic\firstvisit;
|
namespace app\adminapi\logic\firstvisit;
|
||||||
|
|
||||||
use app\adminapi\logic\dept\DeptLogic;
|
use app\adminapi\logic\dept\DeptLogic;
|
||||||
|
use app\common\cache\AdminAuthCache;
|
||||||
use app\common\service\DataScope\DataScopeService;
|
use app\common\service\DataScope\DataScopeService;
|
||||||
use app\common\service\qywx\QywxCustomerAcquisitionApiService;
|
use app\common\service\qywx\QywxCustomerAcquisitionApiService;
|
||||||
use app\common\service\qywx\QywxCustomerAcquisitionLinkService;
|
use app\common\service\qywx\QywxCustomerAcquisitionLinkService;
|
||||||
@@ -13,10 +14,12 @@ use app\common\service\qywx\QywxPromotionConfig;
|
|||||||
use app\common\service\qywx\QywxPromotionContactApiService;
|
use app\common\service\qywx\QywxPromotionContactApiService;
|
||||||
use app\common\service\qywx\QywxPromotionMediaService;
|
use app\common\service\qywx\QywxPromotionMediaService;
|
||||||
use app\common\service\qywx\QywxPromotionMemberSchedulerService;
|
use app\common\service\qywx\QywxPromotionMemberSchedulerService;
|
||||||
|
use app\common\service\qywx\QywxPromotionOperatorAccess;
|
||||||
use app\common\service\qywx\QywxPromotionRangeSyncService;
|
use app\common\service\qywx\QywxPromotionRangeSyncService;
|
||||||
use app\common\service\qywx\QywxPromotionWidgetService;
|
use app\common\service\qywx\QywxPromotionWidgetService;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
|
use think\facade\Log;
|
||||||
|
|
||||||
/** 一诊 / 企业微信获客助手管理逻辑。 */
|
/** 一诊 / 企业微信获客助手管理逻辑。 */
|
||||||
class WecomPromotionLogic
|
class WecomPromotionLogic
|
||||||
@@ -25,7 +28,8 @@ class WecomPromotionLogic
|
|||||||
{
|
{
|
||||||
self::assertMemberDispatchSchema();
|
self::assertMemberDispatchSchema();
|
||||||
self::assertPoolOperatorSchema();
|
self::assertPoolOperatorSchema();
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$hasBasePagePermission = QywxPromotionOperatorAccess::hasBasePagePermission($adminId, $adminInfo);
|
||||||
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
$operatorPoolIds = self::operatorPoolIds($adminId);
|
$operatorPoolIds = self::operatorPoolIds($adminId);
|
||||||
$poolsQuery = Db::name('qywx_promotion_pool')->alias('p')
|
$poolsQuery = Db::name('qywx_promotion_pool')->alias('p')
|
||||||
->leftJoin('admin u', 'u.id = p.owner_admin_id')
|
->leftJoin('admin u', 'u.id = p.owner_admin_id')
|
||||||
@@ -174,7 +178,8 @@ class WecomPromotionLogic
|
|||||||
));
|
));
|
||||||
$pool['is_shared_with_me'] = in_array($adminId, $pool['operator_admin_ids'], true);
|
$pool['is_shared_with_me'] = in_array($adminId, $pool['operator_admin_ids'], true);
|
||||||
$pool['can_operate'] = true;
|
$pool['can_operate'] = true;
|
||||||
$pool['can_manage_access'] = self::ownerInScope((int) ($pool['owner_admin_id'] ?? 0), $visibleIds);
|
$pool['can_manage_access'] = $hasBasePagePermission
|
||||||
|
&& self::ownerInScope((int) ($pool['owner_admin_id'] ?? 0), $visibleIds);
|
||||||
$pool['can_delete'] = $pool['can_manage_access'];
|
$pool['can_delete'] = $pool['can_manage_access'];
|
||||||
$pool['dispatch_sync'] = $sync;
|
$pool['dispatch_sync'] = $sync;
|
||||||
$pool['using_backup'] = $reception['using_backup'];
|
$pool['using_backup'] = $reception['using_backup'];
|
||||||
@@ -196,7 +201,9 @@ class WecomPromotionLogic
|
|||||||
return [
|
return [
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'admin_id' => $adminId,
|
'admin_id' => $adminId,
|
||||||
'scope_label' => DataScopeService::scopeLabel(DataScopeService::getEffectiveScope($adminInfo)),
|
'scope_label' => $hasBasePagePermission
|
||||||
|
? DataScopeService::scopeLabel(DataScopeService::getEffectiveScope($adminInfo))
|
||||||
|
: '仅共享方案',
|
||||||
'generated_at' => date('Y-m-d H:i:s'),
|
'generated_at' => date('Y-m-d H:i:s'),
|
||||||
],
|
],
|
||||||
'config' => $config,
|
'config' => $config,
|
||||||
@@ -210,7 +217,9 @@ class WecomPromotionLogic
|
|||||||
'links' => $links,
|
'links' => $links,
|
||||||
'member_options' => $memberOptions,
|
'member_options' => $memberOptions,
|
||||||
'operator_options' => $operatorOptions,
|
'operator_options' => $operatorOptions,
|
||||||
'department_options' => DeptLogic::getAllDataScoped($adminId, $adminInfo),
|
'department_options' => $hasBasePagePermission
|
||||||
|
? DeptLogic::getAllDataScoped($adminId, $adminInfo)
|
||||||
|
: [],
|
||||||
'automation_installed' => QywxPromotionConfig::installed(),
|
'automation_installed' => QywxPromotionConfig::installed(),
|
||||||
'customer_acquisition_link_example' => QywxCustomerAcquisitionLinkService::example(),
|
'customer_acquisition_link_example' => QywxCustomerAcquisitionLinkService::example(),
|
||||||
];
|
];
|
||||||
@@ -220,6 +229,9 @@ class WecomPromotionLogic
|
|||||||
{
|
{
|
||||||
self::assertMemberDispatchSchema();
|
self::assertMemberDispatchSchema();
|
||||||
$id = max(0, (int) ($params['id'] ?? 0));
|
$id = max(0, (int) ($params['id'] ?? 0));
|
||||||
|
if ($id <= 0 && !QywxPromotionOperatorAccess::hasBasePagePermission($adminId, $adminInfo)) {
|
||||||
|
throw new RuntimeException('共享操作人只能编辑已授权方案,不能新建分流方案');
|
||||||
|
}
|
||||||
$existingPool = $id > 0
|
$existingPool = $id > 0
|
||||||
? self::assertScopedRow('qywx_promotion_pool', $id, $adminId, $adminInfo)
|
? self::assertScopedRow('qywx_promotion_pool', $id, $adminId, $adminInfo)
|
||||||
: null;
|
: null;
|
||||||
@@ -459,7 +471,12 @@ class WecomPromotionLogic
|
|||||||
?QywxCustomerAcquisitionApiService $api = null
|
?QywxCustomerAcquisitionApiService $api = null
|
||||||
): void
|
): void
|
||||||
{
|
{
|
||||||
|
self::assertBasePagePermission($adminId, $adminInfo);
|
||||||
self::assertScopedRow('qywx_promotion_pool', $id, $adminId, $adminInfo, false);
|
self::assertScopedRow('qywx_promotion_pool', $id, $adminId, $adminInfo, false);
|
||||||
|
$operatorAdminIds = self::normalizePositiveIds(Db::name('qywx_promotion_pool_operator')
|
||||||
|
->where('pool_id', $id)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->column('admin_id'));
|
||||||
$links = Db::name('qywx_promotion_link')
|
$links = Db::name('qywx_promotion_link')
|
||||||
->where('pool_id', $id)
|
->where('pool_id', $id)
|
||||||
->order('id', 'asc')
|
->order('id', 'asc')
|
||||||
@@ -563,6 +580,7 @@ class WecomPromotionLogic
|
|||||||
'update_time' => $now,
|
'update_time' => $now,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
self::clearOperatorAuthCaches($operatorAdminIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -574,6 +592,7 @@ class WecomPromotionLogic
|
|||||||
public static function batchSetOperators(array $params, int $adminId, array $adminInfo): array
|
public static function batchSetOperators(array $params, int $adminId, array $adminInfo): array
|
||||||
{
|
{
|
||||||
self::assertPoolOperatorSchema();
|
self::assertPoolOperatorSchema();
|
||||||
|
self::assertBasePagePermission($adminId, $adminInfo);
|
||||||
$poolIds = self::normalizePositiveIds((array) ($params['pool_ids'] ?? []));
|
$poolIds = self::normalizePositiveIds((array) ($params['pool_ids'] ?? []));
|
||||||
$operatorAdminIds = self::normalizePositiveIds((array) (
|
$operatorAdminIds = self::normalizePositiveIds((array) (
|
||||||
$params['operator_admin_ids'] ?? $params['admin_ids'] ?? []
|
$params['operator_admin_ids'] ?? $params['admin_ids'] ?? []
|
||||||
@@ -598,9 +617,8 @@ class WecomPromotionLogic
|
|||||||
throw new RuntimeException('不能将当前账号设置为自己的共享操作人');
|
throw new RuntimeException('不能将当前账号设置为自己的共享操作人');
|
||||||
}
|
}
|
||||||
|
|
||||||
$pools = [];
|
|
||||||
foreach ($poolIds as $poolId) {
|
foreach ($poolIds as $poolId) {
|
||||||
$pools[$poolId] = self::assertScopedRow(
|
self::assertScopedRow(
|
||||||
'qywx_promotion_pool',
|
'qywx_promotion_pool',
|
||||||
$poolId,
|
$poolId,
|
||||||
$adminId,
|
$adminId,
|
||||||
@@ -609,7 +627,7 @@ class WecomPromotionLogic
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
if ($visibleIds !== null) {
|
if ($visibleIds !== null) {
|
||||||
foreach ($operatorAdminIds as $operatorAdminId) {
|
foreach ($operatorAdminIds as $operatorAdminId) {
|
||||||
if (!in_array($operatorAdminId, $visibleIds, true)) {
|
if (!in_array($operatorAdminId, $visibleIds, true)) {
|
||||||
@@ -621,40 +639,24 @@ class WecomPromotionLogic
|
|||||||
if ($action === 'grant') {
|
if ($action === 'grant') {
|
||||||
$adminQuery->where('disable', 0);
|
$adminQuery->where('disable', 0);
|
||||||
}
|
}
|
||||||
$operatorAdmins = $adminQuery->field('id,root')->select()->toArray();
|
$operatorAdmins = $adminQuery->field('id')->select()->toArray();
|
||||||
$existingAdminIds = self::normalizePositiveIds(array_column($operatorAdmins, 'id'));
|
$existingAdminIds = self::normalizePositiveIds(array_column($operatorAdmins, 'id'));
|
||||||
if (count($existingAdminIds) !== count($operatorAdminIds)) {
|
if (count($existingAdminIds) !== count($operatorAdminIds)) {
|
||||||
throw new RuntimeException($action === 'grant'
|
throw new RuntimeException($action === 'grant'
|
||||||
? '选择的操作人不存在或账号已被禁用'
|
? '选择的操作人不存在或账号已被禁用'
|
||||||
: '选择的操作人不存在');
|
: '选择的操作人不存在');
|
||||||
}
|
}
|
||||||
if ($action === 'grant') {
|
|
||||||
$pagePermissionAdminIds = self::promotionPagePermissionAdminIdSet($operatorAdminIds);
|
|
||||||
foreach ($operatorAdmins as $operatorAdmin) {
|
|
||||||
if ((int) ($operatorAdmin['root'] ?? 0) !== 1
|
|
||||||
&& !isset($pagePermissionAdminIds[(int) ($operatorAdmin['id'] ?? 0)])) {
|
|
||||||
throw new RuntimeException('选择的操作人尚未获得企业微信获客助手页面权限');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$now = time();
|
$now = time();
|
||||||
$affected = Db::transaction(function () use (
|
$affected = Db::transaction(function () use (
|
||||||
$action,
|
$action,
|
||||||
$poolIds,
|
$poolIds,
|
||||||
$pools,
|
|
||||||
$operatorAdminIds,
|
$operatorAdminIds,
|
||||||
$adminId,
|
$adminId,
|
||||||
$now
|
$now
|
||||||
): int {
|
): int {
|
||||||
$changed = 0;
|
$changed = 0;
|
||||||
foreach ($poolIds as $poolId) {
|
foreach ($poolIds as $poolId) {
|
||||||
$ownerAdminId = (int) ($pools[$poolId]['owner_admin_id'] ?? 0);
|
|
||||||
foreach ($operatorAdminIds as $operatorAdminId) {
|
foreach ($operatorAdminIds as $operatorAdminId) {
|
||||||
// 方案归属人天然拥有权限,无需写入共享关系。
|
|
||||||
if ($operatorAdminId === $ownerAdminId) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$query = Db::name('qywx_promotion_pool_operator')
|
$query = Db::name('qywx_promotion_pool_operator')
|
||||||
->where('pool_id', $poolId)
|
->where('pool_id', $poolId)
|
||||||
->where('admin_id', $operatorAdminId);
|
->where('admin_id', $operatorAdminId);
|
||||||
@@ -689,6 +691,7 @@ class WecomPromotionLogic
|
|||||||
|
|
||||||
return $changed;
|
return $changed;
|
||||||
});
|
});
|
||||||
|
self::clearOperatorAuthCaches($operatorAdminIds);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
@@ -836,13 +839,14 @@ class WecomPromotionLogic
|
|||||||
*/
|
*/
|
||||||
public static function syncRemoteLinks(int $poolId, int $adminId, array $adminInfo): array
|
public static function syncRemoteLinks(int $poolId, int $adminId, array $adminInfo): array
|
||||||
{
|
{
|
||||||
$pool = self::assertScopedRow('qywx_promotion_pool', $poolId, $adminId, $adminInfo);
|
self::assertBasePagePermission($adminId, $adminInfo);
|
||||||
|
$pool = self::assertScopedRow('qywx_promotion_pool', $poolId, $adminId, $adminInfo, false);
|
||||||
$legacyCount = (int) Db::name('qywx_promotion_link')
|
$legacyCount = (int) Db::name('qywx_promotion_link')
|
||||||
->where('pool_id', $poolId)
|
->where('pool_id', $poolId)
|
||||||
->whereNull('delete_time')
|
->whereNull('delete_time')
|
||||||
->whereRaw("(remote_link_id IS NULL OR remote_link_id = '')")
|
->whereRaw("(remote_link_id IS NULL OR remote_link_id = '')")
|
||||||
->count();
|
->count();
|
||||||
$visibleAdminIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$visibleAdminIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
$visibleUserIds = null;
|
$visibleUserIds = null;
|
||||||
if ($visibleAdminIds !== null) {
|
if ($visibleAdminIds !== null) {
|
||||||
$visibleUserIds = array_fill_keys(array_column(self::memberOptions(
|
$visibleUserIds = array_fill_keys(array_column(self::memberOptions(
|
||||||
@@ -914,7 +918,7 @@ class WecomPromotionLogic
|
|||||||
}
|
}
|
||||||
$api = new QywxCustomerAcquisitionApiService();
|
$api = new QywxCustomerAcquisitionApiService();
|
||||||
$remote = self::normaliseRemoteLink($api->getLink($remoteLinkId), $remoteLinkId);
|
$remote = self::normaliseRemoteLink($api->getLink($remoteLinkId), $remoteLinkId);
|
||||||
$visibleUserIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo) === null
|
$visibleUserIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo) === null
|
||||||
? null
|
? null
|
||||||
: array_fill_keys(array_column(self::memberOptions(
|
: array_fill_keys(array_column(self::memberOptions(
|
||||||
$adminId,
|
$adminId,
|
||||||
@@ -932,7 +936,8 @@ class WecomPromotionLogic
|
|||||||
/** 官方链接由方案统一删除,避免绕过方案删除租约和同步状态机。 */
|
/** 官方链接由方案统一删除,避免绕过方案删除租约和同步状态机。 */
|
||||||
public static function deleteRemoteLink(int $id, int $adminId, array $adminInfo): void
|
public static function deleteRemoteLink(int $id, int $adminId, array $adminInfo): void
|
||||||
{
|
{
|
||||||
$row = self::assertScopedRow('qywx_promotion_link', $id, $adminId, $adminInfo);
|
self::assertBasePagePermission($adminId, $adminInfo);
|
||||||
|
$row = self::assertScopedRow('qywx_promotion_link', $id, $adminId, $adminInfo, false);
|
||||||
$remoteLinkId = trim((string) ($row['remote_link_id'] ?? ''));
|
$remoteLinkId = trim((string) ($row['remote_link_id'] ?? ''));
|
||||||
if ($remoteLinkId === '') {
|
if ($remoteLinkId === '') {
|
||||||
throw new RuntimeException('历史手工链接只能从本地移除');
|
throw new RuntimeException('历史手工链接只能从本地移除');
|
||||||
@@ -955,7 +960,8 @@ class WecomPromotionLogic
|
|||||||
|
|
||||||
public static function deleteLink(int $id, int $adminId, array $adminInfo): void
|
public static function deleteLink(int $id, int $adminId, array $adminInfo): void
|
||||||
{
|
{
|
||||||
$row = self::assertScopedRow('qywx_promotion_link', $id, $adminId, $adminInfo);
|
self::assertBasePagePermission($adminId, $adminInfo);
|
||||||
|
$row = self::assertScopedRow('qywx_promotion_link', $id, $adminId, $adminInfo, false);
|
||||||
if (trim((string) ($row['remote_link_id'] ?? '')) !== '') {
|
if (trim((string) ($row['remote_link_id'] ?? '')) !== '') {
|
||||||
throw new RuntimeException('官方获客链接不能仅从本地移除,请使用“删除分流方案”同步删除企业微信链接');
|
throw new RuntimeException('官方获客链接不能仅从本地移除,请使用“删除分流方案”同步删除企业微信链接');
|
||||||
}
|
}
|
||||||
@@ -968,7 +974,7 @@ class WecomPromotionLogic
|
|||||||
/** @return list<array{id:int,name:string,disable:int,can_grant:bool,display_dept_id:int,dept_ids:list<int>,dept_names:list<string>}> */
|
/** @return list<array{id:int,name:string,disable:int,can_grant:bool,display_dept_id:int,dept_ids:list<int>,dept_names:list<string>}> */
|
||||||
private static function operatorOptions(int $adminId, array $adminInfo): array
|
private static function operatorOptions(int $adminId, array $adminInfo): array
|
||||||
{
|
{
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
if ($visibleIds === []) {
|
if ($visibleIds === []) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -978,24 +984,21 @@ class WecomPromotionLogic
|
|||||||
if ($visibleIds !== null) {
|
if ($visibleIds !== null) {
|
||||||
$query->whereIn('a.id', $visibleIds);
|
$query->whereIn('a.id', $visibleIds);
|
||||||
}
|
}
|
||||||
$admins = $query->field('a.id,a.name,a.root,a.disable')->order('a.disable', 'asc')->order('a.name', 'asc')->order('a.id', 'asc')->select()->toArray();
|
$admins = $query->field('a.id,a.name,a.disable')->order('a.disable', 'asc')->order('a.name', 'asc')->order('a.id', 'asc')->select()->toArray();
|
||||||
if ($admins === []) {
|
if ($admins === []) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$adminIds = self::normalizePositiveIds(array_column($admins, 'id'));
|
$adminIds = self::normalizePositiveIds(array_column($admins, 'id'));
|
||||||
$departments = self::adminDepartmentMaps($adminIds);
|
$departments = self::adminDepartmentMaps($adminIds);
|
||||||
$pagePermissionAdminIds = self::promotionPagePermissionAdminIdSet($adminIds);
|
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($admins as $admin) {
|
foreach ($admins as $admin) {
|
||||||
$aid = (int) $admin['id'];
|
$aid = (int) $admin['id'];
|
||||||
$deptIds = array_values(array_unique(array_filter($departments[$aid]['ids'] ?? [])));
|
$deptIds = array_values(array_unique(array_filter($departments[$aid]['ids'] ?? [])));
|
||||||
$hasPagePermission = (int) ($admin['root'] ?? 0) === 1
|
|
||||||
|| isset($pagePermissionAdminIds[$aid]);
|
|
||||||
$result[] = [
|
$result[] = [
|
||||||
'id' => $aid,
|
'id' => $aid,
|
||||||
'name' => (string) ($admin['name'] ?? ('账号 ' . $aid)),
|
'name' => (string) ($admin['name'] ?? ('账号 ' . $aid)),
|
||||||
'disable' => (int) ($admin['disable'] ?? 0),
|
'disable' => (int) ($admin['disable'] ?? 0),
|
||||||
'can_grant' => (int) ($admin['disable'] ?? 0) === 0 && $hasPagePermission,
|
'can_grant' => (int) ($admin['disable'] ?? 0) === 0,
|
||||||
'display_dept_id' => (int) ($deptIds[0] ?? 0),
|
'display_dept_id' => (int) ($deptIds[0] ?? 0),
|
||||||
'dept_ids' => $deptIds,
|
'dept_ids' => $deptIds,
|
||||||
'dept_names' => array_values(array_unique($departments[$aid]['names'] ?? [])),
|
'dept_names' => array_values(array_unique($departments[$aid]['names'] ?? [])),
|
||||||
@@ -1038,7 +1041,7 @@ class WecomPromotionLogic
|
|||||||
/** @return list<array{id:int,name:string,userid:string,display_dept_id:int,dept_ids:list<int>,dept_names:list<string>}> */
|
/** @return list<array{id:int,name:string,userid:string,display_dept_id:int,dept_ids:list<int>,dept_names:list<string>}> */
|
||||||
private static function memberOptions(int $adminId, array $adminInfo, array $extraAdminIds = []): array
|
private static function memberOptions(int $adminId, array $adminInfo, array $extraAdminIds = []): array
|
||||||
{
|
{
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
$allowedIds = $visibleIds === null
|
$allowedIds = $visibleIds === null
|
||||||
? null
|
? null
|
||||||
: self::normalizePositiveIds(array_merge($visibleIds, $extraAdminIds));
|
: self::normalizePositiveIds(array_merge($visibleIds, $extraAdminIds));
|
||||||
@@ -1439,7 +1442,7 @@ class WecomPromotionLogic
|
|||||||
throw new RuntimeException('数据不存在或已删除');
|
throw new RuntimeException('数据不存在或已删除');
|
||||||
}
|
}
|
||||||
|
|
||||||
$visibleIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
$visibleIds = QywxPromotionOperatorAccess::visibleAdminIds($adminId, $adminInfo);
|
||||||
$pool = $table === 'qywx_promotion_pool'
|
$pool = $table === 'qywx_promotion_pool'
|
||||||
? $row
|
? $row
|
||||||
: ($table === 'qywx_promotion_link'
|
: ($table === 'qywx_promotion_link'
|
||||||
@@ -1506,14 +1509,7 @@ class WecomPromotionLogic
|
|||||||
/** @return list<int> */
|
/** @return list<int> */
|
||||||
private static function operatorPoolIds(int $adminId): array
|
private static function operatorPoolIds(int $adminId): array
|
||||||
{
|
{
|
||||||
if ($adminId <= 0) {
|
return QywxPromotionOperatorAccess::activePoolIds($adminId);
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::normalizePositiveIds(Db::name('qywx_promotion_pool_operator')
|
|
||||||
->where('admin_id', $adminId)
|
|
||||||
->whereNull('delete_time')
|
|
||||||
->column('pool_id'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function isPoolOperator(int $poolId, int $adminId): bool
|
private static function isPoolOperator(int $poolId, int $adminId): bool
|
||||||
@@ -1566,33 +1562,6 @@ class WecomPromotionLogic
|
|||||||
return $departments;
|
return $departments;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param list<int> $adminIds @return array<int,true> */
|
|
||||||
private static function promotionPagePermissionAdminIdSet(array $adminIds): array
|
|
||||||
{
|
|
||||||
if ($adminIds === []) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
$menuIds = self::normalizePositiveIds(Db::name('system_menu')
|
|
||||||
->where('perms', 'firstvisit.wecomPromotion/overview')
|
|
||||||
->where('is_disable', 0)
|
|
||||||
->column('id'));
|
|
||||||
if ($menuIds === []) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
$roleIds = self::normalizePositiveIds(Db::name('system_role_menu')
|
|
||||||
->whereIn('menu_id', $menuIds)
|
|
||||||
->column('role_id'));
|
|
||||||
if ($roleIds === []) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
$permittedAdminIds = self::normalizePositiveIds(Db::name('admin_role')
|
|
||||||
->whereIn('role_id', $roleIds)
|
|
||||||
->whereIn('admin_id', $adminIds)
|
|
||||||
->column('admin_id'));
|
|
||||||
|
|
||||||
return array_fill_keys($permittedAdminIds, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return list<int> */
|
/** @return list<int> */
|
||||||
private static function normalizePositiveIds(array $ids): array
|
private static function normalizePositiveIds(array $ids): array
|
||||||
{
|
{
|
||||||
@@ -1620,6 +1589,30 @@ class WecomPromotionLogic
|
|||||||
return $time === false ? 0 : $time;
|
return $time === false ? 0 : $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function assertBasePagePermission(int $adminId, array $adminInfo): void
|
||||||
|
{
|
||||||
|
if (!QywxPromotionOperatorAccess::hasBasePagePermission($adminId, $adminInfo)) {
|
||||||
|
throw new RuntimeException('共享操作人无权执行新建、删除、转授权或全局同步操作');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param list<int> $adminIds */
|
||||||
|
private static function clearOperatorAuthCaches(array $adminIds): void
|
||||||
|
{
|
||||||
|
foreach (self::normalizePositiveIds($adminIds) as $operatorAdminId) {
|
||||||
|
try {
|
||||||
|
(new AdminAuthCache($operatorAdminId))->clearAuthCache();
|
||||||
|
} catch (\Throwable $error) {
|
||||||
|
// 授权关系已提交,缓存清理失败不应回滚数据;业务接口仍有实时权限校验。
|
||||||
|
Log::warning(sprintf(
|
||||||
|
'清理获客助手共享操作人权限缓存失败 admin_id=%d: %s',
|
||||||
|
$operatorAdminId,
|
||||||
|
$error->getMessage()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static function assertMemberDispatchSchema(): void
|
private static function assertMemberDispatchSchema(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\common\service\qywx;
|
||||||
|
|
||||||
|
use app\common\service\DataScope\DataScopeService;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
/** 分流方案共享操作人产生的页面入口与专用数据范围。 */
|
||||||
|
final class QywxPromotionOperatorAccess
|
||||||
|
{
|
||||||
|
public const PAGE_PERMISSION = 'firstvisit.wecomPromotion/overview';
|
||||||
|
|
||||||
|
public static function hasBasePagePermission(int $adminId, array $adminInfo = []): bool
|
||||||
|
{
|
||||||
|
if ((int) ($adminInfo['root'] ?? 0) === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($adminId <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Db::name('admin_role')->alias('ar')
|
||||||
|
->join('system_role_menu rm', 'rm.role_id = ar.role_id')
|
||||||
|
->join('system_menu m', 'm.id = rm.menu_id')
|
||||||
|
->where('ar.admin_id', $adminId)
|
||||||
|
->where('m.perms', self::PAGE_PERMISSION)
|
||||||
|
->where('m.is_disable', 0)
|
||||||
|
->count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hasSharedPagePermission(int $adminId): bool
|
||||||
|
{
|
||||||
|
if ($adminId <= 0 || !self::pageMenuEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Db::name('qywx_promotion_pool_operator')->alias('po')
|
||||||
|
->join('qywx_promotion_pool p', 'p.id = po.pool_id')
|
||||||
|
->where('po.admin_id', $adminId)
|
||||||
|
->whereNull('po.delete_time')
|
||||||
|
->whereNull('p.delete_time')
|
||||||
|
->count() > 0;
|
||||||
|
} catch (\Throwable $error) {
|
||||||
|
if (self::isMissingTable($error)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hasPagePermission(int $adminId, array $adminInfo = []): bool
|
||||||
|
{
|
||||||
|
return self::hasBasePagePermission($adminId, $adminInfo)
|
||||||
|
|| self::hasSharedPagePermission($adminId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 基础页面权限沿用角色数据范围;纯共享账号只能通过 operator pool 范围访问。 */
|
||||||
|
public static function visibleAdminIds(int $adminId, array $adminInfo): ?array
|
||||||
|
{
|
||||||
|
return self::hasBasePagePermission($adminId, $adminInfo)
|
||||||
|
? DataScopeService::getVisibleAdminIds($adminId, $adminInfo)
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return list<int> */
|
||||||
|
public static function activePoolIds(int $adminId): array
|
||||||
|
{
|
||||||
|
if ($adminId <= 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$ids = Db::name('qywx_promotion_pool_operator')->alias('po')
|
||||||
|
->join('qywx_promotion_pool p', 'p.id = po.pool_id')
|
||||||
|
->where('po.admin_id', $adminId)
|
||||||
|
->whereNull('po.delete_time')
|
||||||
|
->whereNull('p.delete_time')
|
||||||
|
->column('po.pool_id');
|
||||||
|
} catch (\Throwable $error) {
|
||||||
|
if (self::isMissingTable($error)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
throw $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_unique(array_filter(array_map(
|
||||||
|
static fn ($value): int => (int) $value,
|
||||||
|
$ids
|
||||||
|
), static fn (int $value): bool => $value > 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function pageMenuEnabled(): bool
|
||||||
|
{
|
||||||
|
return Db::name('system_menu')
|
||||||
|
->where('perms', self::PAGE_PERMISSION)
|
||||||
|
->where('is_disable', 0)
|
||||||
|
->count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isMissingTable(\Throwable $error): bool
|
||||||
|
{
|
||||||
|
$message = strtolower($error->getMessage());
|
||||||
|
|
||||||
|
return str_contains($message, '42s02')
|
||||||
|
|| str_contains($message, '1146')
|
||||||
|
|| str_contains($message, 'no such table');
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import t from"./error-abZoCXdu.js";import{o,q as r,r as a,v as n,D as c,s}from"./.pnpm-BSw4l71J.js";import"./index-BWlhxa68.js";const p="/admin/assets/no_perms-jDxcYpYC.png",i={class:"error404"},x=o({__name:"403",setup(m){return(_,e)=>(r(),a("div",i,[n(t,{code:"403",title:"您的账号权限不足,请联系管理员添加权限!","show-btn":!1},{content:c(()=>[...e[0]||(e[0]=[s("div",{class:"flex justify-center"},[s("img",{class:"w-[150px] h-[150px]",src:p,alt:""})],-1)])]),_:1})]))}});export{x as default};
|
import t from"./error-D5egTBIV.js";import{o,q as r,r as a,v as n,D as c,s}from"./.pnpm-BSw4l71J.js";import"./index-CQbHw_bK.js";const p="/admin/assets/no_perms-jDxcYpYC.png",i={class:"error404"},x=o({__name:"403",setup(m){return(_,e)=>(r(),a("div",i,[n(t,{code:"403",title:"您的账号权限不足,请联系管理员添加权限!","show-btn":!1},{content:c(()=>[...e[0]||(e[0]=[s("div",{class:"flex justify-center"},[s("img",{class:"w-[150px] h-[150px]",src:p,alt:""})],-1)])]),_:1})]))}});export{x as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import e from"./error-abZoCXdu.js";import{o,q as r,r as t,v as s}from"./.pnpm-BSw4l71J.js";import"./index-BWlhxa68.js";const a={class:"error404"},d=o({__name:"404",setup(c){return(n,_)=>(r(),t("div",a,[s(e,{code:"404",title:"哎呀,出错了!您访问的页面不存在…"})]))}});export{d as default};
|
import e from"./error-D5egTBIV.js";import{o,q as r,r as t,v as s}from"./.pnpm-BSw4l71J.js";import"./index-CQbHw_bK.js";const a={class:"error404"},d=o({__name:"404",setup(c){return(n,_)=>(r(),t("div",a,[s(e,{code:"404",title:"哎呀,出错了!您访问的页面不存在…"})]))}});export{d as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as C,R as D,q as d,r as I,ac as N,O as u,bj as B,D as o,v as l,bk as E,br as L,L as i,T as r,s as p,bi as R,M as w}from"./.pnpm-BSw4l71J.js";import{a as V}from"./doctor-DBWxvtwh.js";import{m as A,_ as M}from"./index-BWlhxa68.js";const P={class:"appointment-record-panel"},$={class:"cell-stack"},j={class:"font-medium"},q={class:"text-gray-500 text-sm"},O={class:"cell-stack"},F={class:"text-gray-500 text-sm"},G=C({__name:"AppointmentRecordPanel",props:{diagnosisId:{}},setup(v,{expose:y}){const f=v,m=w(!1),g=w([]),h=w({});function x(t){return t?String(t).length>=8?String(t).slice(0,5):t:""}function k(t){return t==="morning"?"上午":t==="afternoon"?"下午":t==="all"?"全天":t||"—"}function S(t){const n=t.channel_source??t.channels??"";if(n===""||n===null||n===void 0)return"—";const a=String(n),s=h.value[a]||a,c=String(t.channel_source_detail??"").trim();return c!==""?`${s}(${c})`:s}function T(t){return[...t].sort((n,a)=>{const s=String(n.appointment_date||""),c=String(a.appointment_date||"");if(s!==c)return c.localeCompare(s);const _=String(n.appointment_time||""),e=String(a.appointment_time||"");return _!==e?e.localeCompare(_):Number(a.id||0)-Number(n.id||0)})}const z=async()=>{try{const t=await A({type:"channels"}),n=((t==null?void 0:t.channels)||[]).filter(s=>s.status!==0),a={};for(const s of n)s.value!=null&&(a[String(s.value)]=s.name||String(s.value));h.value=a}catch{h.value={}}},b=async()=>{if(f.diagnosisId){m.value=!0;try{await z();const t=await V({patient_id:f.diagnosisId,diag_scope_relax:1,page_no:1,page_size:500}),n=(t==null?void 0:t.lists)||[];g.value=T(n)}catch(t){console.error(t),g.value=[]}finally{m.value=!1}}};return D(()=>f.diagnosisId,()=>{b()},{immediate:!0}),y({refresh:b}),(t,n)=>{const a=E,s=L,c=B,_=R;return d(),I("div",P,[N((d(),u(c,{data:g.value,border:"",stripe:"","empty-text":"暂无挂号记录"},{default:o(()=>[l(a,{label:"ID",prop:"id",width:"72",align:"center"}),l(a,{label:"状态",width:"100",align:"center"},{default:o(({row:e})=>[l(s,{type:e.status===1?"success":e.status===2?"info":e.status===3?"primary":"danger",size:"small",effect:"light"},{default:o(()=>[i(r(e.status_desc||"—"),1)]),_:2},1032,["type"])]),_:1}),l(a,{label:"患者(挂号人)","min-width":"150"},{default:o(({row:e})=>[p("div",$,[p("span",j,r(e.patient_name||"—"),1),p("span",q,r(e.patient_phone||""),1)])]),_:1}),l(a,{label:"挂号医生",prop:"doctor_name",width:"110","show-overflow-tooltip":""}),l(a,{label:"挂号助理",width:"110","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(e.assistant_name||"—"),1)]),_:1}),l(a,{label:"预约时间","min-width":"130"},{default:o(({row:e})=>[p("div",O,[p("span",null,r(e.appointment_date||"—"),1),p("span",F,r(x(e.appointment_time)),1)])]),_:1}),l(a,{label:"时段",width:"80",align:"center"},{default:o(({row:e})=>[i(r(k(e.period)),1)]),_:1}),l(a,{label:"类型",width:"100","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(e.appointment_type_desc||"—"),1)]),_:1}),l(a,{label:"渠道",width:"110","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(S(e)),1)]),_:1}),l(a,{label:"确认诊单",width:"92",align:"center"},{default:o(({row:e})=>[e.diagnosis_confirmed?(d(),u(s,{key:0,type:"success",size:"small",effect:"plain"},{default:o(()=>[...n[0]||(n[0]=[i("已确认",-1)])]),_:1})):(d(),u(s,{key:1,type:"warning",size:"small",effect:"plain"},{default:o(()=>[...n[1]||(n[1]=[i("未确认",-1)])]),_:1}))]),_:1}),l(a,{label:"开方",width:"80",align:"center"},{default:o(({row:e})=>[e.has_prescription?(d(),u(s,{key:0,type:"success",size:"small",effect:"plain"},{default:o(()=>[...n[2]||(n[2]=[i("已开方",-1)])]),_:1})):(d(),u(s,{key:1,type:"info",size:"small",effect:"plain"},{default:o(()=>[...n[3]||(n[3]=[i("未开方",-1)])]),_:1}))]),_:1}),l(a,{label:"备注",prop:"remark","min-width":"100","show-overflow-tooltip":""}),l(a,{label:"创建时间",width:"165",prop:"create_time"})]),_:1},8,["data"])),[[_,m.value]])])}}}),Q=M(G,[["__scopeId","data-v-4de87dfa"]]);export{Q as default};
|
import{o as C,R as D,q as d,r as I,ac as N,O as u,bj as B,D as o,v as l,bk as E,br as L,L as i,T as r,s as p,bi as R,M as w}from"./.pnpm-BSw4l71J.js";import{a as V}from"./doctor-DcA9ycFS.js";import{m as A,_ as M}from"./index-CQbHw_bK.js";const P={class:"appointment-record-panel"},$={class:"cell-stack"},j={class:"font-medium"},q={class:"text-gray-500 text-sm"},O={class:"cell-stack"},F={class:"text-gray-500 text-sm"},G=C({__name:"AppointmentRecordPanel",props:{diagnosisId:{}},setup(v,{expose:y}){const f=v,m=w(!1),g=w([]),h=w({});function x(t){return t?String(t).length>=8?String(t).slice(0,5):t:""}function k(t){return t==="morning"?"上午":t==="afternoon"?"下午":t==="all"?"全天":t||"—"}function S(t){const n=t.channel_source??t.channels??"";if(n===""||n===null||n===void 0)return"—";const a=String(n),s=h.value[a]||a,c=String(t.channel_source_detail??"").trim();return c!==""?`${s}(${c})`:s}function T(t){return[...t].sort((n,a)=>{const s=String(n.appointment_date||""),c=String(a.appointment_date||"");if(s!==c)return c.localeCompare(s);const _=String(n.appointment_time||""),e=String(a.appointment_time||"");return _!==e?e.localeCompare(_):Number(a.id||0)-Number(n.id||0)})}const z=async()=>{try{const t=await A({type:"channels"}),n=((t==null?void 0:t.channels)||[]).filter(s=>s.status!==0),a={};for(const s of n)s.value!=null&&(a[String(s.value)]=s.name||String(s.value));h.value=a}catch{h.value={}}},b=async()=>{if(f.diagnosisId){m.value=!0;try{await z();const t=await V({patient_id:f.diagnosisId,diag_scope_relax:1,page_no:1,page_size:500}),n=(t==null?void 0:t.lists)||[];g.value=T(n)}catch(t){console.error(t),g.value=[]}finally{m.value=!1}}};return D(()=>f.diagnosisId,()=>{b()},{immediate:!0}),y({refresh:b}),(t,n)=>{const a=E,s=L,c=B,_=R;return d(),I("div",P,[N((d(),u(c,{data:g.value,border:"",stripe:"","empty-text":"暂无挂号记录"},{default:o(()=>[l(a,{label:"ID",prop:"id",width:"72",align:"center"}),l(a,{label:"状态",width:"100",align:"center"},{default:o(({row:e})=>[l(s,{type:e.status===1?"success":e.status===2?"info":e.status===3?"primary":"danger",size:"small",effect:"light"},{default:o(()=>[i(r(e.status_desc||"—"),1)]),_:2},1032,["type"])]),_:1}),l(a,{label:"患者(挂号人)","min-width":"150"},{default:o(({row:e})=>[p("div",$,[p("span",j,r(e.patient_name||"—"),1),p("span",q,r(e.patient_phone||""),1)])]),_:1}),l(a,{label:"挂号医生",prop:"doctor_name",width:"110","show-overflow-tooltip":""}),l(a,{label:"挂号助理",width:"110","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(e.assistant_name||"—"),1)]),_:1}),l(a,{label:"预约时间","min-width":"130"},{default:o(({row:e})=>[p("div",O,[p("span",null,r(e.appointment_date||"—"),1),p("span",F,r(x(e.appointment_time)),1)])]),_:1}),l(a,{label:"时段",width:"80",align:"center"},{default:o(({row:e})=>[i(r(k(e.period)),1)]),_:1}),l(a,{label:"类型",width:"100","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(e.appointment_type_desc||"—"),1)]),_:1}),l(a,{label:"渠道",width:"110","show-overflow-tooltip":""},{default:o(({row:e})=>[i(r(S(e)),1)]),_:1}),l(a,{label:"确认诊单",width:"92",align:"center"},{default:o(({row:e})=>[e.diagnosis_confirmed?(d(),u(s,{key:0,type:"success",size:"small",effect:"plain"},{default:o(()=>[...n[0]||(n[0]=[i("已确认",-1)])]),_:1})):(d(),u(s,{key:1,type:"warning",size:"small",effect:"plain"},{default:o(()=>[...n[1]||(n[1]=[i("未确认",-1)])]),_:1}))]),_:1}),l(a,{label:"开方",width:"80",align:"center"},{default:o(({row:e})=>[e.has_prescription?(d(),u(s,{key:0,type:"success",size:"small",effect:"plain"},{default:o(()=>[...n[2]||(n[2]=[i("已开方",-1)])]),_:1})):(d(),u(s,{key:1,type:"info",size:"small",effect:"plain"},{default:o(()=>[...n[3]||(n[3]=[i("未开方",-1)])]),_:1}))]),_:1}),l(a,{label:"备注",prop:"remark","min-width":"100","show-overflow-tooltip":""}),l(a,{label:"创建时间",width:"165",prop:"create_time"})]),_:1},8,["data"])),[[_,m.value]])])}}}),Q=M(G,[["__scopeId","data-v-4de87dfa"]]);export{Q as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as T,R as C,q as _,r as b,ac as D,O as h,bj as $,D as r,v as n,bk as L,L as c,T as d,br as k,s as E,a1 as A,w as P,u as B,ch as F,bi as M,M as w}from"./.pnpm-BSw4l71J.js";import{af as V}from"./tcm-Bv_Ly0A0.js";import{_ as q}from"./index-BWlhxa68.js";const K={class:"assign-log-panel"},j={key:1,class:"text-gray-400"},z=T({__name:"AssignLogPanel",props:{diagnosisId:{}},setup(v,{expose:y}){const u=v,m=w(!1),p=w([]);function N(a){const e=a.related_po_creator_name;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(a.related_po_creator_id);return Number.isFinite(t)&&t>0?`ID:${t}`:"—"}function x(a){const e=a.related_po_create_time_text;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(a.related_po_create_time);if(!Number.isFinite(t)||t<=0)return"—";const s=new Date(t*1e3);if(Number.isNaN(s.getTime()))return"—";const o=l=>String(l).padStart(2,"0");return`${s.getFullYear()}-${o(s.getMonth()+1)}-${o(s.getDate())} ${o(s.getHours())}:${o(s.getMinutes())}:${o(s.getSeconds())}`}function f(a,e){const t=e==="from"?"from_assistant_name":"to_assistant_name",s=e==="from"?"from_assistant_id":"to_assistant_id",o=a[t];if(o!=null&&String(o).trim()!==""&&String(o)!=="—")return String(o);const l=Number(a[s]);return Number.isFinite(l)&&l>0?`ID:${l}`:"—"}const g=async()=>{if(u.diagnosisId){m.value=!0;try{const a=await V({id:u.diagnosisId}),e=Array.isArray(a)?a:[];p.value=e}catch(a){console.error(a),p.value=[]}finally{m.value=!1}}};return C(()=>u.diagnosisId,()=>{g()},{immediate:!0}),y({refresh:g}),(a,e)=>{const t=L,s=k,o=P,l=A,S=$,I=M;return _(),b("div",K,[D((_(),h(S,{data:p.value,border:"",stripe:"","empty-text":"暂无指派记录"},{default:r(()=>[n(t,{label:"操作时间",width:"175",prop:"create_time_text"}),n(t,{label:"原医助","min-width":"120"},{default:r(({row:i})=>[c(d(f(i,"from")),1)]),_:1}),n(t,{label:"新医助","min-width":"120"},{default:r(({row:i})=>[c(d(f(i,"to")),1)]),_:1}),n(t,{label:"继承",width:"72",align:"center"},{default:r(({row:i})=>[Number(i.is_inherit)===1?(_(),h(s,{key:0,type:"success",size:"small"},{default:r(()=>[...e[0]||(e[0]=[c("是",-1)])]),_:1})):(_(),b("span",j,"否"))]),_:1}),n(t,{label:"快照·业务单创建人","min-width":"130","show-overflow-tooltip":""},{default:r(({row:i})=>[c(d(N(i)),1)]),_:1}),n(t,{label:"快照·业务单创建时间",width:"190"},{header:r(()=>[e[1]||(e[1]=E("span",null,"快照·业务单创建时间",-1)),n(l,{placement:"top",content:"related_po_create_time:触发本次操作的处方业务订单 create_time;与原文助一致时表示医助创建订单时间"},{default:r(()=>[n(o,{class:"assign-log-col-hint"},{default:r(()=>[n(B(F))]),_:1})]),_:1})]),default:r(({row:i})=>[c(d(x(i)),1)]),_:1}),n(t,{label:"操作人",width:"110",prop:"operator_name"}),n(t,{label:"操作账号",width:"120",prop:"operator_account","show-overflow-tooltip":""}),n(t,{label:"IP",width:"130",prop:"ip","show-overflow-tooltip":""})]),_:1},8,["data"])),[[I,m.value]])])}}}),Y=q(z,[["__scopeId","data-v-f670e3e6"]]);export{Y as default};
|
import{o as T,R as C,q as _,r as b,ac as D,O as h,bj as $,D as r,v as n,bk as L,L as c,T as d,br as k,s as E,a1 as A,w as P,u as B,ch as F,bi as M,M as w}from"./.pnpm-BSw4l71J.js";import{af as V}from"./tcm-PbOYp3fC.js";import{_ as q}from"./index-CQbHw_bK.js";const K={class:"assign-log-panel"},j={key:1,class:"text-gray-400"},z=T({__name:"AssignLogPanel",props:{diagnosisId:{}},setup(v,{expose:y}){const u=v,m=w(!1),p=w([]);function N(a){const e=a.related_po_creator_name;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(a.related_po_creator_id);return Number.isFinite(t)&&t>0?`ID:${t}`:"—"}function x(a){const e=a.related_po_create_time_text;if(e!=null&&String(e).trim()!=="")return String(e);const t=Number(a.related_po_create_time);if(!Number.isFinite(t)||t<=0)return"—";const s=new Date(t*1e3);if(Number.isNaN(s.getTime()))return"—";const o=l=>String(l).padStart(2,"0");return`${s.getFullYear()}-${o(s.getMonth()+1)}-${o(s.getDate())} ${o(s.getHours())}:${o(s.getMinutes())}:${o(s.getSeconds())}`}function f(a,e){const t=e==="from"?"from_assistant_name":"to_assistant_name",s=e==="from"?"from_assistant_id":"to_assistant_id",o=a[t];if(o!=null&&String(o).trim()!==""&&String(o)!=="—")return String(o);const l=Number(a[s]);return Number.isFinite(l)&&l>0?`ID:${l}`:"—"}const g=async()=>{if(u.diagnosisId){m.value=!0;try{const a=await V({id:u.diagnosisId}),e=Array.isArray(a)?a:[];p.value=e}catch(a){console.error(a),p.value=[]}finally{m.value=!1}}};return C(()=>u.diagnosisId,()=>{g()},{immediate:!0}),y({refresh:g}),(a,e)=>{const t=L,s=k,o=P,l=A,S=$,I=M;return _(),b("div",K,[D((_(),h(S,{data:p.value,border:"",stripe:"","empty-text":"暂无指派记录"},{default:r(()=>[n(t,{label:"操作时间",width:"175",prop:"create_time_text"}),n(t,{label:"原医助","min-width":"120"},{default:r(({row:i})=>[c(d(f(i,"from")),1)]),_:1}),n(t,{label:"新医助","min-width":"120"},{default:r(({row:i})=>[c(d(f(i,"to")),1)]),_:1}),n(t,{label:"继承",width:"72",align:"center"},{default:r(({row:i})=>[Number(i.is_inherit)===1?(_(),h(s,{key:0,type:"success",size:"small"},{default:r(()=>[...e[0]||(e[0]=[c("是",-1)])]),_:1})):(_(),b("span",j,"否"))]),_:1}),n(t,{label:"快照·业务单创建人","min-width":"130","show-overflow-tooltip":""},{default:r(({row:i})=>[c(d(N(i)),1)]),_:1}),n(t,{label:"快照·业务单创建时间",width:"190"},{header:r(()=>[e[1]||(e[1]=E("span",null,"快照·业务单创建时间",-1)),n(l,{placement:"top",content:"related_po_create_time:触发本次操作的处方业务订单 create_time;与原文助一致时表示医助创建订单时间"},{default:r(()=>[n(o,{class:"assign-log-col-hint"},{default:r(()=>[n(B(F))]),_:1})]),_:1})]),default:r(({row:i})=>[c(d(x(i)),1)]),_:1}),n(t,{label:"操作人",width:"110",prop:"operator_name"}),n(t,{label:"操作账号",width:"120",prop:"operator_account","show-overflow-tooltip":""}),n(t,{label:"IP",width:"130",prop:"ip","show-overflow-tooltip":""})]),_:1},8,["data"])),[[I,m.value]])])}}}),Y=q(z,[["__scopeId","data-v-f670e3e6"]]);export{Y as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as B,R as D,q as E,O,D as I,r as _,T as S,P as x,ac as W,s as h,ad as P,v as U,K as $,L as j,bt as H,p as K,M as v,di as c}from"./.pnpm-BSw4l71J.js";import{ag as Y}from"./tcm-Bv_Ly0A0.js";import{_ as q}from"./index-BWlhxa68.js";const z={key:0,class:"watch-state"},F={key:1,class:"watch-state watch-error"},G=B({__name:"AssistantWatchCallDialog",props:{modelValue:{type:Boolean},diagnosisId:{}},emits:["update:modelValue","closed"],setup(R,{emit:A}){const u=R,g=A,y=K({get:()=>u.modelValue,set:t=>g("update:modelValue",t)}),r=v(null),l=v(!1),i=v(""),f=v("旁观视频通话"),n=new Map;let a=null,p=0;function w(t,e){return`${t}\0${String(e)}`}function N(t){return t.startsWith("patient_")?"患者":t.startsWith("doctor_")?"医护":t}async function T(t){if(!a||!r.value||t.streamType!==c.TYPE.STREAM_TYPE_MAIN)return;const e=w(t.userId,t.streamType);if(n.has(e))return;const o=document.createElement("div");o.className="watch-tile";const s=document.createElement("div");s.className="watch-tile-cap",s.textContent=N(t.userId);const d=document.createElement("div");d.className="watch-tile-view",o.appendChild(s),o.appendChild(d),r.value.appendChild(o),n.set(e,{wrap:o,userId:t.userId,streamType:t.streamType});try{await a.startRemoteVideo({userId:t.userId,streamType:t.streamType,view:d})}catch(b){console.warn("[AssistantWatchCall] startRemoteVideo",b)}}async function V(t){if(!a)return;const e=w(t.userId,t.streamType),o=n.get(e);if(o){try{await a.stopRemoteVideo({userId:t.userId,streamType:t.streamType})}catch{}o.wrap.remove(),n.delete(e)}}function C(){a&&(a.on(c.EVENT.REMOTE_VIDEO_AVAILABLE,T),a.on(c.EVENT.REMOTE_VIDEO_UNAVAILABLE,V))}function k(){a&&(a.off(c.EVENT.REMOTE_VIDEO_AVAILABLE,T),a.off(c.EVENT.REMOTE_VIDEO_UNAVAILABLE,V))}async function m(){if(k(),a){for(const[,t]of n){try{await a.stopRemoteVideo({userId:t.userId,streamType:t.streamType})}catch{}t.wrap.remove()}n.clear(),r.value&&(r.value.innerHTML="");try{await a.exitRoom()}catch{}try{a.destroy()}catch{}a=null}else n.clear(),r.value&&(r.value.innerHTML="")}async function L(){const t=++p;if(await m(),!u.diagnosisId){i.value="诊单无效";return}l.value=!0,i.value="",f.value="旁观视频通话";try{const e=await Y({diagnosis_id:u.diagnosisId});if(t!==p)return;e.patientName&&(f.value=`旁观视频通话 · ${e.patientName}`),a=c.create(),C();const o={sdkAppId:e.sdkAppId,userId:e.userId,userSig:e.userSig,autoReceiveAudio:!0,autoReceiveVideo:!0,...e.roomId!=null&&e.roomId>0?{roomId:e.roomId}:{strRoomId:e.strRoomId}};if(!(e.roomId!=null&&e.roomId>0)&&!e.strRoomId)throw new Error("缺少房间号");if(await a.enterRoom(o),t!==p){await m();return}l.value=!1}catch(e){l.value=!1;let o="进入房间失败";if(typeof e=="string")o=e;else if(e&&typeof e=="object"){const s=e;s.msg?o=String(s.msg):s.message&&(o=String(s.message))}i.value=o,await m()}}function M(){m(),l.value=!1,i.value="",f.value="旁观视频通话",g("closed")}return D(()=>[u.modelValue,u.diagnosisId],([t,e])=>{if(!t){p++,m();return}e>0&&L()}),(t,e)=>{const o=$,s=H;return E(),O(s,{modelValue:y.value,"onUpdate:modelValue":e[1]||(e[1]=d=>y.value=d),title:f.value,width:"760px","destroy-on-close":"","append-to-body":"","close-on-click-modal":!1,class:"assistant-watch-call-dialog",onClosed:M},{footer:I(()=>[e[3]||(e[3]=h("span",{class:"watch-hint"},"仅观看,不会开启摄像头与麦克风",-1)),U(o,{type:"primary",onClick:e[0]||(e[0]=d=>y.value=!1)},{default:I(()=>[...e[2]||(e[2]=[j("离开",-1)])]),_:1})]),default:I(()=>[l.value?(E(),_("div",z,"正在连接房间…")):i.value?(E(),_("div",F,S(i.value),1)):x("",!0),W(h("div",{ref_key:"gridRef",ref:r,class:"watch-grid"},null,512),[[P,!l.value&&!i.value]])]),_:1},8,["modelValue","title"])}}}),Z=q(G,[["__scopeId","data-v-7aff665d"]]);export{Z as default};
|
import{o as B,R as D,q as E,O,D as I,r as _,T as S,P as x,ac as W,s as h,ad as P,v as U,K as $,L as j,bt as H,p as K,M as v,di as c}from"./.pnpm-BSw4l71J.js";import{ag as Y}from"./tcm-PbOYp3fC.js";import{_ as q}from"./index-CQbHw_bK.js";const z={key:0,class:"watch-state"},F={key:1,class:"watch-state watch-error"},G=B({__name:"AssistantWatchCallDialog",props:{modelValue:{type:Boolean},diagnosisId:{}},emits:["update:modelValue","closed"],setup(R,{emit:A}){const u=R,g=A,y=K({get:()=>u.modelValue,set:t=>g("update:modelValue",t)}),r=v(null),l=v(!1),i=v(""),f=v("旁观视频通话"),n=new Map;let a=null,p=0;function w(t,e){return`${t}\0${String(e)}`}function N(t){return t.startsWith("patient_")?"患者":t.startsWith("doctor_")?"医护":t}async function T(t){if(!a||!r.value||t.streamType!==c.TYPE.STREAM_TYPE_MAIN)return;const e=w(t.userId,t.streamType);if(n.has(e))return;const o=document.createElement("div");o.className="watch-tile";const s=document.createElement("div");s.className="watch-tile-cap",s.textContent=N(t.userId);const d=document.createElement("div");d.className="watch-tile-view",o.appendChild(s),o.appendChild(d),r.value.appendChild(o),n.set(e,{wrap:o,userId:t.userId,streamType:t.streamType});try{await a.startRemoteVideo({userId:t.userId,streamType:t.streamType,view:d})}catch(b){console.warn("[AssistantWatchCall] startRemoteVideo",b)}}async function V(t){if(!a)return;const e=w(t.userId,t.streamType),o=n.get(e);if(o){try{await a.stopRemoteVideo({userId:t.userId,streamType:t.streamType})}catch{}o.wrap.remove(),n.delete(e)}}function C(){a&&(a.on(c.EVENT.REMOTE_VIDEO_AVAILABLE,T),a.on(c.EVENT.REMOTE_VIDEO_UNAVAILABLE,V))}function k(){a&&(a.off(c.EVENT.REMOTE_VIDEO_AVAILABLE,T),a.off(c.EVENT.REMOTE_VIDEO_UNAVAILABLE,V))}async function m(){if(k(),a){for(const[,t]of n){try{await a.stopRemoteVideo({userId:t.userId,streamType:t.streamType})}catch{}t.wrap.remove()}n.clear(),r.value&&(r.value.innerHTML="");try{await a.exitRoom()}catch{}try{a.destroy()}catch{}a=null}else n.clear(),r.value&&(r.value.innerHTML="")}async function L(){const t=++p;if(await m(),!u.diagnosisId){i.value="诊单无效";return}l.value=!0,i.value="",f.value="旁观视频通话";try{const e=await Y({diagnosis_id:u.diagnosisId});if(t!==p)return;e.patientName&&(f.value=`旁观视频通话 · ${e.patientName}`),a=c.create(),C();const o={sdkAppId:e.sdkAppId,userId:e.userId,userSig:e.userSig,autoReceiveAudio:!0,autoReceiveVideo:!0,...e.roomId!=null&&e.roomId>0?{roomId:e.roomId}:{strRoomId:e.strRoomId}};if(!(e.roomId!=null&&e.roomId>0)&&!e.strRoomId)throw new Error("缺少房间号");if(await a.enterRoom(o),t!==p){await m();return}l.value=!1}catch(e){l.value=!1;let o="进入房间失败";if(typeof e=="string")o=e;else if(e&&typeof e=="object"){const s=e;s.msg?o=String(s.msg):s.message&&(o=String(s.message))}i.value=o,await m()}}function M(){m(),l.value=!1,i.value="",f.value="旁观视频通话",g("closed")}return D(()=>[u.modelValue,u.diagnosisId],([t,e])=>{if(!t){p++,m();return}e>0&&L()}),(t,e)=>{const o=$,s=H;return E(),O(s,{modelValue:y.value,"onUpdate:modelValue":e[1]||(e[1]=d=>y.value=d),title:f.value,width:"760px","destroy-on-close":"","append-to-body":"","close-on-click-modal":!1,class:"assistant-watch-call-dialog",onClosed:M},{footer:I(()=>[e[3]||(e[3]=h("span",{class:"watch-hint"},"仅观看,不会开启摄像头与麦克风",-1)),U(o,{type:"primary",onClick:e[0]||(e[0]=d=>y.value=!1)},{default:I(()=>[...e[2]||(e[2]=[j("离开",-1)])]),_:1})]),default:I(()=>[l.value?(E(),_("div",z,"正在连接房间…")):i.value?(E(),_("div",F,S(i.value),1)):x("",!0),W(h("div",{ref_key:"gridRef",ref:r,class:"watch-grid"},null,512),[[P,!l.value&&!i.value]])]),_:1},8,["modelValue","title"])}}}),Z=q(G,[["__scopeId","data-v-7aff665d"]]);export{Z as default};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as N,dk as O,R as P,q as d,r as f,v as o,D as i,K as V,L as n,P as h,ac as D,O as w,bj as L,bk as z,T as u,s as y,bi as M,M as v}from"./.pnpm-BSw4l71J.js";import j from"./RecordingPlaybackBlock-Ci19TbAl.js";import{U as k}from"./index-TisaJaAB.js";import{i as c,_ as q}from"./index-BWlhxa68.js";import{ak as K,al as x,am as A}from"./tcm-Bv_Ly0A0.js";import"./RecordingVideoPlayer-fgB7SxV4.js";import"./file-BXk5F0Ys.js";const F={class:"call-record-panel"},G={key:0,class:"call-record-toolbar"},H={class:"call-record-empty"},J={class:"call-record-empty__desc"},Q={key:0,class:"text-primary"},W={key:1,class:"text-gray-400"},X=N({__name:"CallRecordPanel",props:{diagnosisId:{},readOnly:{type:Boolean,default:!1}},setup(_,{expose:R}){const r=_,p=v(!1),g=v([]),U=O("toolbarUploadRef"),m=async()=>{if(r.diagnosisId){p.value=!0;try{g.value=await K({diagnosis_id:r.diagnosisId})||[]}catch(e){console.error(e),g.value=[]}finally{p.value=!1}}};P(()=>r.diagnosisId,()=>{m()},{immediate:!0}),R({refresh:m});function C(e){return{1:"进行中",2:"已结束",3:"未接听",4:"已取消"}[e]??"—"}async function S(e){const t=b(e);if(!t){c.msgError("上传成功但未返回视频地址");return}try{const a=await A({diagnosis_id:r.diagnosisId});await x({diagnosis_id:r.diagnosisId,call_record_id:Number((a==null?void 0:a.id)||0),file_url:t}),c.msgSuccess("视频回放上传成功"),await m()}catch(a){c.msgError((a==null?void 0:a.message)||"写入回放失败")}}async function E(e,t){const a=b(t);if(!a){c.msgError("上传成功但未返回视频地址");return}try{await x({diagnosis_id:r.diagnosisId,call_record_id:Number(e.id||0),file_url:a}),c.msgSuccess("视频回放上传成功"),await m()}catch(l){c.msgError((l==null?void 0:l.message)||"写入回放失败")}}function b(e){var t,a;return String(((t=e==null?void 0:e.data)==null?void 0:t.uri)||((a=e==null?void 0:e.data)==null?void 0:a.url)||"").trim()}return(e,t)=>{const a=V,l=z,I=L,B=M;return d(),f("div",F,[_.readOnly?h("",!0):(d(),f("div",G,[o(k,{ref_key:"toolbarUploadRef",ref:U,type:"video",direct:"",multiple:!1,limit:1,"show-progress":!0,onSuccess:S},{default:i(()=>[o(a,{type:"primary"},{default:i(()=>[...t[0]||(t[0]=[n("上传视频",-1)])]),_:1})]),_:1},512)])),D((d(),w(I,{data:g.value,border:"",stripe:""},{empty:i(()=>[y("div",H,[t[1]||(t[1]=y("div",{class:"call-record-empty__title"},"暂无通话记录",-1)),y("div",J,u(_.readOnly?"暂无录制回放数据。":"现在可以直接点击上方“上传视频”。系统会自动生成一条默认通话记录来承载回放。"),1)])]),default:i(()=>[o(l,{label:"录制回放","min-width":"320"},{default:i(({row:s})=>[o(j,{"record-id":s.id,urls:s.recording_urls_list},null,8,["record-id","urls"])]),_:1}),o(l,{label:"开始时间",width:"170",prop:"start_time_text"}),o(l,{label:"结束时间",width:"170",prop:"end_time_text"}),o(l,{label:"通话类型",width:"100"},{default:i(({row:s})=>[n(u(s.call_type===1?"语音":"视频"),1)]),_:1}),o(l,{label:"房间号",width:"180"},{default:i(({row:s})=>[s.room_id?(d(),f("span",Q,u(s.room_id),1)):(d(),f("span",W,"—"))]),_:1}),o(l,{label:"时长",width:"110",prop:"duration_text"}),o(l,{label:"状态",width:"90"},{default:i(({row:s})=>[n(u(C(s.status)),1)]),_:1}),o(l,{label:"录制",width:"100"},{default:i(({row:s})=>[n(u(s.recording_status_text||"—"),1)]),_:1}),_.readOnly?h("",!0):(d(),w(l,{key:0,label:"上传回放",width:"180"},{default:i(({row:s})=>[o(k,{type:"video",direct:"",multiple:!1,limit:1,"show-progress":!0,onSuccess:T=>E(s,T)},{default:i(()=>[o(a,{type:"primary",plain:"",size:"small"},{default:i(()=>[...t[2]||(t[2]=[n("上传视频",-1)])]),_:1})]),_:1},8,["onSuccess"])]),_:1}))]),_:1},8,["data"])),[[B,p.value]])])}}}),sa=q(X,[["__scopeId","data-v-78d5c9e4"]]);export{sa as default};
|
import{o as N,dk as O,R as P,q as d,r as f,v as o,D as i,K as V,L as n,P as h,ac as D,O as w,bj as L,bk as z,T as u,s as y,bi as M,M as v}from"./.pnpm-BSw4l71J.js";import j from"./RecordingPlaybackBlock-BKFzFdQZ.js";import{U as k}from"./index-D9144h_t.js";import{i as c,_ as q}from"./index-CQbHw_bK.js";import{ak as K,al as x,am as A}from"./tcm-PbOYp3fC.js";import"./RecordingVideoPlayer-CaeLNO_q.js";import"./file-zu5s28di.js";const F={class:"call-record-panel"},G={key:0,class:"call-record-toolbar"},H={class:"call-record-empty"},J={class:"call-record-empty__desc"},Q={key:0,class:"text-primary"},W={key:1,class:"text-gray-400"},X=N({__name:"CallRecordPanel",props:{diagnosisId:{},readOnly:{type:Boolean,default:!1}},setup(_,{expose:R}){const r=_,p=v(!1),g=v([]),U=O("toolbarUploadRef"),m=async()=>{if(r.diagnosisId){p.value=!0;try{g.value=await K({diagnosis_id:r.diagnosisId})||[]}catch(e){console.error(e),g.value=[]}finally{p.value=!1}}};P(()=>r.diagnosisId,()=>{m()},{immediate:!0}),R({refresh:m});function C(e){return{1:"进行中",2:"已结束",3:"未接听",4:"已取消"}[e]??"—"}async function S(e){const t=b(e);if(!t){c.msgError("上传成功但未返回视频地址");return}try{const a=await A({diagnosis_id:r.diagnosisId});await x({diagnosis_id:r.diagnosisId,call_record_id:Number((a==null?void 0:a.id)||0),file_url:t}),c.msgSuccess("视频回放上传成功"),await m()}catch(a){c.msgError((a==null?void 0:a.message)||"写入回放失败")}}async function E(e,t){const a=b(t);if(!a){c.msgError("上传成功但未返回视频地址");return}try{await x({diagnosis_id:r.diagnosisId,call_record_id:Number(e.id||0),file_url:a}),c.msgSuccess("视频回放上传成功"),await m()}catch(l){c.msgError((l==null?void 0:l.message)||"写入回放失败")}}function b(e){var t,a;return String(((t=e==null?void 0:e.data)==null?void 0:t.uri)||((a=e==null?void 0:e.data)==null?void 0:a.url)||"").trim()}return(e,t)=>{const a=V,l=z,I=L,B=M;return d(),f("div",F,[_.readOnly?h("",!0):(d(),f("div",G,[o(k,{ref_key:"toolbarUploadRef",ref:U,type:"video",direct:"",multiple:!1,limit:1,"show-progress":!0,onSuccess:S},{default:i(()=>[o(a,{type:"primary"},{default:i(()=>[...t[0]||(t[0]=[n("上传视频",-1)])]),_:1})]),_:1},512)])),D((d(),w(I,{data:g.value,border:"",stripe:""},{empty:i(()=>[y("div",H,[t[1]||(t[1]=y("div",{class:"call-record-empty__title"},"暂无通话记录",-1)),y("div",J,u(_.readOnly?"暂无录制回放数据。":"现在可以直接点击上方“上传视频”。系统会自动生成一条默认通话记录来承载回放。"),1)])]),default:i(()=>[o(l,{label:"录制回放","min-width":"320"},{default:i(({row:s})=>[o(j,{"record-id":s.id,urls:s.recording_urls_list},null,8,["record-id","urls"])]),_:1}),o(l,{label:"开始时间",width:"170",prop:"start_time_text"}),o(l,{label:"结束时间",width:"170",prop:"end_time_text"}),o(l,{label:"通话类型",width:"100"},{default:i(({row:s})=>[n(u(s.call_type===1?"语音":"视频"),1)]),_:1}),o(l,{label:"房间号",width:"180"},{default:i(({row:s})=>[s.room_id?(d(),f("span",Q,u(s.room_id),1)):(d(),f("span",W,"—"))]),_:1}),o(l,{label:"时长",width:"110",prop:"duration_text"}),o(l,{label:"状态",width:"90"},{default:i(({row:s})=>[n(u(C(s.status)),1)]),_:1}),o(l,{label:"录制",width:"100"},{default:i(({row:s})=>[n(u(s.recording_status_text||"—"),1)]),_:1}),_.readOnly?h("",!0):(d(),w(l,{key:0,label:"上传回放",width:"180"},{default:i(({row:s})=>[o(k,{type:"video",direct:"",multiple:!1,limit:1,"show-progress":!0,onSuccess:T=>E(s,T)},{default:i(()=>[o(a,{type:"primary",plain:"",size:"small"},{default:i(()=>[...t[2]||(t[2]=[n("上传视频",-1)])]),_:1})]),_:1},8,["onSuccess"])]),_:1}))]),_:1},8,["data"])),[[B,p.value]])])}}}),sa=q(X,[["__scopeId","data-v-78d5c9e4"]]);export{sa as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as T,ap as V,R as I,q as o,r as l,v as a,K as N,D as i,L as c,P as k,ac as z,bi as M,u as p,O as f,bk as O,T as _,F as P,br as j,s as F,bj as R,bB as A,M as w}from"./.pnpm-BSw4l71J.js";import{an as q}from"./tcm-Bv_Ly0A0.js";import{_ as H}from"./index-BWlhxa68.js";const K={class:"case-record-list"},Y={key:0,class:"mb-3 flex justify-end"},G={key:0},J={key:1,class:"text-gray-400"},Q={class:"void-detail text-xs text-gray-500 mt-1"},U=T({__name:"CaseRecordList",props:{diagnosisId:{type:Number,default:0},readOnly:{type:Boolean,default:!1}},emits:["view","openPrescription"],setup(y,{expose:x,emit:C}){const m=y,b=C,r=w([]),d=w(!1),u=async()=>{if(m.diagnosisId){d.value=!0;try{const t=await q({diagnosis_id:m.diagnosisId});r.value=Array.isArray(t)?t:[]}catch(t){console.error("获取病历记录失败:",t),r.value=[]}finally{d.value=!1}}},S=t=>{if(!t)return"";const e=new Date(t*1e3);return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")} ${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},B=t=>{b("view",t)},$=()=>{b("openPrescription")};return V(()=>{u()}),I(()=>m.diagnosisId,()=>{u()}),x({refresh:u}),(t,e)=>{const h=N,n=O,v=j,E=R,D=A,L=M;return o(),l("div",K,[y.readOnly?k("",!0):(o(),l("div",Y,[a(h,{type:"primary",size:"small",onClick:$},{default:i(()=>[...e[0]||(e[0]=[c("开方",-1)])]),_:1})])),z((o(),f(E,{data:p(r),border:""},{default:i(()=>[a(n,{prop:"prescription_date",label:"就诊日期",width:"120"}),a(n,{prop:"visit_no",label:"门诊号",width:"120"}),a(n,{prop:"clinical_diagnosis",label:"临床诊断","min-width":"160","show-overflow-tooltip":""}),a(n,{label:"处方摘要","min-width":"180"},{default:i(({row:s})=>[s.herbs&&s.herbs.length?(o(),l("span",G,_(s.herbs.slice(0,3).map(g=>`${g.name}${g.dosage}克`).join("、"))+_(s.herbs.length>3?"...":""),1)):(o(),l("span",J,"—"))]),_:1}),a(n,{prop:"doctor_name",label:"医师",width:"90","show-overflow-tooltip":""}),a(n,{label:"状态",width:"140",align:"center"},{default:i(({row:s})=>[s.void_status===1?(o(),l(P,{key:0},[a(v,{type:"danger",size:"small"},{default:i(()=>[...e[1]||(e[1]=[c("已作废",-1)])]),_:1}),F("div",Q,_(s.void_by_name||"—")+" "+_(S(s.void_time)),1)],64)):(o(),f(v,{key:1,type:"success",size:"small"},{default:i(()=>[...e[2]||(e[2]=[c("正常",-1)])]),_:1}))]),_:1}),a(n,{label:"操作",width:"120",fixed:"right"},{default:i(({row:s})=>[a(h,{link:"",type:"primary",size:"small",onClick:g=>B(s)},{default:i(()=>[...e[3]||(e[3]=[c(" 查看 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[L,p(d)]]),!p(d)&&p(r).length===0?(o(),f(D,{key:1,description:"暂无病历记录,开方后会自动显示",class:"mt-4"})):k("",!0)])}}}),ee=H(U,[["__scopeId","data-v-043d2738"]]);export{ee as default};
|
import{o as T,ap as V,R as I,q as o,r as l,v as a,K as N,D as i,L as c,P as k,ac as z,bi as M,u as p,O as f,bk as O,T as _,F as P,br as j,s as F,bj as R,bB as A,M as w}from"./.pnpm-BSw4l71J.js";import{an as q}from"./tcm-PbOYp3fC.js";import{_ as H}from"./index-CQbHw_bK.js";const K={class:"case-record-list"},Y={key:0,class:"mb-3 flex justify-end"},G={key:0},J={key:1,class:"text-gray-400"},Q={class:"void-detail text-xs text-gray-500 mt-1"},U=T({__name:"CaseRecordList",props:{diagnosisId:{type:Number,default:0},readOnly:{type:Boolean,default:!1}},emits:["view","openPrescription"],setup(y,{expose:x,emit:C}){const m=y,b=C,r=w([]),d=w(!1),u=async()=>{if(m.diagnosisId){d.value=!0;try{const t=await q({diagnosis_id:m.diagnosisId});r.value=Array.isArray(t)?t:[]}catch(t){console.error("获取病历记录失败:",t),r.value=[]}finally{d.value=!1}}},S=t=>{if(!t)return"";const e=new Date(t*1e3);return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")} ${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`},B=t=>{b("view",t)},$=()=>{b("openPrescription")};return V(()=>{u()}),I(()=>m.diagnosisId,()=>{u()}),x({refresh:u}),(t,e)=>{const h=N,n=O,v=j,E=R,D=A,L=M;return o(),l("div",K,[y.readOnly?k("",!0):(o(),l("div",Y,[a(h,{type:"primary",size:"small",onClick:$},{default:i(()=>[...e[0]||(e[0]=[c("开方",-1)])]),_:1})])),z((o(),f(E,{data:p(r),border:""},{default:i(()=>[a(n,{prop:"prescription_date",label:"就诊日期",width:"120"}),a(n,{prop:"visit_no",label:"门诊号",width:"120"}),a(n,{prop:"clinical_diagnosis",label:"临床诊断","min-width":"160","show-overflow-tooltip":""}),a(n,{label:"处方摘要","min-width":"180"},{default:i(({row:s})=>[s.herbs&&s.herbs.length?(o(),l("span",G,_(s.herbs.slice(0,3).map(g=>`${g.name}${g.dosage}克`).join("、"))+_(s.herbs.length>3?"...":""),1)):(o(),l("span",J,"—"))]),_:1}),a(n,{prop:"doctor_name",label:"医师",width:"90","show-overflow-tooltip":""}),a(n,{label:"状态",width:"140",align:"center"},{default:i(({row:s})=>[s.void_status===1?(o(),l(P,{key:0},[a(v,{type:"danger",size:"small"},{default:i(()=>[...e[1]||(e[1]=[c("已作废",-1)])]),_:1}),F("div",Q,_(s.void_by_name||"—")+" "+_(S(s.void_time)),1)],64)):(o(),f(v,{key:1,type:"success",size:"small"},{default:i(()=>[...e[2]||(e[2]=[c("正常",-1)])]),_:1}))]),_:1}),a(n,{label:"操作",width:"120",fixed:"right"},{default:i(({row:s})=>[a(h,{link:"",type:"primary",size:"small",onClick:g=>B(s)},{default:i(()=>[...e[3]||(e[3]=[c(" 查看 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[L,p(d)]]),!p(d)&&p(r).length===0?(o(),f(D,{key:1,description:"暂无病历记录,开方后会自动显示",class:"mt-4"})):k("",!0)])}}}),ee=H(U,[["__scopeId","data-v-043d2738"]]);export{ee as default};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
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-BE5Dm2tJ.js";import"./.pnpm-BSw4l71J.js";import"./tcm-PbOYp3fC.js";import"./index-CQbHw_bK.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./GancaoSubmissionReconcileButton.vue_vue_type_script_setup_true_lang-Dkug3Ge4.js";import"./.pnpm-BSw4l71J.js";import"./tcm-Bv_Ly0A0.js";import"./index-BWlhxa68.js";export{o as default};
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as U,be as F,q as f,r as k,F as M,ac as D,O as E,D as t,L as u,K as G,v as r,bt as B,bh as q,b9 as P,aw as A,b6 as L,bc as T,bf as K,b7 as z,P as g,p as W,M as v,ba as $}from"./.pnpm-BSw4l71J.js";import{p as j}from"./tcm-Bv_Ly0A0.js";import{i as C}from"./index-BWlhxa68.js";const X=U({__name:"GancaoSubmissionReconcileButton",props:{order:{}},emits:["resolved"],setup(N,{emit:w}){const d=N,y=w,V=W(()=>{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=v(!1),_=v(!1),o=$({resolution:"CONFIRM_SUCCESS",remote_order_no:"",note:""});function O(){o.resolution="CONFIRM_SUCCESS",o.remote_order_no="",o.note="",s.value=!0}async function b(){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()){C.msgError("请填写甘草药方单号");return}if(!o.note.trim()){C.msgError("请填写甘草后台核对依据");return}_.value=!0;try{await j({id:i,resolution:o.resolution,remote_order_no:o.resolution==="CONFIRM_SUCCESS"?o.remote_order_no.trim():"",note:o.note.trim()}),C.msgSuccess("甘草提交核对已记录"),s.value=!1,y("resolved")}catch{}finally{_.value=!1}}}return(i,e)=>{const n=G,c=q,m=K,p=T,a=L,S=z,R=P,x=B,I=F("perms");return V.value?(f(),k(M,{key:0},[D((f(),E(n,{type:"danger",size:"small",plain:"",onClick:O},{default:t(()=>[...e[5]||(e[5]=[u("核对甘草提交",-1)])]),_:1})),[[I,["tcm.prescriptionOrder/confirmGancaoSubmission"]]]),r(x,{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:b},{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(R,{"label-width":"100px",onSubmit:A(b,["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"?(f(),E(a,{key:0,label:"甘草单号",required:""},{default:t(()=>[r(S,{modelValue:o.remote_order_no,"onUpdate:modelValue":e[1]||(e[1]=l=>o.remote_order_no=l),maxlength:"64",clearable:""},null,8,["modelValue"])]),_:1})):g("",!0),r(a,{label:"核对依据",required:""},{default:t(()=>[r(S,{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)):g("",!0)}}});export{X as _};
|
import{o as U,be as F,q as f,r as k,F as M,ac as D,O as E,D as t,L as u,K as G,v as r,bt as B,bh as q,b9 as P,aw as A,b6 as L,bc as T,bf as K,b7 as z,P as g,p as W,M as v,ba as $}from"./.pnpm-BSw4l71J.js";import{p as j}from"./tcm-PbOYp3fC.js";import{i as C}from"./index-CQbHw_bK.js";const X=U({__name:"GancaoSubmissionReconcileButton",props:{order:{}},emits:["resolved"],setup(N,{emit:w}){const d=N,y=w,V=W(()=>{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=v(!1),_=v(!1),o=$({resolution:"CONFIRM_SUCCESS",remote_order_no:"",note:""});function O(){o.resolution="CONFIRM_SUCCESS",o.remote_order_no="",o.note="",s.value=!0}async function b(){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()){C.msgError("请填写甘草药方单号");return}if(!o.note.trim()){C.msgError("请填写甘草后台核对依据");return}_.value=!0;try{await j({id:i,resolution:o.resolution,remote_order_no:o.resolution==="CONFIRM_SUCCESS"?o.remote_order_no.trim():"",note:o.note.trim()}),C.msgSuccess("甘草提交核对已记录"),s.value=!1,y("resolved")}catch{}finally{_.value=!1}}}return(i,e)=>{const n=G,c=q,m=K,p=T,a=L,S=z,R=P,x=B,I=F("perms");return V.value?(f(),k(M,{key:0},[D((f(),E(n,{type:"danger",size:"small",plain:"",onClick:O},{default:t(()=>[...e[5]||(e[5]=[u("核对甘草提交",-1)])]),_:1})),[[I,["tcm.prescriptionOrder/confirmGancaoSubmission"]]]),r(x,{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:b},{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(R,{"label-width":"100px",onSubmit:A(b,["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"?(f(),E(a,{key:0,label:"甘草单号",required:""},{default:t(()=>[r(S,{modelValue:o.remote_order_no,"onUpdate:modelValue":e[1]||(e[1]=l=>o.remote_order_no=l),maxlength:"64",clearable:""},null,8,["modelValue"])]),_:1})):g("",!0),r(a,{label:"核对依据",required:""},{default:t(()=>[r(S,{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)):g("",!0)}}});export{X as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as F,R as q,q as t,r as n,v as i,D as c,s as o,L as _,bh as G,w as H,u as x,cX as $,K as j,by as J,ac as K,F as E,G as O,O as f,bB as W,P as v,bi as X,M as m,p as Q,ae as U,T as r,br as Z,aa as ee,bq as se,a8 as ae,E as C}from"./.pnpm-BSw4l71J.js";import{d as te}from"./dayjs-CVa8MSSA.js";import{as as ne,at as oe}from"./tcm-Bv_Ly0A0.js";import{p as re}from"./im-business-message-parse-oYIP1khU.js";import{_ as le}from"./index-BWlhxa68.js";const ie={class:"im-chat-record-panel"},ce={class:"toolbar mb-3"},de={class:"chat-wrap"},_e={key:0,class:"chat-list"},ue={class:"meta"},fe={class:"name"},me={class:"time"},pe={class:"bubble"},ye={key:0,class:"friendly-text"},ge={class:"friendly-main"},ve={key:0,class:"friendly-sub"},he={key:1,class:"text-content"},we={key:2,class:"text-content"},be={key:3,class:"muted"},ke=F({__name:"ImChatRecordPanel",props:{diagnosisId:{}},setup(B,{expose:M}){const u=B,d=m(!1),p=m(!1),y=ae([]),L=m(""),g=m(""),D={text:"",image:"图片",file:"文件",sound:"语音",video:"视频",location:"位置",custom:"自定义",face:"表情",other:""},h=Q(()=>y.value.map(e=>{const a=P(e);let l="";return a!=null&&a.tag?l=a.tag:l=D[e.msg_type]||(e.msg_type!=="other"?e.msg_type:""),{raw:e,friendly:a,tag:l}}));function N(e){if(e==null||!e)return"—";const a=e>1e12?Math.floor(e/1e3):e;return te.unix(a).format("YYYY-MM-DD HH:mm:ss")}function P(e){const a=(e.text||"").trim();if(!a)return null;const l=a.startsWith("{")&&(/\bbusinessID\b/.test(a)||/\bcmd\b/.test(a));return e.msg_type==="custom"||l?re(a):null}function R(e){return e.is_from_doctor?e.from_staff_name?`医生(${e.from_staff_name})`:"医生/员工":g.value?`患者(${g.value})`:"患者"}async function w(){if(u.diagnosisId){d.value=!0;try{const e=await ne({diagnosis_id:u.diagnosisId,only_archived:1});y.value=(e==null?void 0:e.lists)||[],L.value=(e==null?void 0:e.patient_im_id)||"",g.value=(e==null?void 0:e.patient_name)||""}catch(e){console.error(e),y.value=[]}finally{d.value=!1}}}function b(){w()}async function S(){if(u.diagnosisId){p.value=!0;try{await oe({diagnosis_id:u.diagnosisId}),C.success('已发起后台同步,几秒后请点击"重新加载已归档"查看新消息')}catch(e){console.error(e),C.error("发起同步失败")}finally{p.value=!1}}}return q(()=>u.diagnosisId,()=>{w()},{immediate:!0}),M({refresh:b}),(e,a)=>{const l=G,k=H,I=j,T=Z,Y=ee,V=se,z=W,A=X;return t(),n("div",ie,[i(l,{type:"info","show-icon":"",closable:!1,class:"mb-4",title:"说明"},{default:c(()=>[...a[0]||(a[0]=[o("p",{class:"panel-tip"},[_(" 展示单聊记录:已合并患者 与 "),o("strong",null,"所有医生 / 医助账号"),_("分别产生的会话,按时间排序。 数据由后台定时任务从腾讯云 IM 漫游消息同步至本地归档;点击下方按钮可立即触发后台同步。 ")],-1)])]),_:1}),o("div",ce,[i(I,{type:"primary",link:"",loading:p.value,onClick:S},{default:c(()=>[i(k,{class:"mr-1"},{default:c(()=>[i(x($))]),_:1}),a[1]||(a[1]=_(" 同步最新(后台异步) ",-1))]),_:1},8,["loading"]),i(I,{type:"primary",link:"",loading:d.value,onClick:b},{default:c(()=>[i(k,{class:"mr-1"},{default:c(()=>[i(x(J))]),_:1}),a[2]||(a[2]=_(" 重新加载已归档 ",-1))]),_:1},8,["loading"])]),K((t(),n("div",de,[!d.value&&h.value.length?(t(),n("div",_e,[(t(!0),n(E,null,O(h.value,s=>(t(),n("div",{key:s.raw.msg_id,class:U(["chat-row",s.raw.is_from_doctor?"from-doctor":"from-patient"])},[o("div",ue,[o("span",fe,r(R(s.raw)),1),o("span",me,r(N(s.raw.time)),1),s.tag?(t(),f(T,{key:0,size:"small",type:"info",class:"ml-2"},{default:c(()=>[_(r(s.tag),1)]),_:2},1024)):v("",!0)]),o("div",pe,[s.raw.msg_type==="image"&&s.raw.image_url?(t(),f(Y,{key:0,src:s.raw.image_url,"preview-src-list":[s.raw.image_url],fit:"contain",class:"chat-img"},null,8,["src","preview-src-list"])):(s.raw.msg_type==="file"||s.raw.msg_type==="sound"||s.raw.msg_type==="video")&&s.raw.file_url?(t(),f(V,{key:1,href:s.raw.file_url,target:"_blank",type:"primary"},{default:c(()=>[_(r(s.raw.file_name||"打开文件"),1)]),_:2},1032,["href"])):(t(),n(E,{key:2},[s.friendly?(t(),n("div",ye,[o("div",ge,r(s.friendly.main),1),s.friendly.sub?(t(),n("div",ve,r(s.friendly.sub),1)):v("",!0)])):s.raw.msg_type==="text"&&s.raw.text?(t(),n("div",he,r(s.raw.text),1)):s.raw.text?(t(),n("div",we,r(s.raw.text),1)):(t(),n("span",be,"(无法展示该消息类型)"))],64))])],2))),128))])):d.value?v("",!0):(t(),f(z,{key:1,description:"暂无 IM 聊天记录"}))])),[[A,d.value]])])}}}),Me=le(ke,[["__scopeId","data-v-58b699dd"]]);export{Me as default};
|
import{o as F,R as q,q as t,r as n,v as i,D as c,s as o,L as _,bh as G,w as H,u as x,cX as $,K as j,by as J,ac as K,F as E,G as O,O as f,bB as W,P as v,bi as X,M as m,p as Q,ae as U,T as r,br as Z,aa as ee,bq as se,a8 as ae,E as C}from"./.pnpm-BSw4l71J.js";import{d as te}from"./dayjs-CVa8MSSA.js";import{as as ne,at as oe}from"./tcm-PbOYp3fC.js";import{p as re}from"./im-business-message-parse-oYIP1khU.js";import{_ as le}from"./index-CQbHw_bK.js";const ie={class:"im-chat-record-panel"},ce={class:"toolbar mb-3"},de={class:"chat-wrap"},_e={key:0,class:"chat-list"},ue={class:"meta"},fe={class:"name"},me={class:"time"},pe={class:"bubble"},ye={key:0,class:"friendly-text"},ge={class:"friendly-main"},ve={key:0,class:"friendly-sub"},he={key:1,class:"text-content"},we={key:2,class:"text-content"},be={key:3,class:"muted"},ke=F({__name:"ImChatRecordPanel",props:{diagnosisId:{}},setup(B,{expose:M}){const u=B,d=m(!1),p=m(!1),y=ae([]),L=m(""),g=m(""),D={text:"",image:"图片",file:"文件",sound:"语音",video:"视频",location:"位置",custom:"自定义",face:"表情",other:""},h=Q(()=>y.value.map(e=>{const a=P(e);let l="";return a!=null&&a.tag?l=a.tag:l=D[e.msg_type]||(e.msg_type!=="other"?e.msg_type:""),{raw:e,friendly:a,tag:l}}));function N(e){if(e==null||!e)return"—";const a=e>1e12?Math.floor(e/1e3):e;return te.unix(a).format("YYYY-MM-DD HH:mm:ss")}function P(e){const a=(e.text||"").trim();if(!a)return null;const l=a.startsWith("{")&&(/\bbusinessID\b/.test(a)||/\bcmd\b/.test(a));return e.msg_type==="custom"||l?re(a):null}function R(e){return e.is_from_doctor?e.from_staff_name?`医生(${e.from_staff_name})`:"医生/员工":g.value?`患者(${g.value})`:"患者"}async function w(){if(u.diagnosisId){d.value=!0;try{const e=await ne({diagnosis_id:u.diagnosisId,only_archived:1});y.value=(e==null?void 0:e.lists)||[],L.value=(e==null?void 0:e.patient_im_id)||"",g.value=(e==null?void 0:e.patient_name)||""}catch(e){console.error(e),y.value=[]}finally{d.value=!1}}}function b(){w()}async function S(){if(u.diagnosisId){p.value=!0;try{await oe({diagnosis_id:u.diagnosisId}),C.success('已发起后台同步,几秒后请点击"重新加载已归档"查看新消息')}catch(e){console.error(e),C.error("发起同步失败")}finally{p.value=!1}}}return q(()=>u.diagnosisId,()=>{w()},{immediate:!0}),M({refresh:b}),(e,a)=>{const l=G,k=H,I=j,T=Z,Y=ee,V=se,z=W,A=X;return t(),n("div",ie,[i(l,{type:"info","show-icon":"",closable:!1,class:"mb-4",title:"说明"},{default:c(()=>[...a[0]||(a[0]=[o("p",{class:"panel-tip"},[_(" 展示单聊记录:已合并患者 与 "),o("strong",null,"所有医生 / 医助账号"),_("分别产生的会话,按时间排序。 数据由后台定时任务从腾讯云 IM 漫游消息同步至本地归档;点击下方按钮可立即触发后台同步。 ")],-1)])]),_:1}),o("div",ce,[i(I,{type:"primary",link:"",loading:p.value,onClick:S},{default:c(()=>[i(k,{class:"mr-1"},{default:c(()=>[i(x($))]),_:1}),a[1]||(a[1]=_(" 同步最新(后台异步) ",-1))]),_:1},8,["loading"]),i(I,{type:"primary",link:"",loading:d.value,onClick:b},{default:c(()=>[i(k,{class:"mr-1"},{default:c(()=>[i(x(J))]),_:1}),a[2]||(a[2]=_(" 重新加载已归档 ",-1))]),_:1},8,["loading"])]),K((t(),n("div",de,[!d.value&&h.value.length?(t(),n("div",_e,[(t(!0),n(E,null,O(h.value,s=>(t(),n("div",{key:s.raw.msg_id,class:U(["chat-row",s.raw.is_from_doctor?"from-doctor":"from-patient"])},[o("div",ue,[o("span",fe,r(R(s.raw)),1),o("span",me,r(N(s.raw.time)),1),s.tag?(t(),f(T,{key:0,size:"small",type:"info",class:"ml-2"},{default:c(()=>[_(r(s.tag),1)]),_:2},1024)):v("",!0)]),o("div",pe,[s.raw.msg_type==="image"&&s.raw.image_url?(t(),f(Y,{key:0,src:s.raw.image_url,"preview-src-list":[s.raw.image_url],fit:"contain",class:"chat-img"},null,8,["src","preview-src-list"])):(s.raw.msg_type==="file"||s.raw.msg_type==="sound"||s.raw.msg_type==="video")&&s.raw.file_url?(t(),f(V,{key:1,href:s.raw.file_url,target:"_blank",type:"primary"},{default:c(()=>[_(r(s.raw.file_name||"打开文件"),1)]),_:2},1032,["href"])):(t(),n(E,{key:2},[s.friendly?(t(),n("div",ye,[o("div",ge,r(s.friendly.main),1),s.friendly.sub?(t(),n("div",ve,r(s.friendly.sub),1)):v("",!0)])):s.raw.msg_type==="text"&&s.raw.text?(t(),n("div",he,r(s.raw.text),1)):s.raw.text?(t(),n("div",we,r(s.raw.text),1)):(t(),n("span",be,"(无法展示该消息类型)"))],64))])],2))),128))])):d.value?v("",!0):(t(),f(z,{key:1,description:"暂无 IM 聊天记录"}))])),[[A,d.value]])])}}}),Me=le(ke,[["__scopeId","data-v-58b699dd"]]);export{Me as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as S,q as a,r as l,ae as x,v as r,D as m,L as d,T as i,a0 as D,s as n,O as g,br as G,P as B,aa as K,u as v,bE as L,w as q,bF as A,bG as H,bH as O,F as P,K as U,p as u}from"./.pnpm-BSw4l71J.js";import{t as j,_ as J}from"./index-BWlhxa68.js";const Q={class:"msg-body"},R={class:"msg-meta"},W={class:"msg-sender"},X={class:"msg-time"},Y={key:0,class:"content-text"},Z={key:2,class:"content-pending"},ee=["src"],se={key:4,class:"content-pending"},te=["src"],ae={key:6,class:"content-pending"},ne={key:7,class:"content-file"},le={class:"file-meta"},ie=["title"],oe={class:"file-info"},ce={key:8,class:"content-fallback"},re={class:"fallback-title"},me={class:"fallback-desc"},ue=S({__name:"MessageBubble",props:{message:{}},setup(s){const o=s,w=u(()=>o.message.from_is_staff),c=u(()=>(o.message.media||[]).find(t=>t.status===1)??null),_=u(()=>{const e=o.message.from_profile;return e&&e.name||o.message.from_user}),z=u(()=>{const e=o.message.from_profile;return(e==null?void 0:e.avatar)||""}),F=u(()=>(_.value||"").slice(-2)||"?"),E=u(()=>{const e=o.message.msgtype;return e==="image"||e==="video"||e==="voice"?"bubble-media":e==="file"?"bubble-file":"bubble-text"}),C=u(()=>{switch(o.message.msgtype){case"link":return"[链接]";case"weapp":return"[小程序]";case"chatrecord":return"[聊天记录]";case"location":return"[位置]";case"card":return"[名片]";case"meeting":return"[会议]";case"docmsg":return"[文档]";case"mixed":return"[混合消息]";case"emotion":return"[表情]";default:return`[${o.message.msgtype}]`}});function M(e){return e?j(e*1e3,"mm-dd hh:MM"):""}function N(e){return e?e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/1024/1024).toFixed(2)} MB`:`${(e/1024/1024/1024).toFixed(2)} GB`:""}function $(e){window.open(e,"_blank","noopener")}return(e,t)=>{var k,y,p,h;const T=D,b=G,V=K,f=q,I=U;return a(),l("div",{class:x(["msg-bubble",{"is-staff":w.value}])},[r(T,{class:"msg-avatar",size:36,src:z.value},{default:m(()=>[d(i(F.value),1)]),_:1},8,["src"]),n("div",Q,[n("div",R,[n("span",W,i(_.value),1),n("span",X,i(M(s.message.send_time)),1),s.message.action==="recall"?(a(),g(b,{key:0,size:"small",type:"info"},{default:m(()=>[...t[1]||(t[1]=[d(" 已撤回 ",-1)])]),_:1})):B("",!0)]),n("div",{class:x(["msg-content",E.value])},[s.message.msgtype==="text"||s.message.msgtype==="markdown"?(a(),l("div",Y,i(s.message.content),1)):s.message.msgtype==="image"&&((k=c.value)!=null&&k.file_url)?(a(),g(V,{key:1,src:c.value.file_url,"preview-src-list":[c.value.file_url],fit:"contain",class:"content-image","hide-on-click-modal":""},null,8,["src","preview-src-list"])):s.message.msgtype==="image"?(a(),l("div",Z,[r(f,null,{default:m(()=>[r(v(L))]),_:1}),t[2]||(t[2]=n("span",null,"图片下载中…",-1))])):s.message.msgtype==="video"&&((y=c.value)!=null&&y.file_url)?(a(),l("video",{key:3,src:c.value.file_url,controls:"",class:"content-video"},null,8,ee)):s.message.msgtype==="video"?(a(),l("div",se,[r(f,null,{default:m(()=>[r(v(A))]),_:1}),t[3]||(t[3]=n("span",null,"视频下载中…",-1))])):s.message.msgtype==="voice"&&((p=c.value)!=null&&p.file_url)?(a(),l("audio",{key:5,src:c.value.file_url,controls:"",class:"content-audio"},null,8,te)):s.message.msgtype==="voice"?(a(),l("div",ae,[r(f,null,{default:m(()=>[r(v(H))]),_:1}),n("span",null,"语音下载中…("+i(s.message.play_length)+"s)",1)])):s.message.msgtype==="file"?(a(),l("div",ne,[r(f,{size:24},{default:m(()=>[r(v(O))]),_:1}),n("div",le,[n("div",{class:"file-name",title:s.message.file_name},i(s.message.file_name||"未命名文件"),9,ie),n("div",oe,[d(i(N(s.message.file_size))+" ",1),s.message.file_ext?(a(),l(P,{key:0},[d("· "+i(s.message.file_ext),1)],64)):B("",!0)])]),(h=c.value)!=null&&h.file_url?(a(),g(I,{key:0,size:"small",type:"primary",link:"",onClick:t[0]||(t[0]=de=>$(c.value.file_url))},{default:m(()=>[...t[4]||(t[4]=[d(" 下载 ",-1)])]),_:1})):(a(),g(b,{key:1,size:"small",type:"info"},{default:m(()=>[...t[5]||(t[5]=[d("下载中…",-1)])]),_:1}))])):(a(),l("div",ce,[n("div",re,i(C.value),1),n("div",me,i(s.message.content),1)]))],2)])],2)}}}),ve=J(ue,[["__scopeId","data-v-b5ff1168"]]);export{ve as default};
|
import{o as S,q as a,r as l,ae as x,v as r,D as m,L as d,T as i,a0 as D,s as n,O as g,br as G,P as B,aa as K,u as v,bE as L,w as q,bF as A,bG as H,bH as O,F as P,K as U,p as u}from"./.pnpm-BSw4l71J.js";import{t as j,_ as J}from"./index-CQbHw_bK.js";const Q={class:"msg-body"},R={class:"msg-meta"},W={class:"msg-sender"},X={class:"msg-time"},Y={key:0,class:"content-text"},Z={key:2,class:"content-pending"},ee=["src"],se={key:4,class:"content-pending"},te=["src"],ae={key:6,class:"content-pending"},ne={key:7,class:"content-file"},le={class:"file-meta"},ie=["title"],oe={class:"file-info"},ce={key:8,class:"content-fallback"},re={class:"fallback-title"},me={class:"fallback-desc"},ue=S({__name:"MessageBubble",props:{message:{}},setup(s){const o=s,w=u(()=>o.message.from_is_staff),c=u(()=>(o.message.media||[]).find(t=>t.status===1)??null),_=u(()=>{const e=o.message.from_profile;return e&&e.name||o.message.from_user}),z=u(()=>{const e=o.message.from_profile;return(e==null?void 0:e.avatar)||""}),F=u(()=>(_.value||"").slice(-2)||"?"),E=u(()=>{const e=o.message.msgtype;return e==="image"||e==="video"||e==="voice"?"bubble-media":e==="file"?"bubble-file":"bubble-text"}),C=u(()=>{switch(o.message.msgtype){case"link":return"[链接]";case"weapp":return"[小程序]";case"chatrecord":return"[聊天记录]";case"location":return"[位置]";case"card":return"[名片]";case"meeting":return"[会议]";case"docmsg":return"[文档]";case"mixed":return"[混合消息]";case"emotion":return"[表情]";default:return`[${o.message.msgtype}]`}});function M(e){return e?j(e*1e3,"mm-dd hh:MM"):""}function N(e){return e?e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/1024/1024).toFixed(2)} MB`:`${(e/1024/1024/1024).toFixed(2)} GB`:""}function $(e){window.open(e,"_blank","noopener")}return(e,t)=>{var k,y,p,h;const T=D,b=G,V=K,f=q,I=U;return a(),l("div",{class:x(["msg-bubble",{"is-staff":w.value}])},[r(T,{class:"msg-avatar",size:36,src:z.value},{default:m(()=>[d(i(F.value),1)]),_:1},8,["src"]),n("div",Q,[n("div",R,[n("span",W,i(_.value),1),n("span",X,i(M(s.message.send_time)),1),s.message.action==="recall"?(a(),g(b,{key:0,size:"small",type:"info"},{default:m(()=>[...t[1]||(t[1]=[d(" 已撤回 ",-1)])]),_:1})):B("",!0)]),n("div",{class:x(["msg-content",E.value])},[s.message.msgtype==="text"||s.message.msgtype==="markdown"?(a(),l("div",Y,i(s.message.content),1)):s.message.msgtype==="image"&&((k=c.value)!=null&&k.file_url)?(a(),g(V,{key:1,src:c.value.file_url,"preview-src-list":[c.value.file_url],fit:"contain",class:"content-image","hide-on-click-modal":""},null,8,["src","preview-src-list"])):s.message.msgtype==="image"?(a(),l("div",Z,[r(f,null,{default:m(()=>[r(v(L))]),_:1}),t[2]||(t[2]=n("span",null,"图片下载中…",-1))])):s.message.msgtype==="video"&&((y=c.value)!=null&&y.file_url)?(a(),l("video",{key:3,src:c.value.file_url,controls:"",class:"content-video"},null,8,ee)):s.message.msgtype==="video"?(a(),l("div",se,[r(f,null,{default:m(()=>[r(v(A))]),_:1}),t[3]||(t[3]=n("span",null,"视频下载中…",-1))])):s.message.msgtype==="voice"&&((p=c.value)!=null&&p.file_url)?(a(),l("audio",{key:5,src:c.value.file_url,controls:"",class:"content-audio"},null,8,te)):s.message.msgtype==="voice"?(a(),l("div",ae,[r(f,null,{default:m(()=>[r(v(H))]),_:1}),n("span",null,"语音下载中…("+i(s.message.play_length)+"s)",1)])):s.message.msgtype==="file"?(a(),l("div",ne,[r(f,{size:24},{default:m(()=>[r(v(O))]),_:1}),n("div",le,[n("div",{class:"file-name",title:s.message.file_name},i(s.message.file_name||"未命名文件"),9,ie),n("div",oe,[d(i(N(s.message.file_size))+" ",1),s.message.file_ext?(a(),l(P,{key:0},[d("· "+i(s.message.file_ext),1)],64)):B("",!0)])]),(h=c.value)!=null&&h.file_url?(a(),g(I,{key:0,size:"small",type:"primary",link:"",onClick:t[0]||(t[0]=de=>$(c.value.file_url))},{default:m(()=>[...t[4]||(t[4]=[d(" 下载 ",-1)])]),_:1})):(a(),g(b,{key:1,size:"small",type:"info"},{default:m(()=>[...t[5]||(t[5]=[d("下载中…",-1)])]),_:1}))])):(a(),l("div",ce,[n("div",re,i(C.value),1),n("div",me,i(s.message.content),1)]))],2)])],2)}}}),ve=J(ue,[["__scopeId","data-v-b5ff1168"]]);export{ve as default};
|
||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
import{o as ie,R as oe,q as n,r as o,O as k,K as le,D as r,L as P,P as m,v as l,s as d,F as w,G as E,bB as ae,b7 as re,bt as de,p as ue,M as g,T as U,aa as me,u as V,d9 as z,aw as M,w as ce,bH as pe,e as ge}from"./.pnpm-BSw4l71J.js";import{_ as fe}from"./picker-C_3iViNJ.js";import{e as ve,c as _e,i as f,_ as ye}from"./index-BWlhxa68.js";import{a as T,d as he}from"./patient-SnE6JXh9.js";import{h as ke}from"./perm-BdlAVcmi.js";import"./index-IBEgpZdk.js";import"./index-PArzJ7v1.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-Du0eYB29.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";const we={class:"note-timeline-wrap"},Ie={key:0,class:"timeline-actions"},Ce={class:"upload-trigger"},be={class:"upload-trigger"},xe={key:1,class:"note-timeline"},Ee={class:"timeline-date"},Ve={class:"timeline-body"},Ne={key:0,class:"timeline-content"},Se={key:1,class:"timeline-images"},De={key:2,class:"timeline-images"},Be={key:0,class:"thumb-wrap"},Ae={key:1,class:"file-wrap"},Pe=["href","title"],Ue={class:"file-name"},W=8e3,ze=ie({__name:"NoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(u,{emit:j}){const c=u,I=j,X=ue(()=>ke(["doctor.appointment/addDoctorNote"])),v=g(!1),C=g(""),N=g(!1),q=ve(),_=t=>q.getImageUrl(t),S=g([]),D=g([]),y=g(0),h=g(0),H=["jpg","jpeg","png","gif","bmp","webp","svg"],B=t=>{var i;const e=((i=t.split(".").pop())==null?void 0:i.toLowerCase().split("?")[0])||"";return H.includes(e)},$=t=>{var i;const e=t.split("/");return decodeURIComponent(((i=e[e.length-1])==null?void 0:i.split("?")[0])||"文件")},K=t=>t.filter(B).map(_),Z=(t,e)=>{const i=t.filter(B),b=t[e];return i.indexOf(b)},J=t=>t?t.split(`
|
import{o as ie,R as oe,q as n,r as o,O as k,K as le,D as r,L as P,P as m,v as l,s as d,F as w,G as E,bB as ae,b7 as re,bt as de,p as ue,M as g,T as U,aa as me,u as V,d9 as z,aw as M,w as ce,bH as pe,e as ge}from"./.pnpm-BSw4l71J.js";import{_ as fe}from"./picker-GVLgWOJW.js";import{e as ve,c as _e,i as f,_ as ye}from"./index-CQbHw_bK.js";import{a as T,d as he}from"./patient-WSqsUGD5.js";import{h as ke}from"./perm-BheQ0C8Z.js";import"./index-BHzpLgF4.js";import"./index-CvQxbz0R.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-D7nDUOel.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";const we={class:"note-timeline-wrap"},Ie={key:0,class:"timeline-actions"},Ce={class:"upload-trigger"},be={class:"upload-trigger"},xe={key:1,class:"note-timeline"},Ee={class:"timeline-date"},Ve={class:"timeline-body"},Ne={key:0,class:"timeline-content"},Se={key:1,class:"timeline-images"},De={key:2,class:"timeline-images"},Be={key:0,class:"thumb-wrap"},Ae={key:1,class:"file-wrap"},Pe=["href","title"],Ue={class:"file-name"},W=8e3,ze=ie({__name:"NoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(u,{emit:j}){const c=u,I=j,X=ue(()=>ke(["doctor.appointment/addDoctorNote"])),v=g(!1),C=g(""),N=g(!1),q=ve(),_=t=>q.getImageUrl(t),S=g([]),D=g([]),y=g(0),h=g(0),H=["jpg","jpeg","png","gif","bmp","webp","svg"],B=t=>{var i;const e=((i=t.split(".").pop())==null?void 0:i.toLowerCase().split("?")[0])||"";return H.includes(e)},$=t=>{var i;const e=t.split("/");return decodeURIComponent(((i=e[e.length-1])==null?void 0:i.split("?")[0])||"文件")},K=t=>t.filter(B).map(_),Z=(t,e)=>{const i=t.filter(B),b=t[e];return i.indexOf(b)},J=t=>t?t.split(`
|
||||||
`).filter(Boolean):[],Q=t=>{if(!c.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=y.value){y.value=e.length;return}const i=e.slice(y.value);y.value=e.length,i.length>0&&T({diagnosis_id:c.diagnosisId,tongue_images:i}).then(()=>{f.msgSuccess("舌苔照片已添加"),I("refresh")})},Y=t=>{if(!c.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=h.value){h.value=e.length;return}const i=e.slice(h.value);h.value=e.length,i.length>0&&T({diagnosis_id:c.diagnosisId,report_files:i}).then(()=>{f.msgSuccess("检查报告已添加"),I("refresh")})};oe(()=>c.notes,()=>{S.value=[],D.value=[],y.value=0,h.value=0});const ee=async()=>{if(!c.diagnosisId){f.msgWarning("当前无诊单,无法添加备注");return}const t=C.value.trim();if(!t){f.msgWarning("请输入备注内容");return}N.value=!0;try{await T({diagnosis_id:c.diagnosisId,content:t}),f.msgSuccess("备注保存成功"),C.value="",v.value=!1,I("refresh")}catch(e){f.msgError((e==null?void 0:e.message)||"保存失败")}finally{N.value=!1}},A=async(t,e,i)=>{try{await ge.confirm("确认删除?","提示",{type:"warning"})}catch{return}await he({note_id:t,image_type:e,image_path:i}),f.msgSuccess("已删除"),I("refresh")};return(t,e)=>{const i=le,b=_e,F=fe,L=me,x=ce,te=ae,se=re,ne=de;return n(),o("div",we,[!u.readonly&&u.diagnosisId?(n(),o("div",Ie,[X.value?(n(),k(i,{key:0,type:"primary",plain:"",size:"small",onClick:e[0]||(e[0]=s=>v.value=!0)},{default:r(()=>[...e[6]||(e[6]=[P(" 添加备注 ",-1)])]),_:1})):m("",!0),l(F,{modelValue:S.value,"onUpdate:modelValue":e[1]||(e[1]=s=>S.value=s),limit:99,type:"image","exclude-domain":!0,onChange:Q},{upload:r(()=>[d("div",Ce,[l(b,{size:20,name:"el-icon-Plus"}),e[7]||(e[7]=d("span",null,"舌苔照片",-1))])]),_:1},8,["modelValue"]),l(F,{modelValue:D.value,"onUpdate:modelValue":e[2]||(e[2]=s=>D.value=s),limit:99,type:"file","exclude-domain":!0,onChange:Y},{upload:r(()=>[d("div",be,[l(b,{size:20,name:"el-icon-Plus"}),e[8]||(e[8]=d("span",null,"检查报告",-1))])]),_:1},8,["modelValue"])])):m("",!0),u.notes.length?(n(),o("div",xe,[(n(!0),o(w,null,E(u.notes,s=>{var R,G;return n(),o("div",{key:s.id,class:"timeline-node"},[e[11]||(e[11]=d("div",{class:"timeline-dot"},null,-1)),d("div",Ee,U(s.note_date),1),d("div",Ve,[s.content?(n(),o("div",Ne,[(n(!0),o(w,null,E(J(s.content),(a,p)=>(n(),o("div",{key:p,class:"content-line"},U(a),1))),128))])):m("",!0),(R=s.tongue_images)!=null&&R.length?(n(),o("div",Se,[e[9]||(e[9]=d("span",{class:"images-label"},"舌苔照片",-1)),(n(!0),o(w,null,E(s.tongue_images,(a,p)=>(n(),o("div",{key:p,class:"thumb-wrap"},[l(L,{src:_(a),"preview-src-list":s.tongue_images.map(_),"initial-index":p,"z-index":W,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),u.readonly?m("",!0):(n(),k(x,{key:0,class:"thumb-delete",onClick:M(O=>A(s.id,"tongue_images",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))]))),128))])):m("",!0),(G=s.report_files)!=null&&G.length?(n(),o("div",De,[e[10]||(e[10]=d("span",{class:"images-label"},"检查报告",-1)),(n(!0),o(w,null,E(s.report_files,(a,p)=>(n(),o(w,{key:p},[B(a)?(n(),o("div",Be,[l(L,{src:_(a),"preview-src-list":K(s.report_files),"initial-index":Z(s.report_files,p),"z-index":W,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),u.readonly?m("",!0):(n(),k(x,{key:0,class:"thumb-delete",onClick:M(O=>A(s.id,"report_files",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))])):(n(),o("div",Ae,[d("a",{href:_(a),target:"_blank",class:"file-link",title:$(a)},[l(x,{size:20},{default:r(()=>[l(V(pe))]),_:1}),d("span",Ue,U($(a)),1)],8,Pe),u.readonly?m("",!0):(n(),k(x,{key:0,class:"file-delete",onClick:M(O=>A(s.id,"report_files",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))]))],64))),128))])):m("",!0)])])}),128))])):m("",!0),!u.notes.length&&u.readonly?(n(),k(te,{key:2,description:"暂无备注","image-size":48})):m("",!0),l(ne,{modelValue:v.value,"onUpdate:modelValue":e[5]||(e[5]=s=>v.value=s),title:"添加备注",width:"480px","append-to-body":""},{footer:r(()=>[l(i,{onClick:e[4]||(e[4]=s=>v.value=!1)},{default:r(()=>[...e[12]||(e[12]=[P("取消",-1)])]),_:1}),l(i,{type:"primary",loading:N.value,onClick:ee},{default:r(()=>[...e[13]||(e[13]=[P("保存",-1)])]),_:1},8,["loading"])]),default:r(()=>[l(se,{modelValue:C.value,"onUpdate:modelValue":e[3]||(e[3]=s=>C.value=s),type:"textarea",rows:4,placeholder:"输入今日备注...",maxlength:"500","show-word-limit":""},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),Ke=ye(ze,[["__scopeId","data-v-530ad386"]]);export{Ke as default};
|
`).filter(Boolean):[],Q=t=>{if(!c.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=y.value){y.value=e.length;return}const i=e.slice(y.value);y.value=e.length,i.length>0&&T({diagnosis_id:c.diagnosisId,tongue_images:i}).then(()=>{f.msgSuccess("舌苔照片已添加"),I("refresh")})},Y=t=>{if(!c.diagnosisId)return;const e=Array.isArray(t)?t:[t];if(e.length<=h.value){h.value=e.length;return}const i=e.slice(h.value);h.value=e.length,i.length>0&&T({diagnosis_id:c.diagnosisId,report_files:i}).then(()=>{f.msgSuccess("检查报告已添加"),I("refresh")})};oe(()=>c.notes,()=>{S.value=[],D.value=[],y.value=0,h.value=0});const ee=async()=>{if(!c.diagnosisId){f.msgWarning("当前无诊单,无法添加备注");return}const t=C.value.trim();if(!t){f.msgWarning("请输入备注内容");return}N.value=!0;try{await T({diagnosis_id:c.diagnosisId,content:t}),f.msgSuccess("备注保存成功"),C.value="",v.value=!1,I("refresh")}catch(e){f.msgError((e==null?void 0:e.message)||"保存失败")}finally{N.value=!1}},A=async(t,e,i)=>{try{await ge.confirm("确认删除?","提示",{type:"warning"})}catch{return}await he({note_id:t,image_type:e,image_path:i}),f.msgSuccess("已删除"),I("refresh")};return(t,e)=>{const i=le,b=_e,F=fe,L=me,x=ce,te=ae,se=re,ne=de;return n(),o("div",we,[!u.readonly&&u.diagnosisId?(n(),o("div",Ie,[X.value?(n(),k(i,{key:0,type:"primary",plain:"",size:"small",onClick:e[0]||(e[0]=s=>v.value=!0)},{default:r(()=>[...e[6]||(e[6]=[P(" 添加备注 ",-1)])]),_:1})):m("",!0),l(F,{modelValue:S.value,"onUpdate:modelValue":e[1]||(e[1]=s=>S.value=s),limit:99,type:"image","exclude-domain":!0,onChange:Q},{upload:r(()=>[d("div",Ce,[l(b,{size:20,name:"el-icon-Plus"}),e[7]||(e[7]=d("span",null,"舌苔照片",-1))])]),_:1},8,["modelValue"]),l(F,{modelValue:D.value,"onUpdate:modelValue":e[2]||(e[2]=s=>D.value=s),limit:99,type:"file","exclude-domain":!0,onChange:Y},{upload:r(()=>[d("div",be,[l(b,{size:20,name:"el-icon-Plus"}),e[8]||(e[8]=d("span",null,"检查报告",-1))])]),_:1},8,["modelValue"])])):m("",!0),u.notes.length?(n(),o("div",xe,[(n(!0),o(w,null,E(u.notes,s=>{var R,G;return n(),o("div",{key:s.id,class:"timeline-node"},[e[11]||(e[11]=d("div",{class:"timeline-dot"},null,-1)),d("div",Ee,U(s.note_date),1),d("div",Ve,[s.content?(n(),o("div",Ne,[(n(!0),o(w,null,E(J(s.content),(a,p)=>(n(),o("div",{key:p,class:"content-line"},U(a),1))),128))])):m("",!0),(R=s.tongue_images)!=null&&R.length?(n(),o("div",Se,[e[9]||(e[9]=d("span",{class:"images-label"},"舌苔照片",-1)),(n(!0),o(w,null,E(s.tongue_images,(a,p)=>(n(),o("div",{key:p,class:"thumb-wrap"},[l(L,{src:_(a),"preview-src-list":s.tongue_images.map(_),"initial-index":p,"z-index":W,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),u.readonly?m("",!0):(n(),k(x,{key:0,class:"thumb-delete",onClick:M(O=>A(s.id,"tongue_images",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))]))),128))])):m("",!0),(G=s.report_files)!=null&&G.length?(n(),o("div",De,[e[10]||(e[10]=d("span",{class:"images-label"},"检查报告",-1)),(n(!0),o(w,null,E(s.report_files,(a,p)=>(n(),o(w,{key:p},[B(a)?(n(),o("div",Be,[l(L,{src:_(a),"preview-src-list":K(s.report_files),"initial-index":Z(s.report_files,p),"z-index":W,fit:"cover",class:"timeline-thumb","preview-teleported":""},null,8,["src","preview-src-list","initial-index"]),u.readonly?m("",!0):(n(),k(x,{key:0,class:"thumb-delete",onClick:M(O=>A(s.id,"report_files",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))])):(n(),o("div",Ae,[d("a",{href:_(a),target:"_blank",class:"file-link",title:$(a)},[l(x,{size:20},{default:r(()=>[l(V(pe))]),_:1}),d("span",Ue,U($(a)),1)],8,Pe),u.readonly?m("",!0):(n(),k(x,{key:0,class:"file-delete",onClick:M(O=>A(s.id,"report_files",a),["stop"])},{default:r(()=>[l(V(z))]),_:1},8,["onClick"]))]))],64))),128))])):m("",!0)])])}),128))])):m("",!0),!u.notes.length&&u.readonly?(n(),k(te,{key:2,description:"暂无备注","image-size":48})):m("",!0),l(ne,{modelValue:v.value,"onUpdate:modelValue":e[5]||(e[5]=s=>v.value=s),title:"添加备注",width:"480px","append-to-body":""},{footer:r(()=>[l(i,{onClick:e[4]||(e[4]=s=>v.value=!1)},{default:r(()=>[...e[12]||(e[12]=[P("取消",-1)])]),_:1}),l(i,{type:"primary",loading:N.value,onClick:ee},{default:r(()=>[...e[13]||(e[13]=[P("保存",-1)])]),_:1},8,["loading"])]),default:r(()=>[l(se,{modelValue:C.value,"onUpdate:modelValue":e[3]||(e[3]=s=>C.value=s),type:"textarea",rows:4,placeholder:"输入今日备注...",maxlength:"500","show-word-limit":""},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),Ke=ye(ze,[["__scopeId","data-v-530ad386"]]);export{Ke as default};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{m as I,f as p,a as w}from"./diag-display-DCz_VAqj.js";import{o as y,q as x,r as B,s as e,T as a,u as i,P as N}from"./.pnpm-BSw4l71J.js";import{_ as V}from"./index-BWlhxa68.js";const b={class:"card patient-card"},q={class:"patient-hero"},D={class:"patient-name"},E={class:"patient-meta"},G={key:0},S=y({__name:"PatientInfoCard",props:{apt:{default:()=>({})},diag:{default:()=>({})}},setup(t){return(T,n)=>{var d,s,o,c,m,l,r,g,u,f,h,v,k,P,C;return x(),B("div",b,[n[0]||(n[0]=e("div",{class:"card-title"},"患者信息",-1)),e("div",q,[e("div",D,a(((d=t.apt)==null?void 0:d.patient_name)||"—"),1),e("div",E,[e("div",null,a(i(I)((s=t.apt)==null?void 0:s.patient_phone))+" · "+a(i(p)((o=t.diag)==null?void 0:o.gender))+" · "+a(((c=t.diag)==null?void 0:c.age)!=null?t.diag.age+"岁":"—"),1),e("div",null,a((m=t.diag)!=null&&m.height?t.diag.height+"cm":"—")+" / "+a((l=t.diag)!=null&&l.weight?t.diag.weight+"kg":"—")+" · "+a(((r=t.diag)==null?void 0:r.region)||"—"),1),e("div",null," 预约:"+a((g=t.apt)==null?void 0:g.appointment_date)+" "+a((u=t.apt)==null?void 0:u.appointment_time)+" · "+a(i(w)((f=t.apt)==null?void 0:f.period)),1),e("div",null,"医生:"+a(((h=t.apt)==null?void 0:h.doctor_name)||"—")+" 客服:"+a(((v=t.apt)==null?void 0:v.assistant_name)||"—"),1),e("div",null," 状态:"+a(((k=t.apt)==null?void 0:k.status_desc)||"—")+" · "+a((P=t.apt)!=null&&P.has_prescription?"已开方":"未开方"),1),(C=t.apt)!=null&&C.remark?(x(),B("div",G,"备注:"+a(t.apt.remark),1)):N("",!0)])])])}}}),F=V(S,[["__scopeId","data-v-1b0de09c"]]);export{F as default};
|
import{m as I,f as p,a as w}from"./diag-display-DCz_VAqj.js";import{o as y,q as x,r as B,s as e,T as a,u as i,P as N}from"./.pnpm-BSw4l71J.js";import{_ as V}from"./index-CQbHw_bK.js";const b={class:"card patient-card"},q={class:"patient-hero"},D={class:"patient-name"},E={class:"patient-meta"},G={key:0},S=y({__name:"PatientInfoCard",props:{apt:{default:()=>({})},diag:{default:()=>({})}},setup(t){return(T,n)=>{var d,s,o,c,m,l,r,g,u,f,h,v,k,P,C;return x(),B("div",b,[n[0]||(n[0]=e("div",{class:"card-title"},"患者信息",-1)),e("div",q,[e("div",D,a(((d=t.apt)==null?void 0:d.patient_name)||"—"),1),e("div",E,[e("div",null,a(i(I)((s=t.apt)==null?void 0:s.patient_phone))+" · "+a(i(p)((o=t.diag)==null?void 0:o.gender))+" · "+a(((c=t.diag)==null?void 0:c.age)!=null?t.diag.age+"岁":"—"),1),e("div",null,a((m=t.diag)!=null&&m.height?t.diag.height+"cm":"—")+" / "+a((l=t.diag)!=null&&l.weight?t.diag.weight+"kg":"—")+" · "+a(((r=t.diag)==null?void 0:r.region)||"—"),1),e("div",null," 预约:"+a((g=t.apt)==null?void 0:g.appointment_date)+" "+a((u=t.apt)==null?void 0:u.appointment_time)+" · "+a(i(w)((f=t.apt)==null?void 0:f.period)),1),e("div",null,"医生:"+a(((h=t.apt)==null?void 0:h.doctor_name)||"—")+" 客服:"+a(((v=t.apt)==null?void 0:v.assistant_name)||"—"),1),e("div",null," 状态:"+a(((k=t.apt)==null?void 0:k.status_desc)||"—")+" · "+a((P=t.apt)!=null&&P.has_prescription?"已开方":"未开方"),1),(C=t.apt)!=null&&C.remark?(x(),B("div",G,"备注:"+a(t.apt.remark),1)):N("",!0)])])])}}}),F=V(S,[["__scopeId","data-v-1b0de09c"]]);export{F as default};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as L,q as i,r as c,s as d,F as v,O as m,bq as q,D as _,L as k,P as y,G as B,p as f,T as w}from"./.pnpm-BSw4l71J.js";import H from"./RecordingVideoPlayer-fgB7SxV4.js";import{e as I,_ as P}from"./index-BWlhxa68.js";const R={key:0,class:"recording-list"},C={class:"recording-item"},V={key:1,class:"recording-alternates"},N={class:"recording-alternates__links"},D={key:1,class:"text-gray-400"},E=L({__name:"RecordingPlaybackBlock",props:{recordId:{},urls:{}},setup(l){const $=l,h=I(),u=f(()=>{const e=$.urls||[],t=new Set,r=[];for(const o of e){const s=String(o??"").trim();!s||t.has(s)||(t.add(s),r.push(s))}return r}),a=f(()=>{const e=u.value;if(!e.length)return null;const t=e.find(n=>/\.mp4(\?|#|$)/i.test(n));if(t)return t;const r=e.find(n=>/\.m3u8(\?|#|$)/i.test(n)&&/vod-qcloud\.com/i.test(n));if(r)return r;const o=e.find(n=>/\.m3u8(\?|#|$)/i.test(n)&&/\.cos\.[^/]+\.myqcloud\.com/i.test(n));if(o)return o;const s=e.find(n=>/\.m3u8(\?|#|$)/i.test(n));return s||e[0]}),p=f(()=>{const e=u.value,t=a.value;return t?e.filter(r=>r!==t):e.slice(1)});function b(e){if(!e||typeof e!="string")return!1;const t=e.trim();return/^https?:\/\//i.test(t)?/\.(mp4|webm|ogg|mov|mkv|m4v|m3u8)(\?|#|$)/i.test(t):/\.(mp4|webm|ogg|mov|mkv|m4v|m3u8)(\?|#|$)/i.test(t)||t.startsWith("/uploads/")}function g(e){return h.getImageUrl(String(e||"").trim())}function S(e,t){const r=e.trim();return/\.mp4(\?|#|$)/i.test(r)?`MP4 ${t+1}`:/vod-qcloud\.com/i.test(r)&&/\.m3u8/i.test(r)?`点播 ${t+1}`:/\.cos\.[^/]+\.myqcloud\.com/i.test(r)&&/\.m3u8/i.test(r)?`COS HLS ${t+1}`:/\.m3u8/i.test(r)?`HLS ${t+1}`:`链接 ${t+1}`}return(e,t)=>{const r=q;return u.value.length?(i(),c("div",R,[d("div",C,[a.value?(i(),c(v,{key:0},[b(a.value)?(i(),m(H,{key:`${l.recordId}-${a.value}`,src:a.value},null,8,["src"])):(i(),m(r,{key:1,href:g(a.value),target:"_blank",type:"primary"},{default:_(()=>[...t[0]||(t[0]=[k(" 打开回放 ",-1)])]),_:1},8,["href"]))],64)):y("",!0),p.value.length?(i(),c("div",V,[t[1]||(t[1]=d("span",{class:"recording-alternates__label"},"备用地址",-1)),d("div",N,[(i(!0),c(v,null,B(p.value,(o,s)=>(i(),m(r,{key:`${l.recordId}-alt-${s}-${o.slice(-32)}`,href:g(o),target:"_blank",type:"primary",class:"recording-alternates__link"},{default:_(()=>[k(w(S(o,s)),1)]),_:2},1032,["href"]))),128))])])):y("",!0)])])):(i(),c("span",D,"暂无"))}}}),x=P(E,[["__scopeId","data-v-d67b2e91"]]);export{x as default};
|
import{o as L,q as i,r as c,s as d,F as v,O as m,bq as q,D as _,L as k,P as y,G as B,p as f,T as w}from"./.pnpm-BSw4l71J.js";import H from"./RecordingVideoPlayer-CaeLNO_q.js";import{e as I,_ as P}from"./index-CQbHw_bK.js";const R={key:0,class:"recording-list"},C={class:"recording-item"},V={key:1,class:"recording-alternates"},N={class:"recording-alternates__links"},D={key:1,class:"text-gray-400"},E=L({__name:"RecordingPlaybackBlock",props:{recordId:{},urls:{}},setup(l){const $=l,h=I(),u=f(()=>{const e=$.urls||[],t=new Set,r=[];for(const o of e){const s=String(o??"").trim();!s||t.has(s)||(t.add(s),r.push(s))}return r}),a=f(()=>{const e=u.value;if(!e.length)return null;const t=e.find(n=>/\.mp4(\?|#|$)/i.test(n));if(t)return t;const r=e.find(n=>/\.m3u8(\?|#|$)/i.test(n)&&/vod-qcloud\.com/i.test(n));if(r)return r;const o=e.find(n=>/\.m3u8(\?|#|$)/i.test(n)&&/\.cos\.[^/]+\.myqcloud\.com/i.test(n));if(o)return o;const s=e.find(n=>/\.m3u8(\?|#|$)/i.test(n));return s||e[0]}),p=f(()=>{const e=u.value,t=a.value;return t?e.filter(r=>r!==t):e.slice(1)});function b(e){if(!e||typeof e!="string")return!1;const t=e.trim();return/^https?:\/\//i.test(t)?/\.(mp4|webm|ogg|mov|mkv|m4v|m3u8)(\?|#|$)/i.test(t):/\.(mp4|webm|ogg|mov|mkv|m4v|m3u8)(\?|#|$)/i.test(t)||t.startsWith("/uploads/")}function g(e){return h.getImageUrl(String(e||"").trim())}function S(e,t){const r=e.trim();return/\.mp4(\?|#|$)/i.test(r)?`MP4 ${t+1}`:/vod-qcloud\.com/i.test(r)&&/\.m3u8/i.test(r)?`点播 ${t+1}`:/\.cos\.[^/]+\.myqcloud\.com/i.test(r)&&/\.m3u8/i.test(r)?`COS HLS ${t+1}`:/\.m3u8/i.test(r)?`HLS ${t+1}`:`链接 ${t+1}`}return(e,t)=>{const r=q;return u.value.length?(i(),c("div",R,[d("div",C,[a.value?(i(),c(v,{key:0},[b(a.value)?(i(),m(H,{key:`${l.recordId}-${a.value}`,src:a.value},null,8,["src"])):(i(),m(r,{key:1,href:g(a.value),target:"_blank",type:"primary"},{default:_(()=>[...t[0]||(t[0]=[k(" 打开回放 ",-1)])]),_:1},8,["href"]))],64)):y("",!0),p.value.length?(i(),c("div",V,[t[1]||(t[1]=d("span",{class:"recording-alternates__label"},"备用地址",-1)),d("div",N,[(i(!0),c(v,null,B(p.value,(o,s)=>(i(),m(r,{key:`${l.recordId}-alt-${s}-${o.slice(-32)}`,href:g(o),target:"_blank",type:"primary",class:"recording-alternates__link"},{default:_(()=>[k(w(S(o,s)),1)]),_:2},1032,["href"]))),128))])])):y("",!0)])])):(i(),c("span",D,"暂无"))}}}),x=P(E,[["__scopeId","data-v-d67b2e91"]]);export{x as default};
|
||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/.pnpm-BSw4l71J.js","assets/.pnpm-B3v8nGpq.css"])))=>i.map(i=>d[i]);
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/.pnpm-BSw4l71J.js","assets/.pnpm-B3v8nGpq.css"])))=>i.map(i=>d[i]);
|
||||||
import{o as K,ap as z,n as S,R as H,aq as G,q as v,r as p,s as f,ac as O,ad as W,b8 as $,aw as j,F as w,v as k,D as I,u as J,b5 as Q,w as X,P,L as Y,bq as Z,M as _,p as E,al as ee}from"./.pnpm-BSw4l71J.js";import{e as ae,_ as ne}from"./index-BWlhxa68.js";const te={class:"recording-playback__shell"},re=["preload"],oe=["onKeydown"],le=K({__name:"RecordingVideoPlayer",props:{src:{}},setup(B){const V=B,A=ae(),b=_(null),m=_(null),c=_(!1),s=_(!1),t=_(!1);let d=null,r=null,l=0,u=null;function i(){u!==null&&(clearTimeout(u),u=null)}const y=E(()=>{const e=String(V.src||"").trim();return e?U(A.getImageUrl(e)):""}),D=E(()=>{if(!s.value)return"none";const e=y.value;return e&&!L(e)?"metadata":"none"}),q=E(()=>!s.value||t.value);function U(e){if(!e||!/^https?:\/\//i.test(e))return e;try{const a=new URL(e),n=a.hostname.toLowerCase();if(n.includes("myqcloud.com")||n.includes("vod-qcloud.com")||n.includes("vod-qcloud"))return a.pathname.includes("+")&&(a.pathname=a.pathname.replace(/\+/g,"%2B")),a.href}catch{}return e}function L(e){return/\.m3u8(\?|#|$)/i.test(e)}function C(){var n;t.value=!1,i();const e=m.value,a=(n=e==null?void 0:e.error)==null?void 0:n.code;a===MediaError.MEDIA_ERR_ABORTED||a===1||(c.value=!0)}function h(){d&&(d.destroy(),d=null);const e=m.value;e&&(e.pause(),e.removeAttribute("src"),e.load())}function R(e,a){let n=!1;const o=()=>{n||a!==l||(n=!0,i(),t.value=!1)};e.addEventListener("loadedmetadata",()=>o(),{once:!0}),e.addEventListener("loadeddata",()=>o(),{once:!0}),e.addEventListener("canplay",()=>o(),{once:!0}),e.addEventListener("playing",()=>o(),{once:!0}),e.addEventListener("progress",()=>{try{e.buffered.length>0&&e.buffered.end(0)>0&&o("progress-buffered")}catch{}},{passive:!0})}async function g(){if(!s.value)return;await S();const e=m.value,a=y.value;if(!e)return;if(!a){t.value=!1,i();return}const n=++l;if(t.value=!0,i(),h(),c.value=!1,L(a)){try{const o=await ee(()=>import("./.pnpm-BSw4l71J.js").then(M=>M.dP),__vite__mapDeps([0,1])),x=o.default;if(x.isSupported()){d=new x({enableWorker:!0,lowLatencyMode:!1,maxBufferLength:20,maxMaxBufferLength:120}),d.on(o.Events.MANIFEST_PARSED,()=>{n===l&&(t.value=!1,i())}),d.on(o.Events.ERROR,(M,F)=>{if(F.fatal){if(n!==l)return;t.value=!1,i(),c.value=!0,h()}}),d.loadSource(a),d.attachMedia(e),u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},45e3);return}if(e.canPlayType("application/vnd.apple.mpegurl")){R(e,n),e.src=a,u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},45e3);return}}catch{if(n!==l)return;t.value=!1,i(),c.value=!0;return}if(n!==l)return;t.value=!1,i(),c.value=!0;return}R(e,n),e.src=a,u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},25e3)}function N(){const e=b.value;if(!e||typeof IntersectionObserver>"u"){s.value=!0,g();return}r=new IntersectionObserver(a=>{for(const n of a)if(n.isIntersecting){r==null||r.disconnect(),r=null,s.value=!0,g();break}},{root:null,rootMargin:"240px 0px",threshold:0}),r.observe(e)}function T(){r==null||r.disconnect(),r=null,s.value||(s.value=!0),g()}return z(()=>{S(()=>{N()})}),H(y,()=>{s.value&&g()}),G(()=>{r==null||r.disconnect(),r=null,i(),l++,h()}),(e,a)=>{const n=X,o=Z;return v(),p("div",{ref_key:"wrapRef",ref:b,class:"recording-playback"},[f("div",te,[O(f("video",{ref_key:"videoRef",ref:m,class:"recording-video",controls:"",playsinline:"","webkit-playsinline":"",preload:D.value,onError:C},null,40,re),[[W,!c.value]]),!c.value&&q.value?(v(),p("div",{key:0,class:"recording-playback__overlay",role:"button",tabindex:"0",onClick:T,onKeydown:$(j(T,["prevent"]),["enter"])},[s.value?(v(),p(w,{key:1},[k(n,{class:"recording-playback__spin"},{default:I(()=>[k(J(Q))]),_:1}),a[2]||(a[2]=f("span",null,"正在加载…",-1))],64)):(v(),p(w,{key:0},[a[0]||(a[0]=f("span",{class:"recording-playback__overlay-title"},"预览待加载",-1)),a[1]||(a[1]=f("span",{class:"recording-playback__overlay-desc"},"滚动至此处将自动加载(减轻并发卡顿),也可点击立即加载",-1))],64))],40,oe)):P("",!0)]),c.value?(v(),p(w,{key:0},[k(o,{href:y.value||"#",target:"_blank",type:"primary"},{default:I(()=>[...a[3]||(a[3]=[Y("在新窗口打开",-1)])]),_:1},8,["href"]),a[4]||(a[4]=f("div",{class:"recording-playback__hint"}," 内嵌播放失败(编码不支持、跨域或私有存储等)时可尝试在新窗口打开。 ",-1))],64)):P("",!0)],512)}}}),ie=ne(le,[["__scopeId","data-v-749b0199"]]);export{ie as default};
|
import{o as K,ap as z,n as S,R as H,aq as G,q as v,r as p,s as f,ac as O,ad as W,b8 as $,aw as j,F as w,v as k,D as I,u as J,b5 as Q,w as X,P,L as Y,bq as Z,M as _,p as E,al as ee}from"./.pnpm-BSw4l71J.js";import{e as ae,_ as ne}from"./index-CQbHw_bK.js";const te={class:"recording-playback__shell"},re=["preload"],oe=["onKeydown"],le=K({__name:"RecordingVideoPlayer",props:{src:{}},setup(B){const V=B,A=ae(),b=_(null),m=_(null),c=_(!1),s=_(!1),t=_(!1);let d=null,r=null,l=0,u=null;function i(){u!==null&&(clearTimeout(u),u=null)}const y=E(()=>{const e=String(V.src||"").trim();return e?U(A.getImageUrl(e)):""}),D=E(()=>{if(!s.value)return"none";const e=y.value;return e&&!L(e)?"metadata":"none"}),q=E(()=>!s.value||t.value);function U(e){if(!e||!/^https?:\/\//i.test(e))return e;try{const a=new URL(e),n=a.hostname.toLowerCase();if(n.includes("myqcloud.com")||n.includes("vod-qcloud.com")||n.includes("vod-qcloud"))return a.pathname.includes("+")&&(a.pathname=a.pathname.replace(/\+/g,"%2B")),a.href}catch{}return e}function L(e){return/\.m3u8(\?|#|$)/i.test(e)}function C(){var n;t.value=!1,i();const e=m.value,a=(n=e==null?void 0:e.error)==null?void 0:n.code;a===MediaError.MEDIA_ERR_ABORTED||a===1||(c.value=!0)}function h(){d&&(d.destroy(),d=null);const e=m.value;e&&(e.pause(),e.removeAttribute("src"),e.load())}function R(e,a){let n=!1;const o=()=>{n||a!==l||(n=!0,i(),t.value=!1)};e.addEventListener("loadedmetadata",()=>o(),{once:!0}),e.addEventListener("loadeddata",()=>o(),{once:!0}),e.addEventListener("canplay",()=>o(),{once:!0}),e.addEventListener("playing",()=>o(),{once:!0}),e.addEventListener("progress",()=>{try{e.buffered.length>0&&e.buffered.end(0)>0&&o("progress-buffered")}catch{}},{passive:!0})}async function g(){if(!s.value)return;await S();const e=m.value,a=y.value;if(!e)return;if(!a){t.value=!1,i();return}const n=++l;if(t.value=!0,i(),h(),c.value=!1,L(a)){try{const o=await ee(()=>import("./.pnpm-BSw4l71J.js").then(M=>M.dP),__vite__mapDeps([0,1])),x=o.default;if(x.isSupported()){d=new x({enableWorker:!0,lowLatencyMode:!1,maxBufferLength:20,maxMaxBufferLength:120}),d.on(o.Events.MANIFEST_PARSED,()=>{n===l&&(t.value=!1,i())}),d.on(o.Events.ERROR,(M,F)=>{if(F.fatal){if(n!==l)return;t.value=!1,i(),c.value=!0,h()}}),d.loadSource(a),d.attachMedia(e),u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},45e3);return}if(e.canPlayType("application/vnd.apple.mpegurl")){R(e,n),e.src=a,u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},45e3);return}}catch{if(n!==l)return;t.value=!1,i(),c.value=!0;return}if(n!==l)return;t.value=!1,i(),c.value=!0;return}R(e,n),e.src=a,u=setTimeout(()=>{u=null,n===l&&t.value&&(t.value=!1)},25e3)}function N(){const e=b.value;if(!e||typeof IntersectionObserver>"u"){s.value=!0,g();return}r=new IntersectionObserver(a=>{for(const n of a)if(n.isIntersecting){r==null||r.disconnect(),r=null,s.value=!0,g();break}},{root:null,rootMargin:"240px 0px",threshold:0}),r.observe(e)}function T(){r==null||r.disconnect(),r=null,s.value||(s.value=!0),g()}return z(()=>{S(()=>{N()})}),H(y,()=>{s.value&&g()}),G(()=>{r==null||r.disconnect(),r=null,i(),l++,h()}),(e,a)=>{const n=X,o=Z;return v(),p("div",{ref_key:"wrapRef",ref:b,class:"recording-playback"},[f("div",te,[O(f("video",{ref_key:"videoRef",ref:m,class:"recording-video",controls:"",playsinline:"","webkit-playsinline":"",preload:D.value,onError:C},null,40,re),[[W,!c.value]]),!c.value&&q.value?(v(),p("div",{key:0,class:"recording-playback__overlay",role:"button",tabindex:"0",onClick:T,onKeydown:$(j(T,["prevent"]),["enter"])},[s.value?(v(),p(w,{key:1},[k(n,{class:"recording-playback__spin"},{default:I(()=>[k(J(Q))]),_:1}),a[2]||(a[2]=f("span",null,"正在加载…",-1))],64)):(v(),p(w,{key:0},[a[0]||(a[0]=f("span",{class:"recording-playback__overlay-title"},"预览待加载",-1)),a[1]||(a[1]=f("span",{class:"recording-playback__overlay-desc"},"滚动至此处将自动加载(减轻并发卡顿),也可点击立即加载",-1))],64))],40,oe)):P("",!0)]),c.value?(v(),p(w,{key:0},[k(o,{href:y.value||"#",target:"_blank",type:"primary"},{default:I(()=>[...a[3]||(a[3]=[Y("在新窗口打开",-1)])]),_:1},8,["href"]),a[4]||(a[4]=f("div",{class:"recording-playback__hint"}," 内嵌播放失败(编码不支持、跨域或私有存储等)时可尝试在新窗口打开。 ",-1))],64)):P("",!0)],512)}}}),ie=ne(le,[["__scopeId","data-v-749b0199"]]);export{ie as default};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
import{o as T,q as e,r as t,v as m,b7 as V,s as d,D as w,L as I,K as E,P as r,F as u,G as v,T as g,O as C,bB as z,M as p}from"./.pnpm-BSw4l71J.js";import{a5 as L}from"./tcm-Bv_Ly0A0.js";import{i as M,_ as S}from"./index-BWlhxa68.js";/* empty css */const D={class:"tracking-timeline-wrap"},F={key:0,class:"timeline-input"},H={class:"input-actions"},q={key:1,class:"tracking-timeline"},A={class:"timeline-date"},G={class:"timeline-body"},K={key:0,class:"timeline-content"},O=T({__name:"TrackingNoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(n,{emit:f}){const c=n,y=f,o=p(""),l=p(!1),_=s=>s?s.split(`
|
import{o as T,q as e,r as t,v as m,b7 as V,s as d,D as w,L as I,K as E,P as r,F as u,G as v,T as g,O as C,bB as z,M as p}from"./.pnpm-BSw4l71J.js";import{a5 as L}from"./tcm-PbOYp3fC.js";import{i as M,_ as S}from"./index-CQbHw_bK.js";/* empty css */const D={class:"tracking-timeline-wrap"},F={key:0,class:"timeline-input"},H={class:"input-actions"},q={key:1,class:"tracking-timeline"},A={class:"timeline-date"},G={class:"timeline-body"},K={key:0,class:"timeline-content"},O=T({__name:"TrackingNoteTimeline",props:{notes:{},diagnosisId:{},readonly:{type:Boolean}},emits:["refresh"],setup(n,{emit:f}){const c=n,y=f,o=p(""),l=p(!1),_=s=>s?s.split(`
|
||||||
`).filter(Boolean):[],k=async()=>{if(!c.diagnosisId)return;const s=o.value.trim();if(s){l.value=!0;try{await L({diagnosis_id:c.diagnosisId,tracking_content:s}),M.msgSuccess("已添加"),o.value="",y("refresh")}finally{l.value=!1}}};return(s,i)=>{const b=V,h=E,B=z;return e(),t("div",D,[!n.readonly&&n.diagnosisId?(e(),t("div",F,[m(b,{modelValue:o.value,"onUpdate:modelValue":i[0]||(i[0]=a=>o.value=a),type:"textarea",rows:2,placeholder:"输入跟踪备注,回车换行;保存后将以「[HH:MM] 内容」追加到当天记录",maxlength:"1000","show-word-limit":"",resize:"none",disabled:l.value},null,8,["modelValue","disabled"]),d("div",H,[m(h,{type:"primary",size:"small",loading:l.value,disabled:!o.value.trim(),onClick:k},{default:w(()=>[...i[1]||(i[1]=[I(" 添加 ",-1)])]),_:1},8,["loading","disabled"])])])):r("",!0),n.notes.length?(e(),t("div",q,[(e(!0),t(u,null,v(n.notes,a=>(e(),t("div",{key:a.id,class:"timeline-node"},[i[2]||(i[2]=d("div",{class:"timeline-dot"},null,-1)),d("div",A,g(a.note_date),1),d("div",G,[a.content?(e(),t("div",K,[(e(!0),t(u,null,v(_(a.content),(x,N)=>(e(),t("div",{key:N,class:"content-line"},g(x),1))),128))])):r("",!0)])]))),128))])):r("",!0),!n.notes.length&&n.readonly?(e(),C(B,{key:2,description:"暂无跟踪备注","image-size":48})):r("",!0)])}}}),Q=S(O,[["__scopeId","data-v-82b635bd"]]);export{Q as default};
|
`).filter(Boolean):[],k=async()=>{if(!c.diagnosisId)return;const s=o.value.trim();if(s){l.value=!0;try{await L({diagnosis_id:c.diagnosisId,tracking_content:s}),M.msgSuccess("已添加"),o.value="",y("refresh")}finally{l.value=!1}}};return(s,i)=>{const b=V,h=E,B=z;return e(),t("div",D,[!n.readonly&&n.diagnosisId?(e(),t("div",F,[m(b,{modelValue:o.value,"onUpdate:modelValue":i[0]||(i[0]=a=>o.value=a),type:"textarea",rows:2,placeholder:"输入跟踪备注,回车换行;保存后将以「[HH:MM] 内容」追加到当天记录",maxlength:"1000","show-word-limit":"",resize:"none",disabled:l.value},null,8,["modelValue","disabled"]),d("div",H,[m(h,{type:"primary",size:"small",loading:l.value,disabled:!o.value.trim(),onClick:k},{default:w(()=>[...i[1]||(i[1]=[I(" 添加 ",-1)])]),_:1},8,["loading","disabled"])])])):r("",!0),n.notes.length?(e(),t("div",q,[(e(!0),t(u,null,v(n.notes,a=>(e(),t("div",{key:a.id,class:"timeline-node"},[i[2]||(i[2]=d("div",{class:"timeline-dot"},null,-1)),d("div",A,g(a.note_date),1),d("div",G,[a.content?(e(),t("div",K,[(e(!0),t(u,null,v(_(a.content),(x,N)=>(e(),t("div",{key:N,class:"content-line"},g(x),1))),128))])):r("",!0)])]))),128))])):r("",!0),!n.notes.length&&n.readonly?(e(),C(B,{key:2,description:"暂无跟踪备注","image-size":48})):r("",!0)])}}}),Q=S(O,[["__scopeId","data-v-82b635bd"]]);export{Q as default};
|
||||||
+1
-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
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./account-adjust.vue_vue_type_script_setup_true_lang-YRRaIwk_.js";import"./.pnpm-BSw4l71J.js";import"./index-BHzpLgF4.js";import"./index-CQbHw_bK.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./account-adjust.vue_vue_type_script_setup_true_lang-CrbSIkWk.js";import"./.pnpm-BSw4l71J.js";import"./index-IBEgpZdk.js";import"./index-BWlhxa68.js";export{o as default};
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as h,R as v,q,O as B,D as l,s as D,v as t,b9 as F,u as n,b6 as I,L as u,T as w,bc as j,bf as S,b7 as T,a8 as y,ba as U,p as G}from"./.pnpm-BSw4l71J.js";import{_ as L}from"./index-IBEgpZdk.js";import{i as V}from"./index-BWlhxa68.js";const M={class:"pr-8"},H=h({__name:"account-adjust",props:{show:{type:Boolean,required:!0},value:{type:[Number,String],required:!0}},emits:["update:show","confirm"],setup(d,{emit:k}){const s=y(),i=d,f=k,o=U({action:1,num:"",remark:""}),m=y(),c=G(()=>Number(i.value)+Number(o.num)*(o.action==1?1:-1)),R={num:[{required:!0,message:"请输入调整的金额"}]},g=e=>{if(e.includes("-"))return V.msgError("请输入正整数");o.num=e},x=async()=>{var e;await((e=s.value)==null?void 0:e.validate()),f("confirm",o)},E=()=>{var e;f("update:show",!1),(e=s.value)==null||e.resetFields()};return v(()=>i.show,e=>{var a,r;e?(a=m.value)==null||a.open():(r=m.value)==null||r.close()}),v(c,e=>{e<0&&(V.msgError("调整后余额需大于0"),o.num="")}),(e,a)=>{const r=I,_=S,C=j,b=T,N=F;return q(),B(L,{ref_key:"popupRef",ref:m,title:"余额调整",width:"500px",onConfirm:x,async:!0,onClose:E},{default:l(()=>[D("div",M,[t(N,{ref_key:"formRef",ref:s,model:n(o),"label-width":"120px",rules:R},{default:l(()=>[t(r,{label:"当前余额"},{default:l(()=>[u("¥ "+w(d.value),1)]),_:1}),t(r,{label:"余额增减",required:"",prop:"action"},{default:l(()=>[t(C,{modelValue:n(o).action,"onUpdate:modelValue":a[0]||(a[0]=p=>n(o).action=p)},{default:l(()=>[t(_,{value:1},{default:l(()=>[...a[2]||(a[2]=[u("增加余额",-1)])]),_:1}),t(_,{value:2},{default:l(()=>[...a[3]||(a[3]=[u("扣减余额",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(r,{label:"调整余额",prop:"num"},{default:l(()=>[t(b,{"model-value":n(o).num,placeholder:"请输入调整的金额",type:"number",onInput:g},null,8,["model-value"])]),_:1}),t(r,{label:"调整后余额"},{default:l(()=>[u(" ¥ "+w(n(c)),1)]),_:1}),t(r,{label:"备注",prop:"remark"},{default:l(()=>[t(b,{modelValue:n(o).remark,"onUpdate:modelValue":a[1]||(a[1]=p=>n(o).remark=p),type:"textarea",rows:4},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])])]),_:1},512)}}});export{H as _};
|
import{o as h,R as v,q,O as B,D as l,s as D,v as t,b9 as F,u as n,b6 as I,L as u,T as w,bc as j,bf as S,b7 as T,a8 as y,ba as U,p as G}from"./.pnpm-BSw4l71J.js";import{_ as L}from"./index-BHzpLgF4.js";import{i as V}from"./index-CQbHw_bK.js";const M={class:"pr-8"},H=h({__name:"account-adjust",props:{show:{type:Boolean,required:!0},value:{type:[Number,String],required:!0}},emits:["update:show","confirm"],setup(d,{emit:k}){const s=y(),i=d,f=k,o=U({action:1,num:"",remark:""}),m=y(),c=G(()=>Number(i.value)+Number(o.num)*(o.action==1?1:-1)),R={num:[{required:!0,message:"请输入调整的金额"}]},g=e=>{if(e.includes("-"))return V.msgError("请输入正整数");o.num=e},x=async()=>{var e;await((e=s.value)==null?void 0:e.validate()),f("confirm",o)},E=()=>{var e;f("update:show",!1),(e=s.value)==null||e.resetFields()};return v(()=>i.show,e=>{var a,r;e?(a=m.value)==null||a.open():(r=m.value)==null||r.close()}),v(c,e=>{e<0&&(V.msgError("调整后余额需大于0"),o.num="")}),(e,a)=>{const r=I,_=S,C=j,b=T,N=F;return q(),B(L,{ref_key:"popupRef",ref:m,title:"余额调整",width:"500px",onConfirm:x,async:!0,onClose:E},{default:l(()=>[D("div",M,[t(N,{ref_key:"formRef",ref:s,model:n(o),"label-width":"120px",rules:R},{default:l(()=>[t(r,{label:"当前余额"},{default:l(()=>[u("¥ "+w(d.value),1)]),_:1}),t(r,{label:"余额增减",required:"",prop:"action"},{default:l(()=>[t(C,{modelValue:n(o).action,"onUpdate:modelValue":a[0]||(a[0]=p=>n(o).action=p)},{default:l(()=>[t(_,{value:1},{default:l(()=>[...a[2]||(a[2]=[u("增加余额",-1)])]),_:1}),t(_,{value:2},{default:l(()=>[...a[3]||(a[3]=[u("扣减余额",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(r,{label:"调整余额",prop:"num"},{default:l(()=>[t(b,{"model-value":n(o).num,placeholder:"请输入调整的金额",type:"number",onInput:g},null,8,["model-value"])]),_:1}),t(r,{label:"调整后余额"},{default:l(()=>[u(" ¥ "+w(n(c)),1)]),_:1}),t(r,{label:"备注",prop:"remark"},{default:l(()=>[t(b,{modelValue:n(o).remark,"onUpdate:modelValue":a[1]||(a[1]=p=>n(o).remark=p),type:"textarea",rows:4},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])])]),_:1},512)}}});export{H as _};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";import"./.pnpm-BSw4l71J.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";import"./.pnpm-BSw4l71J.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as E,q as p,r as C,s as l,v as a,u as c,bQ as B,C as N,D as d,O as $,b7 as z,b6 as D,I,K as A,L,p as R}from"./.pnpm-BSw4l71J.js";import{_ as q}from"./index-Du0eYB29.js";import{_ as F}from"./picker-B4EVDozl.js";import{_ as K}from"./picker-C_3iViNJ.js";import{c as O,i as r}from"./index-BWlhxa68.js";const P={class:"bg-fill-light flex items-center w-full p-4 mb-4"},Q={class:"upload-btn w-[60px] h-[60px]"},S={class:"ml-3 flex-1"},T={class:"flex items-center"},j={class:"flex items-center mt-[18px]"},G={class:"flex-1 flex items-center"},H={class:"drag-move cursor-move ml-auto"},Z=E({__name:"add-nav",props:{modelValue:{type:Array,default:()=>[]},max:{type:Number,default:100},min:{type:Number,default:1}},emits:["update:modelValue"],setup(_,{emit:f}){const t=_,V=f,m=R({get(){return t.modelValue},set(s){V("update:modelValue",s)}}),x=()=>{var s;((s=t.modelValue)==null?void 0:s.length)<t.max?m.value.push({image:"",name:"导航名称",link:{},is_show:"1"}):r.msgError(`最多添加${t.max}个`)},v=s=>{var e;if(((e=t.modelValue)==null?void 0:e.length)<=t.min)return r.msgError(`最少保留${t.min}个`);m.value.splice(s,1)};return(s,e)=>{const u=O,g=K,b=z,h=F,k=I,w=D,y=q,U=A;return p(),C("div",null,[l("div",null,[a(c(B),{class:"draggable",modelValue:c(m),"onUpdate:modelValue":e[0]||(e[0]=o=>N(m)?m.value=o:null),animation:"300",handle:".drag-move","item-key":"index"},{item:d(({element:o,index:i})=>[(p(),$(y,{class:"w-[467px]",key:i,onClose:n=>v(i)},{default:d(()=>[l("div",P,[a(g,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body",size:"60px","exclude-domain":""},{upload:d(()=>[l("div",Q,[a(u,{name:"el-icon-Plus",size:20})])]),_:1},8,["modelValue","onUpdate:modelValue"]),l("div",S,[l("div",T,[e[1]||(e[1]=l("span",{class:"text-tx-regular flex-none mr-3"},"名称",-1)),a(b,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),l("div",j,[e[2]||(e[2]=l("span",{class:"text-tx-regular flex-none mr-3"},"链接",-1)),a(h,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])]),a(w,{label:"是否显示",class:"mt-[18px]"},{default:d(()=>[l("div",G,[a(k,{modelValue:o.is_show,"onUpdate:modelValue":n=>o.is_show=n,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),l("div",H,[a(u,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"])]),l("div",null,[a(U,{type:"primary",onClick:x},{default:d(()=>[...e[3]||(e[3]=[L("添加",-1)])]),_:1})])])}}});export{Z as _};
|
import{o as E,q as p,r as C,s as l,v as a,u as c,bQ as B,C as N,D as d,O as $,b7 as z,b6 as D,I,K as A,L,p as R}from"./.pnpm-BSw4l71J.js";import{_ as q}from"./index-D7nDUOel.js";import{_ as F}from"./picker-D0OtRCxO.js";import{_ as K}from"./picker-GVLgWOJW.js";import{c as O,i as r}from"./index-CQbHw_bK.js";const P={class:"bg-fill-light flex items-center w-full p-4 mb-4"},Q={class:"upload-btn w-[60px] h-[60px]"},S={class:"ml-3 flex-1"},T={class:"flex items-center"},j={class:"flex items-center mt-[18px]"},G={class:"flex-1 flex items-center"},H={class:"drag-move cursor-move ml-auto"},Z=E({__name:"add-nav",props:{modelValue:{type:Array,default:()=>[]},max:{type:Number,default:100},min:{type:Number,default:1}},emits:["update:modelValue"],setup(_,{emit:f}){const t=_,V=f,m=R({get(){return t.modelValue},set(s){V("update:modelValue",s)}}),x=()=>{var s;((s=t.modelValue)==null?void 0:s.length)<t.max?m.value.push({image:"",name:"导航名称",link:{},is_show:"1"}):r.msgError(`最多添加${t.max}个`)},v=s=>{var e;if(((e=t.modelValue)==null?void 0:e.length)<=t.min)return r.msgError(`最少保留${t.min}个`);m.value.splice(s,1)};return(s,e)=>{const u=O,g=K,b=z,h=F,k=I,w=D,y=q,U=A;return p(),C("div",null,[l("div",null,[a(c(B),{class:"draggable",modelValue:c(m),"onUpdate:modelValue":e[0]||(e[0]=o=>N(m)?m.value=o:null),animation:"300",handle:".drag-move","item-key":"index"},{item:d(({element:o,index:i})=>[(p(),$(y,{class:"w-[467px]",key:i,onClose:n=>v(i)},{default:d(()=>[l("div",P,[a(g,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body",size:"60px","exclude-domain":""},{upload:d(()=>[l("div",Q,[a(u,{name:"el-icon-Plus",size:20})])]),_:1},8,["modelValue","onUpdate:modelValue"]),l("div",S,[l("div",T,[e[1]||(e[1]=l("span",{class:"text-tx-regular flex-none mr-3"},"名称",-1)),a(b,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),l("div",j,[e[2]||(e[2]=l("span",{class:"text-tx-regular flex-none mr-3"},"链接",-1)),a(h,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])]),a(w,{label:"是否显示",class:"mt-[18px]"},{default:d(()=>[l("div",G,[a(k,{modelValue:o.is_show,"onUpdate:modelValue":n=>o.is_show=n,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),l("div",H,[a(u,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"])]),l("div",null,[a(U,{type:"primary",onClick:x},{default:d(()=>[...e[3]||(e[3]=[L("添加",-1)])]),_:1})])])}}});export{Z as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as n}from"./index-BWlhxa68.js";function e(t){return n.get({url:"/auth.admin/lists",params:t},{ignoreCancelToken:!0})}function i(t){return n.post({url:"/auth.admin/add",params:t})}function r(t){return n.post({url:"/auth.admin/edit",params:t})}function u(t){return n.post({url:"/auth.admin/delete",params:t})}function d(t){return n.get({url:"/auth.admin/detail",params:t})}export{e as a,r as b,u as c,i as d,d as e};
|
import{r as n}from"./index-CQbHw_bK.js";function e(t){return n.get({url:"/auth.admin/lists",params:t},{ignoreCancelToken:!0})}function i(t){return n.post({url:"/auth.admin/add",params:t})}function r(t){return n.post({url:"/auth.admin/edit",params:t})}function u(t){return n.post({url:"/auth.admin/delete",params:t})}function d(t){return n.get({url:"/auth.admin/detail",params:t})}export{e as a,r as b,u as c,i as d,d as e};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as e}from"./index-BWlhxa68.js";function a(t){return e.get({url:"/article.articleCate/lists",params:t})}function l(t){return e.get({url:"/article.articleCate/all",params:t})}function i(t){return e.post({url:"/article.articleCate/add",params:t})}function c(t){return e.post({url:"/article.articleCate/edit",params:t})}function u(t){return e.post({url:"/article.articleCate/delete",params:t})}function n(t){return e.get({url:"/article.articleCate/detail",params:t})}function s(t){return e.post({url:"/article.articleCate/updateStatus",params:t})}function o(t){return e.get({url:"/article.article/lists",params:t})}function d(t){return e.post({url:"/article.article/add",params:t})}function f(t){return e.post({url:"/article.article/edit",params:t})}function C(t){return e.post({url:"/article.article/delete",params:t})}function p(t){return e.get({url:"/article.article/detail",params:t})}function g(t){return e.post({url:"/article.article/updateStatus",params:t})}export{a,u as b,s as c,c as d,i as e,n as f,p as g,f as h,d as i,l as j,o as k,g as l,C as m};
|
import{r as e}from"./index-CQbHw_bK.js";function a(t){return e.get({url:"/article.articleCate/lists",params:t})}function l(t){return e.get({url:"/article.articleCate/all",params:t})}function i(t){return e.post({url:"/article.articleCate/add",params:t})}function c(t){return e.post({url:"/article.articleCate/edit",params:t})}function u(t){return e.post({url:"/article.articleCate/delete",params:t})}function n(t){return e.get({url:"/article.articleCate/detail",params:t})}function s(t){return e.post({url:"/article.articleCate/updateStatus",params:t})}function o(t){return e.get({url:"/article.article/lists",params:t})}function d(t){return e.post({url:"/article.article/add",params:t})}function f(t){return e.post({url:"/article.article/edit",params:t})}function C(t){return e.post({url:"/article.article/delete",params:t})}function p(t){return e.get({url:"/article.article/detail",params:t})}function g(t){return e.post({url:"/article.article/updateStatus",params:t})}export{a,u as b,s as c,c as d,i as e,n as f,p as g,f as h,d as i,l as j,o as k,g as l,C as m};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as e}from"./index-BWlhxa68.js";function r(s){return e.get({url:"/asset.AssetUser/lists",params:s})}function u(s){return e.post({url:"/asset.AssetUser/add",params:s})}function a(s){return e.post({url:"/asset.AssetUser/edit",params:s})}function i(s){return e.post({url:"/asset.AssetUser/delete",params:s})}function o(s){return e.get({url:"/asset.AssetResource/lists",params:s})}function n(s){return e.post({url:"/asset.AssetResource/add",params:s})}function A(s){return e.post({url:"/asset.AssetResource/edit",params:s})}function c(s){return e.post({url:"/asset.AssetResource/delete",params:s})}export{o as a,c as b,A as c,n as d,r as e,a as f,i as g,u as h};
|
import{r as e}from"./index-CQbHw_bK.js";function r(s){return e.get({url:"/asset.AssetUser/lists",params:s})}function u(s){return e.post({url:"/asset.AssetUser/add",params:s})}function a(s){return e.post({url:"/asset.AssetUser/edit",params:s})}function i(s){return e.post({url:"/asset.AssetUser/delete",params:s})}function o(s){return e.get({url:"/asset.AssetResource/lists",params:s})}function n(s){return e.post({url:"/asset.AssetResource/add",params:s})}function A(s){return e.post({url:"/asset.AssetResource/edit",params:s})}function c(s){return e.post({url:"/asset.AssetResource/delete",params:s})}export{o as a,c as b,A as c,n as d,r as e,a as f,i as g,u as h};
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-CIWDdzC0.js";import"./.pnpm-BSw4l71J.js";import"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-v5ByQeMO.js";import"./.pnpm-BSw4l71J.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";export{o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-DOQJNCXj.js";import"./.pnpm-BSw4l71J.js";import"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-xgAFCbr-.js";import"./.pnpm-BSw4l71J.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import"./picker-C_3iViNJ.js";import"./index-IBEgpZdk.js";import"./index-BWlhxa68.js";import"./index-PArzJ7v1.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-Du0eYB29.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";export{o as default};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-M5jxX98n.js";import"./.pnpm-BSw4l71J.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-vjIWb05X.js";import"./.pnpm-BSw4l71J.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-C8lIxgDs.js";import"./.pnpm-BSw4l71J.js";import"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-BdCYjatm.js";import"./.pnpm-BSw4l71J.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import"./picker-GVLgWOJW.js";import"./index-BHzpLgF4.js";import"./index-CQbHw_bK.js";import"./index-CvQxbz0R.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-D7nDUOel.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";export{o as default};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-DhUhjGrV.js";import"./.pnpm-BSw4l71J.js";import"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-CeNuJ945.js";import"./.pnpm-BSw4l71J.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";export{o as default};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-CV21g8WJ.js";import"./.pnpm-BSw4l71J.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-CNu0a1pL.js";import"./.pnpm-BSw4l71J.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";export{o as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-bZoT5wvF.js";import"./.pnpm-BSw4l71J.js";import"./picker-C_3iViNJ.js";import"./index-IBEgpZdk.js";import"./index-BWlhxa68.js";import"./index-PArzJ7v1.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-Du0eYB29.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";export{o as default};
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as b,q as c,r as V,s as v,v as t,D as a,Y as x,X as E,u as l,b9 as g,F as k,p as w}from"./.pnpm-BSw4l71J.js";import{_ as p}from"./menu-set.vue_vue_type_script_setup_true_lang-CxXbGeBD.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";const $=b({__name:"attr",props:{modelValue:{type:Object,default:()=>({nav:[],menu:{}})}},emits:["update:modelValue"],setup(s,{emit:u}){const d=s,i=u,o=w({get(){return d.modelValue},set(n){i("update:modelValue",n)}});return(n,e)=>{const r=E,f=x,_=g;return c(),V(k,null,[e[2]||(e[2]=v("div",{class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2"}," pc导航设置 ",-1)),t(_,{class:"mt-4","label-width":"70px"},{default:a(()=>[t(f,{"model-value":"nav"},{default:a(()=>[t(r,{label:"主导航设置",name:"nav"},{default:a(()=>[t(p,{modelValue:l(o).nav,"onUpdate:modelValue":e[0]||(e[0]=m=>l(o).nav=m)},null,8,["modelValue"])]),_:1}),t(r,{label:"菜单设置",name:"menu"},{default:a(()=>[t(p,{modelValue:l(o).menu,"onUpdate:modelValue":e[1]||(e[1]=m=>l(o).menu=m)},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})],64)}}});export{$ as default};
|
import{o as b,q as c,r as V,s as v,v as t,D as a,Y as x,X as E,u as l,b9 as g,F as k,p as w}from"./.pnpm-BSw4l71J.js";import{_ as p}from"./menu-set.vue_vue_type_script_setup_true_lang-2QDmAX1Y.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";const $=b({__name:"attr",props:{modelValue:{type:Object,default:()=>({nav:[],menu:{}})}},emits:["update:modelValue"],setup(s,{emit:u}){const d=s,i=u,o=w({get(){return d.modelValue},set(n){i("update:modelValue",n)}});return(n,e)=>{const r=E,f=x,_=g;return c(),V(k,null,[e[2]||(e[2]=v("div",{class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2"}," pc导航设置 ",-1)),t(_,{class:"mt-4","label-width":"70px"},{default:a(()=>[t(f,{"model-value":"nav"},{default:a(()=>[t(r,{label:"主导航设置",name:"nav"},{default:a(()=>[t(p,{modelValue:l(o).nav,"onUpdate:modelValue":e[0]||(e[0]=m=>l(o).nav=m)},null,8,["modelValue"])]),_:1}),t(r,{label:"菜单设置",name:"menu"},{default:a(()=>[t(p,{modelValue:l(o).menu,"onUpdate:modelValue":e[1]||(e[1]=m=>l(o).menu=m)},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})],64)}}});export{$ as default};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr.vue_vue_type_script_setup_true_lang-C1hlVczi.js";import"./.pnpm-BSw4l71J.js";import"./picker-GVLgWOJW.js";import"./index-BHzpLgF4.js";import"./index-CQbHw_bK.js";import"./index-CvQxbz0R.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./index-D7nDUOel.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./usePaging-BeGcb2kN.js";export{o as default};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./attr-setting.vue_vue_type_script_setup_true_lang-DF1nvSWK.js";import"./.pnpm-BSw4l71J.js";import"./index-CFAMa2Uy.js";import"./attr-68FRjzh-.js";import"./index-D7nDUOel.js";import"./index-CQbHw_bK.js";import"./picker-D0OtRCxO.js";import"./index-BHzpLgF4.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-Bdl217L3.js";import"./usePaging-BeGcb2kN.js";import"./picker-GVLgWOJW.js";import"./index-CvQxbz0R.js";import"./index-D9144h_t.js";import"./file-zu5s28di.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./content.vue_vue_type_script_setup_true_lang-_iAcEo1Z.js";import"./decoration-img-DNIR5TnZ.js";import"./attr.vue_vue_type_script_setup_true_lang-C1hlVczi.js";import"./content-DgdLvoFc.js";import"./attr.vue_vue_type_script_setup_true_lang-CV21g8WJ.js";import"./content.vue_vue_type_script_setup_true_lang-mOLMYJe5.js";import"./attr.vue_vue_type_script_setup_true_lang-CIWDdzC0.js";import"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";import"./content-CoOZ-i_d.js";import"./attr.vue_vue_type_script_setup_true_lang-DhUhjGrV.js";import"./content.vue_vue_type_script_setup_true_lang-CYRjob1c.js";import"./attr.vue_vue_type_script_setup_true_lang-BX4gdclK.js";import"./content-BnPpTkbJ.js";import"./decoration-DDdlzi-n.js";import"./attr.vue_vue_type_script_setup_true_lang-BdCYjatm.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import"./content-V8xZXolj.js";import"./content.vue_vue_type_script_setup_true_lang-D2coawus.js";import"./attr.vue_vue_type_script_setup_true_lang-CdNAifO0.js";import"./content-_0a4H5-i.js";import"./attr.vue_vue_type_script_setup_true_lang-M5jxX98n.js";import"./content.vue_vue_type_script_setup_true_lang-C1TW7W0z.js";import"./attr.vue_vue_type_script_setup_true_lang-Cxhd7Qdg.js";import"./content-D2jPpT8k.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./attr-setting.vue_vue_type_script_setup_true_lang-BAjQj504.js";import"./.pnpm-BSw4l71J.js";import"./index-BOPo4KMm.js";import"./attr-C3r7H7UP.js";import"./index-Du0eYB29.js";import"./index-BWlhxa68.js";import"./picker-B4EVDozl.js";import"./index-IBEgpZdk.js";import"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import"./article-_SYv-ini.js";import"./usePaging-BeGcb2kN.js";import"./picker-C_3iViNJ.js";import"./index-PArzJ7v1.js";import"./index-TisaJaAB.js";import"./file-BXk5F0Ys.js";import"./index.vue_vue_type_script_setup_true_lang-D3ZtXZaD.js";import"./content.vue_vue_type_script_setup_true_lang-BUSWRMQc.js";import"./decoration-img-frlDOjkz.js";import"./attr.vue_vue_type_script_setup_true_lang-bZoT5wvF.js";import"./content-D7TY9P5J.js";import"./attr.vue_vue_type_script_setup_true_lang-CNu0a1pL.js";import"./content.vue_vue_type_script_setup_true_lang---C_n7J8.js";import"./attr.vue_vue_type_script_setup_true_lang-C8lIxgDs.js";import"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";import"./content-stjF46XH.js";import"./attr.vue_vue_type_script_setup_true_lang-DOQJNCXj.js";import"./content.vue_vue_type_script_setup_true_lang-YorKB9i2.js";import"./attr.vue_vue_type_script_setup_true_lang-BX4gdclK.js";import"./content-IYJe5Twe.js";import"./decoration-B9DxqqTF.js";import"./attr.vue_vue_type_script_setup_true_lang-xgAFCbr-.js";import"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import"./content-DbfcA86i.js";import"./content.vue_vue_type_script_setup_true_lang-IPr_LqG1.js";import"./attr.vue_vue_type_script_setup_true_lang-CdNAifO0.js";import"./content-1SM6TxNJ.js";import"./attr.vue_vue_type_script_setup_true_lang-vjIWb05X.js";import"./content.vue_vue_type_script_setup_true_lang-CXyDgMLw.js";import"./attr.vue_vue_type_script_setup_true_lang-Cxhd7Qdg.js";import"./content-udWiOD_Z.js";export{o as default};
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as g,q as a,r as b,v as c,bg as y,D as r,s as x,T as _,a2 as h,O as i,a3 as w,a4 as v,u as C}from"./.pnpm-BSw4l71J.js";import{e as k}from"./index-BOPo4KMm.js";const B={class:"pages-setting"},D={class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2 text-xl font-medium"},O=g({__name:"attr-setting",props:{widget:{type:Object,default:()=>({})},type:{type:String,default:"mobile"}},emits:["update:content"],setup(e,{emit:d}){const m=d,p=n=>{m("update:content",n)};return(n,E)=>{const f=y,u=h;return a(),b("div",B,[c(f,{shadow:"never",class:"!border-none flex"},{default:r(()=>{var t;return[x("div",D,_((t=e.widget)==null?void 0:t.title),1)]}),_:1}),c(u,{class:"w-full",style:{height:"calc(100% - 60px)"}},{default:r(()=>{var t,s,o,l;return[(a(),i(w,null,[(a(),i(v((s=C(k)[(t=e.widget)==null?void 0:t.name])==null?void 0:s.attr),{content:(o=e.widget)==null?void 0:o.content,styles:(l=e.widget)==null?void 0:l.styles,type:e.type,"onUpdate:content":p},null,40,["content","styles","type"]))],1024))]}),_:1})])}}});export{O as _};
|
import{o as g,q as a,r as b,v as c,bg as y,D as r,s as x,T as _,a2 as h,O as i,a3 as w,a4 as v,u as C}from"./.pnpm-BSw4l71J.js";import{e as k}from"./index-CFAMa2Uy.js";const B={class:"pages-setting"},D={class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2 text-xl font-medium"},O=g({__name:"attr-setting",props:{widget:{type:Object,default:()=>({})},type:{type:String,default:"mobile"}},emits:["update:content"],setup(e,{emit:d}){const m=d,p=n=>{m("update:content",n)};return(n,E)=>{const f=y,u=h;return a(),b("div",B,[c(f,{shadow:"never",class:"!border-none flex"},{default:r(()=>{var t;return[x("div",D,_((t=e.widget)==null?void 0:t.title),1)]}),_:1}),c(u,{class:"w-full",style:{height:"calc(100% - 60px)"}},{default:r(()=>{var t,s,o,l;return[(a(),i(w,null,[(a(),i(v((s=C(k)[(t=e.widget)==null?void 0:t.name])==null?void 0:s.attr),{content:(o=e.widget)==null?void 0:o.content,styles:(l=e.widget)==null?void 0:l.styles,type:e.type,"onUpdate:content":p},null,40,["content","styles","type"]))],1024))]}),_:1})])}}});export{O as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as E,q as s,O as r,D as t,v as l,bg as F,b6 as C,bc as N,u as a,bf as z,L as p,b7 as B,P as i,s as b,b9 as O,p as j}from"./.pnpm-BSw4l71J.js";import{_ as D}from"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import{_ as I}from"./picker-C_3iViNJ.js";const G=E({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(d,{emit:g}){const y=g,x=d,o=j({get:()=>x.content,set:f=>{y("update:content",f)}});return(f,e)=>{const m=z,_=N,u=C,v=B,V=I,k=D,U=F,w=O;return s(),r(w,{ref:"form","label-width":"80px",size:"large"},{default:t(()=>[l(U,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>[l(u,{label:"页面标题"},{default:t(()=>[l(_,{modelValue:a(o).title_type,"onUpdate:modelValue":e[0]||(e[0]=n=>a(o).title_type=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[7]||(e[7]=[p("文字",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[8]||(e[8]=[p("图片",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),d.content.title_type==1?(s(),r(u,{key:0},{default:t(()=>[l(v,{modelValue:a(o).title,"onUpdate:modelValue":e[1]||(e[1]=n=>a(o).title=n),maxlength:"8","show-word-limit":"",class:"w-[300px]",placeholder:"请输入页面标题"},null,8,["modelValue"])]),_:1})):i("",!0),d.content.title_type==2?(s(),r(u,{key:1},{default:t(()=>[l(V,{modelValue:a(o).title_img,"onUpdate:modelValue":e[2]||(e[2]=n=>a(o).title_img=n),limit:1,size:"100px"},null,8,["modelValue"]),e[9]||(e[9]=b("div",{class:"form-tips"},"建议图片尺寸:300px*40px",-1))]),_:1})):i("",!0),d.content.title_type==1?(s(),r(u,{key:2,label:"文字颜色"},{default:t(()=>[l(_,{modelValue:a(o).text_color,"onUpdate:modelValue":e[3]||(e[3]=n=>a(o).text_color=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[10]||(e[10]=[p("白色",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[11]||(e[11]=[p("黑色",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})):i("",!0),l(u,{label:"页面背景"},{default:t(()=>[l(_,{modelValue:a(o).bg_type,"onUpdate:modelValue":e[4]||(e[4]=n=>a(o).bg_type=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[12]||(e[12]=[p("背景颜色",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[13]||(e[13]=[p("背景图片",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),d.content.bg_type==1?(s(),r(u,{key:3},{default:t(()=>[l(k,{modelValue:a(o).bg_color,"onUpdate:modelValue":e[5]||(e[5]=n=>a(o).bg_color=n),"reset-color":"#F5F5F5"},null,8,["modelValue"])]),_:1})):i("",!0),d.content.bg_type==2?(s(),r(u,{key:4},{default:t(()=>[l(V,{modelValue:a(o).bg_image,"onUpdate:modelValue":e[6]||(e[6]=n=>a(o).bg_image=n),limit:1,size:"100px"},null,8,["modelValue"]),e[14]||(e[14]=b("div",{class:"form-tips"},"建议图片尺寸:750px*高度不限",-1))]),_:1})):i("",!0)]),_:1})]),_:1},512)}}});export{G as _};
|
import{o as E,q as s,O as r,D as t,v as l,bg as F,b6 as C,bc as N,u as a,bf as z,L as p,b7 as B,P as i,s as b,b9 as O,p as j}from"./.pnpm-BSw4l71J.js";import{_ as D}from"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";import{_ as I}from"./picker-GVLgWOJW.js";const G=E({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(d,{emit:g}){const y=g,x=d,o=j({get:()=>x.content,set:f=>{y("update:content",f)}});return(f,e)=>{const m=z,_=N,u=C,v=B,V=I,k=D,U=F,w=O;return s(),r(w,{ref:"form","label-width":"80px",size:"large"},{default:t(()=>[l(U,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>[l(u,{label:"页面标题"},{default:t(()=>[l(_,{modelValue:a(o).title_type,"onUpdate:modelValue":e[0]||(e[0]=n=>a(o).title_type=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[7]||(e[7]=[p("文字",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[8]||(e[8]=[p("图片",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),d.content.title_type==1?(s(),r(u,{key:0},{default:t(()=>[l(v,{modelValue:a(o).title,"onUpdate:modelValue":e[1]||(e[1]=n=>a(o).title=n),maxlength:"8","show-word-limit":"",class:"w-[300px]",placeholder:"请输入页面标题"},null,8,["modelValue"])]),_:1})):i("",!0),d.content.title_type==2?(s(),r(u,{key:1},{default:t(()=>[l(V,{modelValue:a(o).title_img,"onUpdate:modelValue":e[2]||(e[2]=n=>a(o).title_img=n),limit:1,size:"100px"},null,8,["modelValue"]),e[9]||(e[9]=b("div",{class:"form-tips"},"建议图片尺寸:300px*40px",-1))]),_:1})):i("",!0),d.content.title_type==1?(s(),r(u,{key:2,label:"文字颜色"},{default:t(()=>[l(_,{modelValue:a(o).text_color,"onUpdate:modelValue":e[3]||(e[3]=n=>a(o).text_color=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[10]||(e[10]=[p("白色",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[11]||(e[11]=[p("黑色",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})):i("",!0),l(u,{label:"页面背景"},{default:t(()=>[l(_,{modelValue:a(o).bg_type,"onUpdate:modelValue":e[4]||(e[4]=n=>a(o).bg_type=n)},{default:t(()=>[l(m,{value:"1"},{default:t(()=>[...e[12]||(e[12]=[p("背景颜色",-1)])]),_:1}),l(m,{value:"2"},{default:t(()=>[...e[13]||(e[13]=[p("背景图片",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),d.content.bg_type==1?(s(),r(u,{key:3},{default:t(()=>[l(k,{modelValue:a(o).bg_color,"onUpdate:modelValue":e[5]||(e[5]=n=>a(o).bg_color=n),"reset-color":"#F5F5F5"},null,8,["modelValue"])]),_:1})):i("",!0),d.content.bg_type==2?(s(),r(u,{key:4},{default:t(()=>[l(V,{modelValue:a(o).bg_image,"onUpdate:modelValue":e[6]||(e[6]=n=>a(o).bg_image=n),limit:1,size:"100px"},null,8,["modelValue"]),e[14]||(e[14]=b("div",{class:"form-tips"},"建议图片尺寸:750px*高度不限",-1))]),_:1})):i("",!0)]),_:1})]),_:1},512)}}});export{G as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as V,q as b,r as w,v as e,D as n,bg as x,b6 as g,b7 as k,u as o,s as E,b9 as U,p as v}from"./.pnpm-BSw4l71J.js";import{_ as q}from"./picker-C_3iViNJ.js";const C=V({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(u,{emit:p}){const r=p,i=u,l=v({get:()=>i.content,set:d=>{r("update:content",d)}});return(d,t)=>{const s=k,m=g,_=q,c=x,f=U;return b(),w("div",null,[e(f,{"label-width":"90px",size:"large","label-position":"top"},{default:n(()=>[e(c,{shadow:"never",class:"!border-none flex mt-2"},{default:n(()=>[e(m,{label:"平台名称"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).title,"onUpdate:modelValue":t[0]||(t[0]=a=>o(l).title=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"客服二维码"},{default:n(()=>[E("div",null,[e(_,{modelValue:o(l).qrcode,"onUpdate:modelValue":t[1]||(t[1]=a=>o(l).qrcode=a),"exclude-domain":""},null,8,["modelValue"])])]),_:1}),e(m,{label:"备注"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).remark,"onUpdate:modelValue":t[2]||(t[2]=a=>o(l).remark=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"联系电话"},{default:n(()=>[e(s,{class:"w-[400px]",modelValue:o(l).mobile,"onUpdate:modelValue":t[3]||(t[3]=a=>o(l).mobile=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"服务时间"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).time,"onUpdate:modelValue":t[4]||(t[4]=a=>o(l).time=a)},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})])}}});export{C as _};
|
import{o as V,q as b,r as w,v as e,D as n,bg as x,b6 as g,b7 as k,u as o,s as E,b9 as U,p as v}from"./.pnpm-BSw4l71J.js";import{_ as q}from"./picker-GVLgWOJW.js";const C=V({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(u,{emit:p}){const r=p,i=u,l=v({get:()=>i.content,set:d=>{r("update:content",d)}});return(d,t)=>{const s=k,m=g,_=q,c=x,f=U;return b(),w("div",null,[e(f,{"label-width":"90px",size:"large","label-position":"top"},{default:n(()=>[e(c,{shadow:"never",class:"!border-none flex mt-2"},{default:n(()=>[e(m,{label:"平台名称"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).title,"onUpdate:modelValue":t[0]||(t[0]=a=>o(l).title=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"客服二维码"},{default:n(()=>[E("div",null,[e(_,{modelValue:o(l).qrcode,"onUpdate:modelValue":t[1]||(t[1]=a=>o(l).qrcode=a),"exclude-domain":""},null,8,["modelValue"])])]),_:1}),e(m,{label:"备注"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).remark,"onUpdate:modelValue":t[2]||(t[2]=a=>o(l).remark=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"联系电话"},{default:n(()=>[e(s,{class:"w-[400px]",modelValue:o(l).mobile,"onUpdate:modelValue":t[3]||(t[3]=a=>o(l).mobile=a)},null,8,["modelValue"])]),_:1}),e(m,{label:"服务时间"},{default:n(()=>[e(s,{class:"w-[400px]","show-word-limit":"",maxlength:"20",modelValue:o(l).time,"onUpdate:modelValue":t[4]||(t[4]=a=>o(l).time=a)},null,8,["modelValue"])]),_:1})]),_:1})]),_:1})])}}});export{C as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as V,q as E,r as w,v as t,D as o,bg as y,b6 as g,b7 as B,u as s,s as a,bc as C,bf as N,L as u,b9 as U,p as j}from"./.pnpm-BSw4l71J.js";import{_ as k}from"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";const D={class:"flex-1"},O=V({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(p,{emit:i}){const f=i,_=p,l=j({get:()=>_.content,set:m=>{f("update:content",m)}});return(m,e)=>{const x=B,c=g,d=y,r=N,b=C,v=U;return E(),w("div",null,[t(v,{"label-width":"70px"},{default:o(()=>[t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[t(c,{label:"标题"},{default:o(()=>[t(x,{class:"w-[396px]",modelValue:s(l).title,"onUpdate:modelValue":e[0]||(e[0]=n=>s(l).title=n)},null,8,["modelValue"])]),_:1})]),_:1}),t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[5]||(e[5]=a("div",{class:"flex items-end mb-4"},[a("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),t(b,{modelValue:s(l).style,"onUpdate:modelValue":e[1]||(e[1]=n=>s(l).style=n)},{default:o(()=>[t(r,{value:1},{default:o(()=>[...e[3]||(e[3]=[u("横排",-1)])]),_:1}),t(r,{value:2},{default:o(()=>[...e[4]||(e[4]=[u("竖排",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[6]||(e[6]=a("div",{class:"flex items-end mb-4"},[a("div",{class:"text-base text-[#101010] font-medium"},"菜单"),a("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),a("div",D,[t(k,{modelValue:s(l).data,"onUpdate:modelValue":e[2]||(e[2]=n=>s(l).data=n)},null,8,["modelValue"])])]),_:1})]),_:1})])}}});export{O as _};
|
import{o as V,q as E,r as w,v as t,D as o,bg as y,b6 as g,b7 as B,u as s,s as a,bc as C,bf as N,L as u,b9 as U,p as j}from"./.pnpm-BSw4l71J.js";import{_ as k}from"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";const D={class:"flex-1"},O=V({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(p,{emit:i}){const f=i,_=p,l=j({get:()=>_.content,set:m=>{f("update:content",m)}});return(m,e)=>{const x=B,c=g,d=y,r=N,b=C,v=U;return E(),w("div",null,[t(v,{"label-width":"70px"},{default:o(()=>[t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[t(c,{label:"标题"},{default:o(()=>[t(x,{class:"w-[396px]",modelValue:s(l).title,"onUpdate:modelValue":e[0]||(e[0]=n=>s(l).title=n)},null,8,["modelValue"])]),_:1})]),_:1}),t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[5]||(e[5]=a("div",{class:"flex items-end mb-4"},[a("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),t(b,{modelValue:s(l).style,"onUpdate:modelValue":e[1]||(e[1]=n=>s(l).style=n)},{default:o(()=>[t(r,{value:1},{default:o(()=>[...e[3]||(e[3]=[u("横排",-1)])]),_:1}),t(r,{value:2},{default:o(()=>[...e[4]||(e[4]=[u("竖排",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(d,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[6]||(e[6]=a("div",{class:"flex items-end mb-4"},[a("div",{class:"text-base text-[#101010] font-medium"},"菜单"),a("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),a("div",D,[t(k,{modelValue:s(l).data,"onUpdate:modelValue":e[2]||(e[2]=n=>s(l).data=n)},null,8,["modelValue"])])]),_:1})]),_:1})])}}});export{O as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as j,q as d,r as b,v as o,D as s,bg as F,s as n,u as p,bQ as S,O as _,b6 as q,P as r,b7 as z,I as A,K,L,b9 as P,p as Q,cm as v}from"./.pnpm-BSw4l71J.js";import{_ as R}from"./index-Du0eYB29.js";import{c as T,i as k}from"./index-BWlhxa68.js";import{_ as G}from"./picker-B4EVDozl.js";import{_ as H}from"./picker-C_3iViNJ.js";const J={class:"flex-1"},M={class:"bg-fill-light w-full p-4 mt-4"},W={class:"flex-1"},X={class:"flex-1 flex items-center"},Y={class:"drag-move cursor-move ml-auto"},Z={key:0,class:"mt-4"},f=5,ae=j({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})},type:{type:String,default:"mobile"}},emits:["update:content"],setup(m,{emit:y}){const u=y,c=m,g=Q({get:()=>c.content,set:a=>{u("update:content",a)}}),w=()=>{var a;if(((a=c.content.data)==null?void 0:a.length)<f){const e=v(c.content);e.data.push({is_show:"1",image:"",name:"",link:{}}),u("update:content",e)}else k.msgError(`最多添加${f}张图片`)},E=a=>{var i;if(((i=c.content.data)==null?void 0:i.length)<=1)return k.msgError("最少保留一张图片");const e=v(c.content);e.data.splice(a,1),u("update:content",e)};return(a,e)=>{const i=H,U=G,C=z,h=q,B=A,D=T,N=R,$=K,I=F,O=P;return d(),b("div",null,[o(O,{"label-width":"70px"},{default:s(()=>[o(I,{shadow:"never",class:"!border-none flex mt-2"},{default:s(()=>{var x;return[e[2]||(e[2]=n("div",{class:"flex items-end"},[n("div",{class:"text-base text-[#101010] font-medium"},"图片设置"),n("div",{class:"text-xs text-tx-secondary ml-2"}," 最多添加5张,建议图片尺寸:750px*200px ")],-1)),n("div",J,[o(p(S),{class:"draggable",modelValue:p(g).data,"onUpdate:modelValue":e[0]||(e[0]=t=>p(g).data=t),animation:"300",handle:".drag-move"},{item:s(({element:t,index:V})=>[(d(),_(N,{key:V,onClose:l=>E(V),class:"w-full"},{default:s(()=>[n("div",M,[o(i,{width:"396px",height:"196px",modelValue:t.image,"onUpdate:modelValue":l=>t.image=l,"upload-class":"bg-body","exclude-domain":""},null,8,["modelValue","onUpdate:modelValue"]),n("div",W,[o(h,{class:"mt-[18px]",label:"图片链接"},{default:s(()=>[m.type=="mobile"?(d(),_(U,{key:0,modelValue:t.link,"onUpdate:modelValue":l=>t.link=l},null,8,["modelValue","onUpdate:modelValue"])):r("",!0),m.type=="pc"?(d(),_(C,{key:1,placeholder:"请输入链接",modelValue:t.link.path,"onUpdate:modelValue":l=>t.link.path=l},null,8,["modelValue","onUpdate:modelValue"])):r("",!0)]),_:2},1024),o(h,{label:"是否显示",class:"mt-[18px] !mb-0"},{default:s(()=>[n("div",X,[o(B,{modelValue:t.is_show,"onUpdate:modelValue":l=>t.is_show=l,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),n("div",Y,[o(D,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"])]),((x=m.content.data)==null?void 0:x.length)<f?(d(),b("div",Z,[o($,{class:"w-full",type:"primary",onClick:w},{default:s(()=>[...e[1]||(e[1]=[L("添加图片",-1)])]),_:1})])):r("",!0)]}),_:1})]),_:1})])}}});export{ae as _};
|
import{o as j,q as d,r as b,v as o,D as s,bg as F,s as n,u as p,bQ as S,O as _,b6 as q,P as r,b7 as z,I as A,K,L,b9 as P,p as Q,cm as v}from"./.pnpm-BSw4l71J.js";import{_ as R}from"./index-D7nDUOel.js";import{c as T,i as k}from"./index-CQbHw_bK.js";import{_ as G}from"./picker-D0OtRCxO.js";import{_ as H}from"./picker-GVLgWOJW.js";const J={class:"flex-1"},M={class:"bg-fill-light w-full p-4 mt-4"},W={class:"flex-1"},X={class:"flex-1 flex items-center"},Y={class:"drag-move cursor-move ml-auto"},Z={key:0,class:"mt-4"},f=5,ae=j({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})},type:{type:String,default:"mobile"}},emits:["update:content"],setup(m,{emit:y}){const u=y,c=m,g=Q({get:()=>c.content,set:a=>{u("update:content",a)}}),w=()=>{var a;if(((a=c.content.data)==null?void 0:a.length)<f){const e=v(c.content);e.data.push({is_show:"1",image:"",name:"",link:{}}),u("update:content",e)}else k.msgError(`最多添加${f}张图片`)},E=a=>{var i;if(((i=c.content.data)==null?void 0:i.length)<=1)return k.msgError("最少保留一张图片");const e=v(c.content);e.data.splice(a,1),u("update:content",e)};return(a,e)=>{const i=H,U=G,C=z,h=q,B=A,D=T,N=R,$=K,I=F,O=P;return d(),b("div",null,[o(O,{"label-width":"70px"},{default:s(()=>[o(I,{shadow:"never",class:"!border-none flex mt-2"},{default:s(()=>{var x;return[e[2]||(e[2]=n("div",{class:"flex items-end"},[n("div",{class:"text-base text-[#101010] font-medium"},"图片设置"),n("div",{class:"text-xs text-tx-secondary ml-2"}," 最多添加5张,建议图片尺寸:750px*200px ")],-1)),n("div",J,[o(p(S),{class:"draggable",modelValue:p(g).data,"onUpdate:modelValue":e[0]||(e[0]=t=>p(g).data=t),animation:"300",handle:".drag-move"},{item:s(({element:t,index:V})=>[(d(),_(N,{key:V,onClose:l=>E(V),class:"w-full"},{default:s(()=>[n("div",M,[o(i,{width:"396px",height:"196px",modelValue:t.image,"onUpdate:modelValue":l=>t.image=l,"upload-class":"bg-body","exclude-domain":""},null,8,["modelValue","onUpdate:modelValue"]),n("div",W,[o(h,{class:"mt-[18px]",label:"图片链接"},{default:s(()=>[m.type=="mobile"?(d(),_(U,{key:0,modelValue:t.link,"onUpdate:modelValue":l=>t.link=l},null,8,["modelValue","onUpdate:modelValue"])):r("",!0),m.type=="pc"?(d(),_(C,{key:1,placeholder:"请输入链接",modelValue:t.link.path,"onUpdate:modelValue":l=>t.link.path=l},null,8,["modelValue","onUpdate:modelValue"])):r("",!0)]),_:2},1024),o(h,{label:"是否显示",class:"mt-[18px] !mb-0"},{default:s(()=>[n("div",X,[o(B,{modelValue:t.is_show,"onUpdate:modelValue":l=>t.is_show=l,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),n("div",Y,[o(D,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"])]),((x=m.content.data)==null?void 0:x.length)<f?(d(),b("div",Z,[o($,{class:"w-full",type:"primary",onClick:w},{default:s(()=>[...e[1]||(e[1]=[L("添加图片",-1)])]),_:1})])):r("",!0)]}),_:1})]),_:1})])}}});export{ae as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as j,q as V,r as v,v as e,D as t,s,L as h,bg as q,b6 as A,u as m,bQ as K,ae as M,b7 as O,I as Q,K as R,T as w,P as G,b9 as H,F as J,p as y}from"./.pnpm-BSw4l71J.js";import{_ as W}from"./index-Du0eYB29.js";import{_ as X}from"./picker-B4EVDozl.js";import{_ as Y}from"./picker-C_3iViNJ.js";import{c as Z,i as b}from"./index-BWlhxa68.js";import{_ as ee}from"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";const le={class:"mb-[18px] max-w-[400px]"},oe={class:"bg-fill-light w-full p-4 mt-4"},te={class:"upload-btn w-[60px] h-[60px]"},se={class:"upload-btn w-[60px] h-[60px]"},ae={class:"flex-1 flex items-center"},ne={class:"drag-move cursor-move ml-auto"},de={key:0,class:"mt-4"},c=5,p=2,_e=j({__name:"attr",props:{modelValue:{type:Object,default:()=>({list:[],style:{}})}},emits:["update:modelValue"],setup(k,{emit:U}){const C=k,E=U,n=y({get(){return C.modelValue},set(a){E("update:modelValue",a)}}),$=y(()=>{var a;return((a=n.value.list)==null?void 0:a.filter(l=>l.is_show=="1"))||[]}),z=()=>{var a;((a=n.value.list)==null?void 0:a.length)<c?n.value.list.push({name:"",selected:"",unselected:"",is_show:1,link:{}}):b.msgError(`最多添加${c}个`)},B=a=>{var l;if(((l=n.value.list)==null?void 0:l.length)<=p)return b.msgError(`最少保留${p}个`);n.value.list.splice(a,1)},D=a=>a.relatedContext.index!=0,F=a=>{if($.value.length<p)return a.is_show=1,b.msgError(`最少显示${p}个`)};return(a,l)=>{const _=q,x=ee,i=A,f=Z,g=Y,N=O,I=X,P=Q,S=W,T=R,L=H;return V(),v(J,null,[e(_,{shadow:"never",class:"!border-none flex"},{default:t(()=>[...l[3]||(l[3]=[s("div",{class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2 text-xl font-medium"},[h(" 底部导航设置 "),s("span",{class:"form-tips ml-[10px] !mt-0"}," 至少添加2个导航,最多添加5个导航 ")],-1)])]),_:1}),e(L,{"label-width":"70px"},{default:t(()=>[e(_,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>[l[4]||(l[4]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),e(i,{label:"默认颜色"},{default:t(()=>[e(x,{class:"max-w-[400px]",modelValue:m(n).style.default_color,"onUpdate:modelValue":l[0]||(l[0]=u=>m(n).style.default_color=u),"default-color":"#999999"},null,8,["modelValue"])]),_:1}),e(i,{label:"选中颜色",style:{"margin-bottom":"0"}},{default:t(()=>[e(x,{class:"max-w-[400px]",modelValue:m(n).style.selected_color,"onUpdate:modelValue":l[1]||(l[1]=u=>m(n).style.selected_color=u),"default-color":"#4173ff"},null,8,["modelValue"])]),_:1})]),_:1}),e(_,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>{var u;return[l[7]||(l[7]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单设置"),s("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),s("div",le,[e(m(K),{class:"draggable",modelValue:m(n).list,"onUpdate:modelValue":l[2]||(l[2]=o=>m(n).list=o),animation:"300",draggable:".draggable",handle:".drag-move",move:D,"item-key":"index"},{item:t(({element:o,index:r})=>[e(S,{onClose:d=>B(r),class:M(["max-w-[400px]",{draggable:r!=0}]),"show-close":r!==0},{default:t(()=>[s("div",oe,[e(i,{label:"导航图标"},{default:t(()=>[e(g,{modelValue:o.unselected,"onUpdate:modelValue":d=>o.unselected=d,"upload-class":"bg-body","exclude-domain":"",size:"60px"},{upload:t(()=>[s("div",te,[e(f,{name:"el-icon-Plus",size:16}),l[5]||(l[5]=s("span",{class:"text-xs leading-5"}," 未选中 ",-1))])]),_:1},8,["modelValue","onUpdate:modelValue"]),e(g,{modelValue:o.selected,"onUpdate:modelValue":d=>o.selected=d,"exclude-domain":"","upload-class":"bg-body",size:"60px"},{upload:t(()=>[s("div",se,[e(f,{name:"el-icon-Plus",size:16}),l[6]||(l[6]=s("span",{class:"text-xs leading-5"}," 选中 ",-1))])]),_:1},8,["modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"导航名称"},{default:t(()=>[e(N,{modelValue:o.name,"onUpdate:modelValue":d=>o.name=d,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"链接地址"},{default:t(()=>[e(I,{"is-tab":!0,disabled:r===0,modelValue:o.link,"onUpdate:modelValue":d=>o.link=d},null,8,["disabled","modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"是否显示"},{default:t(()=>[s("div",ae,[e(P,{disabled:r==0,modelValue:o.is_show,"onUpdate:modelValue":d=>o.is_show=d,"active-value":1,"inactive-value":0,onChange:d=>F(o)},null,8,["disabled","modelValue","onUpdate:modelValue","onChange"]),s("div",ne,[e(f,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])]),_:2},1032,["onClose","show-close","class"])]),_:1},8,["modelValue"])]),((u=m(n).list)==null?void 0:u.length)<c?(V(),v("div",de,[e(T,{class:"w-full",type:"primary",onClick:z},{default:t(()=>{var o;return[h(" 添加导航 "+w((o=m(n).list)==null?void 0:o.length)+" / "+w(c),1)]}),_:1})])):G("",!0)]}),_:1})]),_:1})],64)}}});export{_e as _};
|
import{o as j,q as V,r as v,v as e,D as t,s,L as h,bg as q,b6 as A,u as m,bQ as K,ae as M,b7 as O,I as Q,K as R,T as w,P as G,b9 as H,F as J,p as y}from"./.pnpm-BSw4l71J.js";import{_ as W}from"./index-D7nDUOel.js";import{_ as X}from"./picker-D0OtRCxO.js";import{_ as Y}from"./picker-GVLgWOJW.js";import{c as Z,i as b}from"./index-CQbHw_bK.js";import{_ as ee}from"./index.vue_vue_type_script_setup_true_lang-D6YizxbY.js";const le={class:"mb-[18px] max-w-[400px]"},oe={class:"bg-fill-light w-full p-4 mt-4"},te={class:"upload-btn w-[60px] h-[60px]"},se={class:"upload-btn w-[60px] h-[60px]"},ae={class:"flex-1 flex items-center"},ne={class:"drag-move cursor-move ml-auto"},de={key:0,class:"mt-4"},c=5,p=2,_e=j({__name:"attr",props:{modelValue:{type:Object,default:()=>({list:[],style:{}})}},emits:["update:modelValue"],setup(k,{emit:U}){const C=k,E=U,n=y({get(){return C.modelValue},set(a){E("update:modelValue",a)}}),$=y(()=>{var a;return((a=n.value.list)==null?void 0:a.filter(l=>l.is_show=="1"))||[]}),z=()=>{var a;((a=n.value.list)==null?void 0:a.length)<c?n.value.list.push({name:"",selected:"",unselected:"",is_show:1,link:{}}):b.msgError(`最多添加${c}个`)},B=a=>{var l;if(((l=n.value.list)==null?void 0:l.length)<=p)return b.msgError(`最少保留${p}个`);n.value.list.splice(a,1)},D=a=>a.relatedContext.index!=0,F=a=>{if($.value.length<p)return a.is_show=1,b.msgError(`最少显示${p}个`)};return(a,l)=>{const _=q,x=ee,i=A,f=Z,g=Y,N=O,I=X,P=Q,S=W,T=R,L=H;return V(),v(J,null,[e(_,{shadow:"never",class:"!border-none flex"},{default:t(()=>[...l[3]||(l[3]=[s("div",{class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2 text-xl font-medium"},[h(" 底部导航设置 "),s("span",{class:"form-tips ml-[10px] !mt-0"}," 至少添加2个导航,最多添加5个导航 ")],-1)])]),_:1}),e(L,{"label-width":"70px"},{default:t(()=>[e(_,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>[l[4]||(l[4]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),e(i,{label:"默认颜色"},{default:t(()=>[e(x,{class:"max-w-[400px]",modelValue:m(n).style.default_color,"onUpdate:modelValue":l[0]||(l[0]=u=>m(n).style.default_color=u),"default-color":"#999999"},null,8,["modelValue"])]),_:1}),e(i,{label:"选中颜色",style:{"margin-bottom":"0"}},{default:t(()=>[e(x,{class:"max-w-[400px]",modelValue:m(n).style.selected_color,"onUpdate:modelValue":l[1]||(l[1]=u=>m(n).style.selected_color=u),"default-color":"#4173ff"},null,8,["modelValue"])]),_:1})]),_:1}),e(_,{shadow:"never",class:"!border-none flex mt-2"},{default:t(()=>{var u;return[l[7]||(l[7]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单设置"),s("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),s("div",le,[e(m(K),{class:"draggable",modelValue:m(n).list,"onUpdate:modelValue":l[2]||(l[2]=o=>m(n).list=o),animation:"300",draggable:".draggable",handle:".drag-move",move:D,"item-key":"index"},{item:t(({element:o,index:r})=>[e(S,{onClose:d=>B(r),class:M(["max-w-[400px]",{draggable:r!=0}]),"show-close":r!==0},{default:t(()=>[s("div",oe,[e(i,{label:"导航图标"},{default:t(()=>[e(g,{modelValue:o.unselected,"onUpdate:modelValue":d=>o.unselected=d,"upload-class":"bg-body","exclude-domain":"",size:"60px"},{upload:t(()=>[s("div",te,[e(f,{name:"el-icon-Plus",size:16}),l[5]||(l[5]=s("span",{class:"text-xs leading-5"}," 未选中 ",-1))])]),_:1},8,["modelValue","onUpdate:modelValue"]),e(g,{modelValue:o.selected,"onUpdate:modelValue":d=>o.selected=d,"exclude-domain":"","upload-class":"bg-body",size:"60px"},{upload:t(()=>[s("div",se,[e(f,{name:"el-icon-Plus",size:16}),l[6]||(l[6]=s("span",{class:"text-xs leading-5"}," 选中 ",-1))])]),_:1},8,["modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"导航名称"},{default:t(()=>[e(N,{modelValue:o.name,"onUpdate:modelValue":d=>o.name=d,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"链接地址"},{default:t(()=>[e(I,{"is-tab":!0,disabled:r===0,modelValue:o.link,"onUpdate:modelValue":d=>o.link=d},null,8,["disabled","modelValue","onUpdate:modelValue"])]),_:2},1024),e(i,{label:"是否显示"},{default:t(()=>[s("div",ae,[e(P,{disabled:r==0,modelValue:o.is_show,"onUpdate:modelValue":d=>o.is_show=d,"active-value":1,"inactive-value":0,onChange:d=>F(o)},null,8,["disabled","modelValue","onUpdate:modelValue","onChange"]),s("div",ne,[e(f,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])]),_:2},1032,["onClose","show-close","class"])]),_:1},8,["modelValue"])]),((u=m(n).list)==null?void 0:u.length)<c?(V(),v("div",de,[e(T,{class:"w-full",type:"primary",onClick:z},{default:t(()=>{var o;return[h(" 添加导航 "+w((o=m(n).list)==null?void 0:o.length)+" / "+w(c),1)]}),_:1})])):G("",!0)]}),_:1})]),_:1})],64)}}});export{_e as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as k,q as d,r as u,v as l,D as o,bg as F,s,bc as U,u as n,bf as B,L as x,b6 as C,bm as N,F as b,G as c,bn as O,b9 as j,p as D}from"./.pnpm-BSw4l71J.js";import{_ as G}from"./add-nav.vue_vue_type_script_setup_true_lang-B_JUXGnm.js";const L={class:"flex-1 mt-4"},I=k({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(v,{emit:V}){const y=V,w=v,a=D({get:()=>w.content,set:m=>{y("update:content",m)}});return(m,e)=>{const r=B,E=U,p=O,_=N,i=C,f=F,g=j;return d(),u("div",null,[l(g,{"label-width":"70px"},{default:o(()=>[l(f,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[6]||(e[6]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),l(E,{modelValue:n(a).style,"onUpdate:modelValue":e[0]||(e[0]=t=>n(a).style=t)},{default:o(()=>[l(r,{value:1},{default:o(()=>[...e[4]||(e[4]=[x("固定显示",-1)])]),_:1}),l(r,{value:2},{default:o(()=>[...e[5]||(e[5]=[x("分页滑动",-1)])]),_:1})]),_:1},8,["modelValue"]),l(i,{label:"每行数量",class:"mt-4"},{default:o(()=>[l(_,{modelValue:n(a).per_line,"onUpdate:modelValue":e[1]||(e[1]=t=>n(a).per_line=t),style:{width:"300px"}},{default:o(()=>[(d(),u(b,null,c(5,t=>l(p,{key:t,label:t+"个",value:t},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),l(i,{label:"显示行数"},{default:o(()=>[l(_,{modelValue:n(a).show_line,"onUpdate:modelValue":e[2]||(e[2]=t=>n(a).show_line=t),style:{width:"300px"}},{default:o(()=>[(d(),u(b,null,c(2,t=>l(p,{key:t,label:t+"行",value:t},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1})]),_:1}),l(f,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[7]||(e[7]=s("div",{class:"flex items-end"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单设置"),s("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),s("div",L,[l(G,{modelValue:n(a).data,"onUpdate:modelValue":e[3]||(e[3]=t=>n(a).data=t)},null,8,["modelValue"])])]),_:1})]),_:1})])}}});export{I as _};
|
import{o as k,q as d,r as u,v as l,D as o,bg as F,s,bc as U,u as n,bf as B,L as x,b6 as C,bm as N,F as b,G as c,bn as O,b9 as j,p as D}from"./.pnpm-BSw4l71J.js";import{_ as G}from"./add-nav.vue_vue_type_script_setup_true_lang-CT_vK854.js";const L={class:"flex-1 mt-4"},I=k({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(v,{emit:V}){const y=V,w=v,a=D({get:()=>w.content,set:m=>{y("update:content",m)}});return(m,e)=>{const r=B,E=U,p=O,_=N,i=C,f=F,g=j;return d(),u("div",null,[l(g,{"label-width":"70px"},{default:o(()=>[l(f,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[6]||(e[6]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"展示样式")],-1)),l(E,{modelValue:n(a).style,"onUpdate:modelValue":e[0]||(e[0]=t=>n(a).style=t)},{default:o(()=>[l(r,{value:1},{default:o(()=>[...e[4]||(e[4]=[x("固定显示",-1)])]),_:1}),l(r,{value:2},{default:o(()=>[...e[5]||(e[5]=[x("分页滑动",-1)])]),_:1})]),_:1},8,["modelValue"]),l(i,{label:"每行数量",class:"mt-4"},{default:o(()=>[l(_,{modelValue:n(a).per_line,"onUpdate:modelValue":e[1]||(e[1]=t=>n(a).per_line=t),style:{width:"300px"}},{default:o(()=>[(d(),u(b,null,c(5,t=>l(p,{key:t,label:t+"个",value:t},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1}),l(i,{label:"显示行数"},{default:o(()=>[l(_,{modelValue:n(a).show_line,"onUpdate:modelValue":e[2]||(e[2]=t=>n(a).show_line=t),style:{width:"300px"}},{default:o(()=>[(d(),u(b,null,c(2,t=>l(p,{key:t,label:t+"行",value:t},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),_:1})]),_:1}),l(f,{shadow:"never",class:"!border-none flex mt-2"},{default:o(()=>[e[7]||(e[7]=s("div",{class:"flex items-end"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单设置"),s("div",{class:"text-xs text-tx-secondary ml-2"},"建议图片尺寸:100px*100px")],-1)),s("div",L,[l(G,{modelValue:n(a).data,"onUpdate:modelValue":e[3]||(e[3]=t=>n(a).data=t)},null,8,["modelValue"])])]),_:1})]),_:1})])}}});export{I as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as I,q as i,r as g,v as t,D as l,bg as O,s,u,bQ as j,O as F,b6 as q,b7 as z,I as A,K,L,P,b9 as Q,p as R,cm as b}from"./.pnpm-BSw4l71J.js";import{_ as S}from"./index-Du0eYB29.js";import{c as T,i as v}from"./index-BWlhxa68.js";import{_ as G}from"./picker-B4EVDozl.js";import{_ as H}from"./picker-C_3iViNJ.js";const J={class:"bg-fill-light flex items-center w-full p-4 mt-4"},M={class:"ml-3 flex-1"},W={class:"flex-1 flex items-center"},X={class:"drag-move cursor-move ml-auto"},Y={key:0,class:"mt-4"},p=5,le=I({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(r,{emit:h}){const m=h,c=r,f=R({get:()=>c.content,set:a=>{m("update:content",a)}}),k=()=>{var a;if(((a=c.content.data)==null?void 0:a.length)<p){const e=b(c.content);e.data.push({is_show:"1",image:"",name:"",link:{}}),m("update:content",e)}else v.msgError(`最多添加${p}张图片`)},w=a=>{var d;if(((d=c.content.data)==null?void 0:d.length)<=1)return v.msgError("最少保留一张图片");const e=b(c.content);e.data.splice(a,1),m("update:content",e)};return(a,e)=>{const d=H,y=z,_=q,E=G,U=A,C=T,B=S,D=K,N=O,$=Q;return i(),g("div",null,[t($,{"label-width":"70px"},{default:l(()=>[t(N,{shadow:"never",class:"!border-none flex mt-2"},{default:l(()=>{var x;return[e[2]||(e[2]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单"),s("div",{class:"text-xs text-tx-secondary ml-2"}," 最多添加5张,建议图片尺寸:750px*200px ")],-1)),t(u(j),{class:"draggable",modelValue:u(f).data,"onUpdate:modelValue":e[0]||(e[0]=o=>u(f).data=o),animation:"300",handle:".drag-move","item-key":"index"},{item:l(({element:o,index:V})=>[(i(),F(B,{key:V,onClose:n=>w(V),class:"w-[467px]"},{default:l(()=>[s("div",J,[t(d,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body","exclude-domain":""},null,8,["modelValue","onUpdate:modelValue"]),s("div",M,[t(_,{label:"图片名称"},{default:l(()=>[t(y,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),t(_,{class:"mt-[18px]",label:"图片链接"},{default:l(()=>[t(E,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),t(_,{label:"是否显示",class:"mt-[18px]"},{default:l(()=>[s("div",W,[t(U,{modelValue:o.is_show,"onUpdate:modelValue":n=>o.is_show=n,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),s("div",X,[t(C,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"]),((x=r.content.data)==null?void 0:x.length)<p?(i(),g("div",Y,[t(D,{class:"w-full",type:"primary",onClick:k},{default:l(()=>[...e[1]||(e[1]=[L("添加图片",-1)])]),_:1})])):P("",!0)]}),_:1})]),_:1})])}}});export{le as _};
|
import{o as I,q as i,r as g,v as t,D as l,bg as O,s,u,bQ as j,O as F,b6 as q,b7 as z,I as A,K,L,P,b9 as Q,p as R,cm as b}from"./.pnpm-BSw4l71J.js";import{_ as S}from"./index-D7nDUOel.js";import{c as T,i as v}from"./index-CQbHw_bK.js";import{_ as G}from"./picker-D0OtRCxO.js";import{_ as H}from"./picker-GVLgWOJW.js";const J={class:"bg-fill-light flex items-center w-full p-4 mt-4"},M={class:"ml-3 flex-1"},W={class:"flex-1 flex items-center"},X={class:"drag-move cursor-move ml-auto"},Y={key:0,class:"mt-4"},p=5,le=I({__name:"attr",props:{content:{type:Object,default:()=>({})},styles:{type:Object,default:()=>({})}},emits:["update:content"],setup(r,{emit:h}){const m=h,c=r,f=R({get:()=>c.content,set:a=>{m("update:content",a)}}),k=()=>{var a;if(((a=c.content.data)==null?void 0:a.length)<p){const e=b(c.content);e.data.push({is_show:"1",image:"",name:"",link:{}}),m("update:content",e)}else v.msgError(`最多添加${p}张图片`)},w=a=>{var d;if(((d=c.content.data)==null?void 0:d.length)<=1)return v.msgError("最少保留一张图片");const e=b(c.content);e.data.splice(a,1),m("update:content",e)};return(a,e)=>{const d=H,y=z,_=q,E=G,U=A,C=T,B=S,D=K,N=O,$=Q;return i(),g("div",null,[t($,{"label-width":"70px"},{default:l(()=>[t(N,{shadow:"never",class:"!border-none flex mt-2"},{default:l(()=>{var x;return[e[2]||(e[2]=s("div",{class:"flex items-end mb-4"},[s("div",{class:"text-base text-[#101010] font-medium"},"菜单"),s("div",{class:"text-xs text-tx-secondary ml-2"}," 最多添加5张,建议图片尺寸:750px*200px ")],-1)),t(u(j),{class:"draggable",modelValue:u(f).data,"onUpdate:modelValue":e[0]||(e[0]=o=>u(f).data=o),animation:"300",handle:".drag-move","item-key":"index"},{item:l(({element:o,index:V})=>[(i(),F(B,{key:V,onClose:n=>w(V),class:"w-[467px]"},{default:l(()=>[s("div",J,[t(d,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body","exclude-domain":""},null,8,["modelValue","onUpdate:modelValue"]),s("div",M,[t(_,{label:"图片名称"},{default:l(()=>[t(y,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"请输入名称"},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),t(_,{class:"mt-[18px]",label:"图片链接"},{default:l(()=>[t(E,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])]),_:2},1024),t(_,{label:"是否显示",class:"mt-[18px]"},{default:l(()=>[s("div",W,[t(U,{modelValue:o.is_show,"onUpdate:modelValue":n=>o.is_show=n,"active-value":"1","inactive-value":"0"},null,8,["modelValue","onUpdate:modelValue"]),s("div",X,[t(C,{name:"el-icon-Rank",size:"18"})])])]),_:2},1024)])])]),_:2},1032,["onClose"]))]),_:1},8,["modelValue"]),((x=r.content.data)==null?void 0:x.length)<p?(i(),g("div",Y,[t(D,{class:"w-full",type:"primary",onClick:k},{default:l(()=>[...e[1]||(e[1]=[L("添加图片",-1)])]),_:1})])):P("",!0)]}),_:1})]),_:1})])}}});export{le as _};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./auth.vue_vue_type_script_setup_true_lang-5Y_lUvd0.js";import"./.pnpm-BSw4l71J.js";import"./menu-QnTjwn5T.js";import"./index-CQbHw_bK.js";import"./role-fyMDcf6a.js";import"./index-BHzpLgF4.js";export{o as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{_ as o}from"./auth.vue_vue_type_script_setup_true_lang-CFc2eGLT.js";import"./.pnpm-BSw4l71J.js";import"./menu-BVjq04Up.js";import"./index-BWlhxa68.js";import"./role-CHpVoaGw.js";import"./index-IBEgpZdk.js";export{o as default};
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as O,q as k,r as U,v as s,D as d,ac as H,O as I,b9 as j,u as c,a2 as z,b6 as G,s as y,bd as J,C as P,bU as Q,bi as W,a8 as f,M as r,ba as X,n as b}from"./.pnpm-BSw4l71J.js";import{m as Y}from"./menu-BVjq04Up.js";import{a as Z}from"./role-CHpVoaGw.js";import{_ as $}from"./index-IBEgpZdk.js";import{x as ee}from"./index-BWlhxa68.js";const te={class:"edit-popup"},re=O({__name:"auth",emits:["success","close"],setup(ae,{expose:x,emit:C}){const _=C,l=f(),h=f(),u=f(),g=r(!1),i=r(!0),m=r(!1),v=r([]),p=r([]),o=X({id:"",name:"",desc:"",sort:0,data_scope:1,menu_id:[]}),E={name:[{required:!0,message:"请输入名称",trigger:["blur"]}]},w=()=>{m.value=!0,Y().then(e=>{p.value=e,v.value=ee(e),b(()=>{A()}),m.value=!1})},R=()=>{var a,n;const e=(a=l.value)==null?void 0:a.getCheckedKeys(),t=(n=l.value)==null?void 0:n.getHalfCheckedKeys();return e==null||e.unshift.apply(e,t),e},A=()=>{o.menu_id.forEach(e=>{b(()=>{var t;(t=l.value)==null||t.setChecked(e,!0,!1)})})},D=e=>{const t=p.value;for(let a=0;a<t.length;a++)l.value.store.nodesMap[t[a].id].expanded=e},K=e=>{var t,a;e?(t=l.value)==null||t.setCheckedKeys(v.value.map(n=>n.id)):(a=l.value)==null||a.setCheckedKeys([])},V=async()=>{var e,t;await((e=h.value)==null?void 0:e.validate()),o.menu_id=R(),await Z(o),(t=u.value)==null||t.close(),_("success")},B=()=>{_("close")},S=()=>{var e;(e=u.value)==null||e.open()},T=async e=>{for(const t in o)e[t]!=null&&e[t]!=null&&(o[t]=e[t])};return w(),x({open:S,setFormData:T}),(e,t)=>{const a=J,n=Q,F=G,q=z,L=j,M=W;return k(),U("div",te,[s($,{ref_key:"popupRef",ref:u,title:"分配权限",async:!0,width:"550px",onConfirm:V,onClose:B},{default:d(()=>[H((k(),I(L,{class:"ls-form",ref_key:"formRef",ref:h,rules:E,model:c(o),"label-width":"60px"},{default:d(()=>[s(q,{class:"h-[400px] sm:h-[600px]"},{default:d(()=>[s(F,{label:"权限",prop:"menu_id"},{default:d(()=>[y("div",null,[s(a,{label:"展开/折叠",onChange:D}),s(a,{label:"全选/不全选",onChange:K}),s(a,{modelValue:c(i),"onUpdate:modelValue":t[0]||(t[0]=N=>P(i)?i.value=N:null),label:"父子联动"},null,8,["modelValue"]),y("div",null,[s(n,{ref_key:"treeRef",ref:l,data:c(p),props:{label:"name",children:"children"},"check-strictly":!c(i),"node-key":"id","default-expand-all":c(g),"show-checkbox":""},null,8,["data","check-strictly","default-expand-all"])])])]),_:1})]),_:1})]),_:1},8,["model"])),[[M,c(m)]])]),_:1},512)])}}});export{re as _};
|
import{o as O,q as k,r as U,v as s,D as d,ac as H,O as I,b9 as j,u as c,a2 as z,b6 as G,s as y,bd as J,C as P,bU as Q,bi as W,a8 as f,M as r,ba as X,n as b}from"./.pnpm-BSw4l71J.js";import{m as Y}from"./menu-QnTjwn5T.js";import{a as Z}from"./role-fyMDcf6a.js";import{_ as $}from"./index-BHzpLgF4.js";import{x as ee}from"./index-CQbHw_bK.js";const te={class:"edit-popup"},re=O({__name:"auth",emits:["success","close"],setup(ae,{expose:x,emit:C}){const _=C,l=f(),h=f(),u=f(),g=r(!1),i=r(!0),m=r(!1),v=r([]),p=r([]),o=X({id:"",name:"",desc:"",sort:0,data_scope:1,menu_id:[]}),E={name:[{required:!0,message:"请输入名称",trigger:["blur"]}]},w=()=>{m.value=!0,Y().then(e=>{p.value=e,v.value=ee(e),b(()=>{A()}),m.value=!1})},R=()=>{var a,n;const e=(a=l.value)==null?void 0:a.getCheckedKeys(),t=(n=l.value)==null?void 0:n.getHalfCheckedKeys();return e==null||e.unshift.apply(e,t),e},A=()=>{o.menu_id.forEach(e=>{b(()=>{var t;(t=l.value)==null||t.setChecked(e,!0,!1)})})},D=e=>{const t=p.value;for(let a=0;a<t.length;a++)l.value.store.nodesMap[t[a].id].expanded=e},K=e=>{var t,a;e?(t=l.value)==null||t.setCheckedKeys(v.value.map(n=>n.id)):(a=l.value)==null||a.setCheckedKeys([])},V=async()=>{var e,t;await((e=h.value)==null?void 0:e.validate()),o.menu_id=R(),await Z(o),(t=u.value)==null||t.close(),_("success")},B=()=>{_("close")},S=()=>{var e;(e=u.value)==null||e.open()},T=async e=>{for(const t in o)e[t]!=null&&e[t]!=null&&(o[t]=e[t])};return w(),x({open:S,setFormData:T}),(e,t)=>{const a=J,n=Q,F=G,q=z,L=j,M=W;return k(),U("div",te,[s($,{ref_key:"popupRef",ref:u,title:"分配权限",async:!0,width:"550px",onConfirm:V,onClose:B},{default:d(()=>[H((k(),I(L,{class:"ls-form",ref_key:"formRef",ref:h,rules:E,model:c(o),"label-width":"60px"},{default:d(()=>[s(q,{class:"h-[400px] sm:h-[600px]"},{default:d(()=>[s(F,{label:"权限",prop:"menu_id"},{default:d(()=>[y("div",null,[s(a,{label:"展开/折叠",onChange:D}),s(a,{label:"全选/不全选",onChange:K}),s(a,{modelValue:c(i),"onUpdate:modelValue":t[0]||(t[0]=N=>P(i)?i.value=N:null),label:"父子联动"},null,8,["modelValue"]),y("div",null,[s(n,{ref_key:"treeRef",ref:l,data:c(p),props:{label:"name",children:"children"},"check-strictly":!c(i),"node-key":"id","default-expand-all":c(g),"show-checkbox":""},null,8,["data","check-strictly","default-expand-all"])])])]),_:1})]),_:1})]),_:1},8,["model"])),[[M,c(m)]])]),_:1},512)])}}});export{re as _};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as y,q as m,r as h,v as e,D as l,bh as K,b9 as P,u as a,b6 as N,b7 as O,b8 as j,bm as q,bn as z,F as I,G as R,O as w,K as S,L as _,bg as $,ac as A,bj as G,bk as H,s as p,T as v,ae as J,bi as M,C as Q,ba as W}from"./.pnpm-BSw4l71J.js";import{_ as X}from"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import{h as Y}from"./index-BWlhxa68.js";import{_ as Z}from"./index.vue_vue_type_script_setup_true_lang--kuEf_zw.js";import{g as ee,h as te}from"./finance-glk8Sko5.js";import{u as ae}from"./useDictOptions-DL_MQ7g9.js";import{u as ne}from"./usePaging-BeGcb2kN.js";const le={class:"flex items-center"},oe={class:"flex justify-end mt-4"},se=y({name:"balanceDetail"}),be=y({...se,setup(ie){const o=W({user_info:"",change_type:"",start_time:"",end_time:""}),{pager:i,getLists:d,resetPage:c,resetParams:C}=ne({fetchFun:ee,params:o}),{optionsData:x}=ae({change_type:{api:te}});return d(),(re,n)=>{const V=K,E=O,r=N,u=z,T=q,k=Z,f=S,D=P,b=$,s=H,U=Y,B=G,F=X,L=M;return m(),h("div",null,[e(b,{class:"!border-none",shadow:"never"},{default:l(()=>[e(V,{type:"warning",title:"温馨提示:用户账户变动记录",closable:!1,"show-icon":""}),e(D,{ref:"formRef",class:"mb-[-16px] mt-[16px]",model:a(o),inline:!0},{default:l(()=>[e(r,{class:"w-[280px]",label:"用户信息"},{default:l(()=>[e(E,{modelValue:a(o).user_info,"onUpdate:modelValue":n[0]||(n[0]=t=>a(o).user_info=t),placeholder:"请输入用户账号/昵称/手机号",clearable:"",onKeyup:j(a(c),["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),e(r,{class:"w-[280px]",label:"变动类型"},{default:l(()=>[e(T,{modelValue:a(o).change_type,"onUpdate:modelValue":n[1]||(n[1]=t=>a(o).change_type=t)},{default:l(()=>[e(u,{label:"全部",value:""}),(m(!0),h(I,null,R(a(x).change_type,(t,g)=>(m(),w(u,{key:g,label:t,value:g},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(r,{label:"记录时间"},{default:l(()=>[e(k,{startTime:a(o).start_time,"onUpdate:startTime":n[2]||(n[2]=t=>a(o).start_time=t),endTime:a(o).end_time,"onUpdate:endTime":n[3]||(n[3]=t=>a(o).end_time=t)},null,8,["startTime","endTime"])]),_:1}),e(r,null,{default:l(()=>[e(f,{type:"primary",onClick:a(c)},{default:l(()=>[...n[5]||(n[5]=[_("查询",-1)])]),_:1},8,["onClick"]),e(f,{onClick:a(C)},{default:l(()=>[...n[6]||(n[6]=[_("重置",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["model"])]),_:1}),e(b,{class:"!border-none mt-4",shadow:"never"},{default:l(()=>[A((m(),w(B,{size:"large",data:a(i).lists},{default:l(()=>[e(s,{label:"用户账号",prop:"account","min-width":"100"}),e(s,{label:"用户昵称","min-width":"160"},{default:l(({row:t})=>[p("div",le,[e(U,{class:"flex-none mr-2",src:t.avatar,width:40,height:40,"preview-teleported":"",fit:"contain"},null,8,["src"]),_(" "+v(t.nickname),1)])]),_:1}),e(s,{label:"手机号码",prop:"mobile","min-width":"100"}),e(s,{label:"变动金额",prop:"change_amount","min-width":"100"},{default:l(({row:t})=>[p("span",{class:J({"text-error":t.action==2})},v(t.change_amount),3)]),_:1}),e(s,{label:"剩余金额",prop:"left_amount","min-width":"100"}),e(s,{label:"变动类型",prop:"change_type_desc","min-width":"120"}),e(s,{label:"来源单号",prop:"source_sn","min-width":"100"}),e(s,{label:"记录时间",prop:"create_time","min-width":"120"})]),_:1},8,["data"])),[[L,a(i).loading]]),p("div",oe,[e(F,{modelValue:a(i),"onUpdate:modelValue":n[4]||(n[4]=t=>Q(i)?i.value=t:null),onChange:a(d)},null,8,["modelValue","onChange"])])]),_:1})])}}});export{be as default};
|
import{o as y,q as m,r as h,v as e,D as l,bh as K,b9 as P,u as a,b6 as N,b7 as O,b8 as j,bm as q,bn as z,F as I,G as R,O as w,K as S,L as _,bg as $,ac as A,bj as G,bk as H,s as p,T as v,ae as J,bi as M,C as Q,ba as W}from"./.pnpm-BSw4l71J.js";import{_ as X}from"./index.vue_vue_type_script_setup_true_lang-BOJpu9c9.js";import{h as Y}from"./index-CQbHw_bK.js";import{_ as Z}from"./index.vue_vue_type_script_setup_true_lang--kuEf_zw.js";import{g as ee,h as te}from"./finance-DRnLClYc.js";import{u as ae}from"./useDictOptions-KNledyAV.js";import{u as ne}from"./usePaging-BeGcb2kN.js";const le={class:"flex items-center"},oe={class:"flex justify-end mt-4"},se=y({name:"balanceDetail"}),be=y({...se,setup(ie){const o=W({user_info:"",change_type:"",start_time:"",end_time:""}),{pager:i,getLists:d,resetPage:c,resetParams:C}=ne({fetchFun:ee,params:o}),{optionsData:x}=ae({change_type:{api:te}});return d(),(re,n)=>{const V=K,E=O,r=N,u=z,T=q,k=Z,f=S,D=P,b=$,s=H,U=Y,B=G,F=X,L=M;return m(),h("div",null,[e(b,{class:"!border-none",shadow:"never"},{default:l(()=>[e(V,{type:"warning",title:"温馨提示:用户账户变动记录",closable:!1,"show-icon":""}),e(D,{ref:"formRef",class:"mb-[-16px] mt-[16px]",model:a(o),inline:!0},{default:l(()=>[e(r,{class:"w-[280px]",label:"用户信息"},{default:l(()=>[e(E,{modelValue:a(o).user_info,"onUpdate:modelValue":n[0]||(n[0]=t=>a(o).user_info=t),placeholder:"请输入用户账号/昵称/手机号",clearable:"",onKeyup:j(a(c),["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),e(r,{class:"w-[280px]",label:"变动类型"},{default:l(()=>[e(T,{modelValue:a(o).change_type,"onUpdate:modelValue":n[1]||(n[1]=t=>a(o).change_type=t)},{default:l(()=>[e(u,{label:"全部",value:""}),(m(!0),h(I,null,R(a(x).change_type,(t,g)=>(m(),w(u,{key:g,label:t,value:g},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(r,{label:"记录时间"},{default:l(()=>[e(k,{startTime:a(o).start_time,"onUpdate:startTime":n[2]||(n[2]=t=>a(o).start_time=t),endTime:a(o).end_time,"onUpdate:endTime":n[3]||(n[3]=t=>a(o).end_time=t)},null,8,["startTime","endTime"])]),_:1}),e(r,null,{default:l(()=>[e(f,{type:"primary",onClick:a(c)},{default:l(()=>[...n[5]||(n[5]=[_("查询",-1)])]),_:1},8,["onClick"]),e(f,{onClick:a(C)},{default:l(()=>[...n[6]||(n[6]=[_("重置",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["model"])]),_:1}),e(b,{class:"!border-none mt-4",shadow:"never"},{default:l(()=>[A((m(),w(B,{size:"large",data:a(i).lists},{default:l(()=>[e(s,{label:"用户账号",prop:"account","min-width":"100"}),e(s,{label:"用户昵称","min-width":"160"},{default:l(({row:t})=>[p("div",le,[e(U,{class:"flex-none mr-2",src:t.avatar,width:40,height:40,"preview-teleported":"",fit:"contain"},null,8,["src"]),_(" "+v(t.nickname),1)])]),_:1}),e(s,{label:"手机号码",prop:"mobile","min-width":"100"}),e(s,{label:"变动金额",prop:"change_amount","min-width":"100"},{default:l(({row:t})=>[p("span",{class:J({"text-error":t.action==2})},v(t.change_amount),3)]),_:1}),e(s,{label:"剩余金额",prop:"left_amount","min-width":"100"}),e(s,{label:"变动类型",prop:"change_type_desc","min-width":"120"}),e(s,{label:"来源单号",prop:"source_sn","min-width":"100"}),e(s,{label:"记录时间",prop:"create_time","min-width":"120"})]),_:1},8,["data"])),[[L,a(i).loading]]),p("div",oe,[e(F,{modelValue:a(i),"onUpdate:modelValue":n[4]||(n[4]=t=>Q(i)?i.value=t:null),onChange:a(d)},null,8,["modelValue","onChange"])])]),_:1})])}}});export{be as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as T,W as $,ap as j,E as p,aq as z,q as d,r as l,s as r,v as c,D as y,u as S,b5 as I,w as A,F as D,L as M,K as F,M as k,n as C}from"./.pnpm-BSw4l71J.js";import{_ as K}from"./footer.vue_vue_type_script_setup_true_lang-CzPfxxzB.js";import{u as Q,g as V,P as L,a as X,b as G,_ as H}from"./index-BWlhxa68.js";import{a as J}from"./wecomOauthPostMessage-C_e6VGrO.js";const Y={class:"bind-wx flex flex-col"},Z={class:"flex-1 flex items-center justify-center"},ee={class:"bind-wx-card bg-body rounded-md px-10 py-10 w-[480px]"},te={key:0,class:"text-center py-10"},oe={key:0,class:"text-center py-10"},ne={key:1,id:"wxwork_bind_qrcode_container",class:"wxwork-qrcode mx-auto"},ae={class:"mt-8 flex justify-center gap-4"},w="bind_wxwork",g="like_admin_wx_bind_oauth",se=T({__name:"bind-work-wechat",setup(re){const u=$(),f=Q(),x=k(!1),_=k(!1),m=k({corp_id:"",agent_id:""}),U=()=>/wxwork/i.test(navigator.userAgent),v=()=>window.location.origin+window.location.pathname+"?bind_wxwork=1";function W(){const o=new URLSearchParams(window.location.search),e=window.location.hash||"",t=e.includes("?")?e.split("?").slice(1).join("?"):"";return t&&new URLSearchParams(t).forEach((n,i)=>{o.has(i)||o.set(i,n)}),o}const E=()=>{f.logout()},q=async()=>{try{await f.getUserInfo()}catch{}if(f.isPaw===0){u.replace("/change-password");return}u.replace(L.INDEX)},b=async o=>{_.value=!0;try{await G({code:o}),window.history.replaceState({},"",window.location.pathname),await q()}catch(e){console.error(e),p.error((e==null?void 0:e.msg)||(e==null?void 0:e.message)||"绑定失败"),_.value=!1}};let s=null;const B=async()=>{if(!m.value.corp_id)return;x.value=!0,window.WwLogin||await new Promise((e,t)=>{const n=document.createElement("script");n.src="https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js",n.onload=()=>e(),n.onerror=()=>t(new Error("加载企业微信 JS 失败")),document.head.appendChild(n)}),await C(),x.value=!1,await C();const o=encodeURIComponent(v());new window.WwLogin({id:"wxwork_bind_qrcode_container",appid:m.value.corp_id,agentid:m.value.agent_id,redirect_uri:o,lang:"zh",state:w,href:"",self_redirect:!1})};return j(async()=>{let o="";try{o=(new URLSearchParams(window.location.search).get("code")||"").trim()}catch{o=""}if(!V()){p.error("请先登录"),u.push(L.LOGIN);return}const e=W(),t=o||(e.get("code")||"").trim(),n=e.get("state"),i=n!=null?String(n).trim():"",P=i===w||i==="admin_bind_wx"||i.toLowerCase()===w.toLowerCase(),R=e.get("bind_wxwork")==="1",N=!!t&&i===""&&u.currentRoute.value.path==="/bind-work-wechat";if(t&&(P||R||N)){if(sessionStorage.getItem(g)===t)return;sessionStorage.setItem(g,t);try{await b(t)}finally{sessionStorage.removeItem(g)}return}try{const a=await X();if(!(a!=null&&a.enabled)||!a.corp_id){p.error("企业微信未配置,请联系管理员");return}if(m.value={corp_id:a.corp_id,agent_id:a.agent_id},U()){_.value=!0;const h=encodeURIComponent(v()),O=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${a.corp_id}&redirect_uri=${h}&response_type=code&scope=snsapi_privateinfo&agentid=${a.agent_id}&state=${w}#wechat_redirect`;window.location.href=O;return}s==null||s(),s=J({pathIncludes:"bind-work-wechat",lockKey:g,wxBindState:w,onCode:h=>b(h)}),await B()}catch(a){console.error(a),p.error("获取企业微信配置失败")}}),z(()=>{s==null||s(),s=null}),(o,e)=>{const t=A,n=F;return d(),l("div",Y,[r("div",Z,[r("div",ee,[e[4]||(e[4]=r("div",{class:"text-center text-2xl font-medium mb-2"},"绑定企业微信",-1)),e[5]||(e[5]=r("div",{class:"text-center text-gray-500 text-sm mb-8"}," 根据安全策略,需绑定企业微信账号后方可使用管理后台 ",-1)),_.value?(d(),l("div",te,[c(t,{class:"is-loading mb-4",size:40,color:"var(--el-color-primary)"},{default:y(()=>[c(S(I))]),_:1}),e[0]||(e[0]=r("div",{class:"text-gray-500"},"企业微信授权中...",-1))])):(d(),l(D,{key:1},[x.value?(d(),l("div",oe,[c(t,{class:"is-loading",size:32,color:"var(--el-color-primary)"},{default:y(()=>[c(S(I))]),_:1}),e[1]||(e[1]=r("div",{class:"mt-2 text-gray-400 text-sm"},"加载扫码...",-1))])):(d(),l("div",ne)),e[2]||(e[2]=r("div",{class:"text-center text-sm text-gray-400 mt-4"}," 请使用企业微信扫描二维码完成绑定 ",-1))],64)),r("div",ae,[c(n,{onClick:E},{default:y(()=>[...e[3]||(e[3]=[M("退出登录",-1)])]),_:1})])])]),c(K)])}}}),ue=H(se,[["__scopeId","data-v-d4a61522"]]);export{ue as default};
|
import{o as T,W as $,ap as j,E as p,aq as z,q as d,r as l,s as r,v as c,D as y,u as S,b5 as I,w as A,F as D,L as M,K as F,M as k,n as C}from"./.pnpm-BSw4l71J.js";import{_ as K}from"./footer.vue_vue_type_script_setup_true_lang-smHQaDwA.js";import{u as Q,g as V,P as L,a as X,b as G,_ as H}from"./index-CQbHw_bK.js";import{a as J}from"./wecomOauthPostMessage-C_e6VGrO.js";const Y={class:"bind-wx flex flex-col"},Z={class:"flex-1 flex items-center justify-center"},ee={class:"bind-wx-card bg-body rounded-md px-10 py-10 w-[480px]"},te={key:0,class:"text-center py-10"},oe={key:0,class:"text-center py-10"},ne={key:1,id:"wxwork_bind_qrcode_container",class:"wxwork-qrcode mx-auto"},ae={class:"mt-8 flex justify-center gap-4"},w="bind_wxwork",g="like_admin_wx_bind_oauth",se=T({__name:"bind-work-wechat",setup(re){const u=$(),f=Q(),x=k(!1),_=k(!1),m=k({corp_id:"",agent_id:""}),U=()=>/wxwork/i.test(navigator.userAgent),v=()=>window.location.origin+window.location.pathname+"?bind_wxwork=1";function W(){const o=new URLSearchParams(window.location.search),e=window.location.hash||"",t=e.includes("?")?e.split("?").slice(1).join("?"):"";return t&&new URLSearchParams(t).forEach((n,i)=>{o.has(i)||o.set(i,n)}),o}const E=()=>{f.logout()},q=async()=>{try{await f.getUserInfo()}catch{}if(f.isPaw===0){u.replace("/change-password");return}u.replace(L.INDEX)},b=async o=>{_.value=!0;try{await G({code:o}),window.history.replaceState({},"",window.location.pathname),await q()}catch(e){console.error(e),p.error((e==null?void 0:e.msg)||(e==null?void 0:e.message)||"绑定失败"),_.value=!1}};let s=null;const B=async()=>{if(!m.value.corp_id)return;x.value=!0,window.WwLogin||await new Promise((e,t)=>{const n=document.createElement("script");n.src="https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js",n.onload=()=>e(),n.onerror=()=>t(new Error("加载企业微信 JS 失败")),document.head.appendChild(n)}),await C(),x.value=!1,await C();const o=encodeURIComponent(v());new window.WwLogin({id:"wxwork_bind_qrcode_container",appid:m.value.corp_id,agentid:m.value.agent_id,redirect_uri:o,lang:"zh",state:w,href:"",self_redirect:!1})};return j(async()=>{let o="";try{o=(new URLSearchParams(window.location.search).get("code")||"").trim()}catch{o=""}if(!V()){p.error("请先登录"),u.push(L.LOGIN);return}const e=W(),t=o||(e.get("code")||"").trim(),n=e.get("state"),i=n!=null?String(n).trim():"",P=i===w||i==="admin_bind_wx"||i.toLowerCase()===w.toLowerCase(),R=e.get("bind_wxwork")==="1",N=!!t&&i===""&&u.currentRoute.value.path==="/bind-work-wechat";if(t&&(P||R||N)){if(sessionStorage.getItem(g)===t)return;sessionStorage.setItem(g,t);try{await b(t)}finally{sessionStorage.removeItem(g)}return}try{const a=await X();if(!(a!=null&&a.enabled)||!a.corp_id){p.error("企业微信未配置,请联系管理员");return}if(m.value={corp_id:a.corp_id,agent_id:a.agent_id},U()){_.value=!0;const h=encodeURIComponent(v()),O=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${a.corp_id}&redirect_uri=${h}&response_type=code&scope=snsapi_privateinfo&agentid=${a.agent_id}&state=${w}#wechat_redirect`;window.location.href=O;return}s==null||s(),s=J({pathIncludes:"bind-work-wechat",lockKey:g,wxBindState:w,onCode:h=>b(h)}),await B()}catch(a){console.error(a),p.error("获取企业微信配置失败")}}),z(()=>{s==null||s(),s=null}),(o,e)=>{const t=A,n=F;return d(),l("div",Y,[r("div",Z,[r("div",ee,[e[4]||(e[4]=r("div",{class:"text-center text-2xl font-medium mb-2"},"绑定企业微信",-1)),e[5]||(e[5]=r("div",{class:"text-center text-gray-500 text-sm mb-8"}," 根据安全策略,需绑定企业微信账号后方可使用管理后台 ",-1)),_.value?(d(),l("div",te,[c(t,{class:"is-loading mb-4",size:40,color:"var(--el-color-primary)"},{default:y(()=>[c(S(I))]),_:1}),e[0]||(e[0]=r("div",{class:"text-gray-500"},"企业微信授权中...",-1))])):(d(),l(D,{key:1},[x.value?(d(),l("div",oe,[c(t,{class:"is-loading",size:32,color:"var(--el-color-primary)"},{default:y(()=>[c(S(I))]),_:1}),e[1]||(e[1]=r("div",{class:"mt-2 text-gray-400 text-sm"},"加载扫码...",-1))])):(d(),l("div",ne)),e[2]||(e[2]=r("div",{class:"text-center text-sm text-gray-400 mt-4"}," 请使用企业微信扫描二维码完成绑定 ",-1))],64)),r("div",ae,[c(n,{onClick:E},{default:y(()=>[...e[3]||(e[3]=[M("退出登录",-1)])]),_:1})])])]),c(K)])}}}),ue=H(se,[["__scopeId","data-v-d4a61522"]]);export{ue as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as l,q as i,r as m,v as e,D as a,bh as p,bg as f,bj as b,u,bk as h,K as w,L as C,M as k}from"./.pnpm-BSw4l71J.js";import{i as E,B as x}from"./index-BWlhxa68.js";const y={class:"cache"},g=l({name:"cache"}),N=l({...g,setup(v){const s=k([{content:"系统缓存",desc:"系统运行过程中产生的各类缓存数据"}]),c=async()=>{await E.confirm("确认清除系统缓存?"),await x(),window.location.reload()};return(B,o)=>{const r=p,n=f,t=h,_=w,d=b;return i(),m("div",y,[e(n,{class:"!border-none",shadow:"never"},{default:a(()=>[e(r,{type:"warning",title:"温馨提示:管理系统运行过程中产生的缓存",closable:!1,"show-icon":""})]),_:1}),e(n,{class:"!border-none mt-4",shadow:"never"},{default:a(()=>[e(d,{data:u(s),size:"large"},{default:a(()=>[e(t,{label:"管理内容",prop:"content","min-width":"130"}),e(t,{label:"内容说明",prop:"desc","min-width":"180"}),e(t,{label:"操作",width:"130",fixed:"right"},{default:a(()=>[e(_,{type:"primary",link:"",onClick:c},{default:a(()=>[...o[0]||(o[0]=[C("清除系统缓存",-1)])]),_:1})]),_:1})]),_:1},8,["data"])]),_:1})])}}});export{N as default};
|
import{o as l,q as i,r as m,v as e,D as a,bh as p,bg as f,bj as b,u,bk as h,K as w,L as C,M as k}from"./.pnpm-BSw4l71J.js";import{i as E,B as x}from"./index-CQbHw_bK.js";const y={class:"cache"},g=l({name:"cache"}),N=l({...g,setup(v){const s=k([{content:"系统缓存",desc:"系统运行过程中产生的各类缓存数据"}]),c=async()=>{await E.confirm("确认清除系统缓存?"),await x(),window.location.reload()};return(B,o)=>{const r=p,n=f,t=h,_=w,d=b;return i(),m("div",y,[e(n,{class:"!border-none",shadow:"never"},{default:a(()=>[e(r,{type:"warning",title:"温馨提示:管理系统运行过程中产生的缓存",closable:!1,"show-icon":""})]),_:1}),e(n,{class:"!border-none mt-4",shadow:"never"},{default:a(()=>[e(d,{data:u(s),size:"large"},{default:a(()=>[e(t,{label:"管理内容",prop:"content","min-width":"130"}),e(t,{label:"内容说明",prop:"desc","min-width":"180"}),e(t,{label:"操作",width:"130",fixed:"right"},{default:a(()=>[e(_,{type:"primary",link:"",onClick:c},{default:a(()=>[...o[0]||(o[0]=[C("清除系统缓存",-1)])]),_:1})]),_:1})]),_:1},8,["data"])]),_:1})])}}});export{N as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{o as k,W as v,ap as E,E as l,q as h,r as V,s as n,v as e,D as r,b6 as P,b7 as C,b8 as L,b9 as F,L as z,u as f,K as B,a8 as I,ba as N}from"./.pnpm-BSw4l71J.js";import{u as R,g as S,P as q,c as K,d as U,_ as D}from"./index-BWlhxa68.js";import{u as M}from"./useLockFn-DZ9wDgti.js";import{_ as T}from"./footer.vue_vue_type_script_setup_true_lang-CzPfxxzB.js";const $={class:"change-password flex flex-col"},j={class:"flex-1 flex items-center justify-center"},G={class:"change-password-card bg-body rounded-md px-10 py-10 w-[480px]"},O=k({__name:"change-password",setup(W){const i=I(),_=v(),m=R();E(()=>{S()||(l.error("请先登录"),_.push(q.LOGIN))});const o=N({password:"",password_confirm:""}),w={password:[{required:!0,message:"请输入新密码",trigger:"blur"},{min:6,message:"密码长度不能少于6位",trigger:"blur"}],password_confirm:[{required:!0,validator:(t,s,a)=>{s===""?a(new Error("请再次输入密码")):s!==o.password?a(new Error("两次输入的密码不一致")):a()},trigger:"blur"}]},p=async()=>{var t;await((t=i.value)==null?void 0:t.validate());try{await U({password:o.password,password_confirm:o.password_confirm}),l.success("密码修改成功,请重新登录"),m.isPaw=1,await m.logout()}catch(s){l.error((s==null?void 0:s.msg)||(s==null?void 0:s.message)||"密码修改失败")}},{isLock:g,lockFn:x}=M(p);return(t,s)=>{const a=K,c=C,u=P,b=F,y=B;return h(),V("div",$,[n("div",j,[n("div",G,[s[3]||(s[3]=n("div",{class:"text-center text-2xl font-medium mb-2"},"首次登录",-1)),s[4]||(s[4]=n("div",{class:"text-center text-gray-500 text-sm mb-8"},"为了您的账号安全,请修改初始密码",-1)),e(b,{ref_key:"formRef",ref:i,model:o,size:"large",rules:w},{default:r(()=>[e(u,{prop:"password"},{default:r(()=>[e(c,{modelValue:o.password,"onUpdate:modelValue":s[0]||(s[0]=d=>o.password=d),type:"password","show-password":"",placeholder:"请输入新密码"},{prepend:r(()=>[e(a,{name:"el-icon-Lock",size:"16"})]),_:1},8,["modelValue"])]),_:1}),e(u,{prop:"password_confirm"},{default:r(()=>[e(c,{modelValue:o.password_confirm,"onUpdate:modelValue":s[1]||(s[1]=d=>o.password_confirm=d),type:"password","show-password":"",placeholder:"请再次输入新密码",onKeyup:L(p,["enter"])},{prepend:r(()=>[e(a,{name:"el-icon-Lock",size:"16"})]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"]),e(y,{type:"primary",size:"large",loading:f(g),onClick:f(x),class:"w-full"},{default:r(()=>[...s[2]||(s[2]=[z(" 确认修改 ",-1)])]),_:1},8,["loading","onClick"])])]),e(T)])}}}),Y=D(O,[["__scopeId","data-v-bbd4ab41"]]);export{Y as default};
|
import{o as k,W as v,ap as E,E as l,q as h,r as V,s as n,v as e,D as r,b6 as P,b7 as C,b8 as L,b9 as F,L as z,u as f,K as B,a8 as I,ba as N}from"./.pnpm-BSw4l71J.js";import{u as R,g as S,P as q,c as K,d as U,_ as D}from"./index-CQbHw_bK.js";import{u as M}from"./useLockFn-DZ9wDgti.js";import{_ as T}from"./footer.vue_vue_type_script_setup_true_lang-smHQaDwA.js";const $={class:"change-password flex flex-col"},j={class:"flex-1 flex items-center justify-center"},G={class:"change-password-card bg-body rounded-md px-10 py-10 w-[480px]"},O=k({__name:"change-password",setup(W){const i=I(),_=v(),m=R();E(()=>{S()||(l.error("请先登录"),_.push(q.LOGIN))});const o=N({password:"",password_confirm:""}),w={password:[{required:!0,message:"请输入新密码",trigger:"blur"},{min:6,message:"密码长度不能少于6位",trigger:"blur"}],password_confirm:[{required:!0,validator:(t,s,a)=>{s===""?a(new Error("请再次输入密码")):s!==o.password?a(new Error("两次输入的密码不一致")):a()},trigger:"blur"}]},p=async()=>{var t;await((t=i.value)==null?void 0:t.validate());try{await U({password:o.password,password_confirm:o.password_confirm}),l.success("密码修改成功,请重新登录"),m.isPaw=1,await m.logout()}catch(s){l.error((s==null?void 0:s.msg)||(s==null?void 0:s.message)||"密码修改失败")}},{isLock:g,lockFn:x}=M(p);return(t,s)=>{const a=K,c=C,u=P,b=F,y=B;return h(),V("div",$,[n("div",j,[n("div",G,[s[3]||(s[3]=n("div",{class:"text-center text-2xl font-medium mb-2"},"首次登录",-1)),s[4]||(s[4]=n("div",{class:"text-center text-gray-500 text-sm mb-8"},"为了您的账号安全,请修改初始密码",-1)),e(b,{ref_key:"formRef",ref:i,model:o,size:"large",rules:w},{default:r(()=>[e(u,{prop:"password"},{default:r(()=>[e(c,{modelValue:o.password,"onUpdate:modelValue":s[0]||(s[0]=d=>o.password=d),type:"password","show-password":"",placeholder:"请输入新密码"},{prepend:r(()=>[e(a,{name:"el-icon-Lock",size:"16"})]),_:1},8,["modelValue"])]),_:1}),e(u,{prop:"password_confirm"},{default:r(()=>[e(c,{modelValue:o.password_confirm,"onUpdate:modelValue":s[1]||(s[1]=d=>o.password_confirm=d),type:"password","show-password":"",placeholder:"请再次输入新密码",onKeyup:L(p,["enter"])},{prepend:r(()=>[e(a,{name:"el-icon-Lock",size:"16"})]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"]),e(y,{type:"primary",size:"large",loading:f(g),onClick:f(x),class:"w-full"},{default:r(()=>[...s[2]||(s[2]=[z(" 确认修改 ",-1)])]),_:1},8,["loading","onClick"])])]),e(T)])}}}),Y=D(O,[["__scopeId","data-v-bbd4ab41"]]);export{Y as default};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as t}from"./index-BWlhxa68.js";function o(e){return t.get({url:"/tools.generator/generateTable",params:e})}function n(e){return t.get({url:"/tools.generator/dataTable",params:e})}function a(e){return t.post({url:"/tools.generator/selectTable",params:e})}function l(e){return t.get({url:"/tools.generator/detail",params:e})}function s(e){return t.post({url:"/tools.generator/syncColumn",params:e})}function u(e){return t.post({url:"/tools.generator/delete",params:e})}function g(e){return t.post({url:"/tools.generator/edit",params:e})}function i(e){return t.post({url:"/tools.generator/preview",params:e})}function c(e){return t.post({url:"/tools.generator/generate",params:e})}function f(){return t.get({url:"/tools.generator/getModels"})}export{f as a,o as b,u as c,i as d,c as e,n as f,g,a as h,s,l as t};
|
import{r as t}from"./index-CQbHw_bK.js";function o(e){return t.get({url:"/tools.generator/generateTable",params:e})}function n(e){return t.get({url:"/tools.generator/dataTable",params:e})}function a(e){return t.post({url:"/tools.generator/selectTable",params:e})}function l(e){return t.get({url:"/tools.generator/detail",params:e})}function s(e){return t.post({url:"/tools.generator/syncColumn",params:e})}function u(e){return t.post({url:"/tools.generator/delete",params:e})}function g(e){return t.post({url:"/tools.generator/edit",params:e})}function i(e){return t.post({url:"/tools.generator/preview",params:e})}function c(e){return t.post({url:"/tools.generator/generate",params:e})}function f(){return t.get({url:"/tools.generator/getModels"})}export{f as a,o as b,u as c,i as d,c as e,n as f,g,a as h,s,l as t};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user