codexmate 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/web-ui/modules/app.methods.navigation.mjs +2 -2
- package/web-ui/modules/i18n/locales/en.mjs +1 -0
- package/web-ui/modules/i18n/locales/ja.mjs +1 -0
- package/web-ui/modules/i18n/locales/vi.mjs +1 -0
- package/web-ui/modules/i18n/locales/zh-tw.mjs +1 -0
- package/web-ui/modules/i18n/locales/zh.mjs +1 -0
- package/web-ui/partials/index/panel-dashboard.html +51 -44
- package/web-ui/res/web-ui-render.precompiled.js +81 -73
- package/web-ui/session-helpers.mjs +12 -23
- package/web-ui/styles/dashboard.css +52 -158
package/package.json
CHANGED
|
@@ -732,8 +732,8 @@
|
|
|
732
732
|
this.invalidateSessionTimelineMeasurementCache();
|
|
733
733
|
},
|
|
734
734
|
|
|
735
|
-
async loadMoreSessionMessages(
|
|
736
|
-
return loadMoreSessionMessagesHelper.call(this
|
|
735
|
+
async loadMoreSessionMessages() {
|
|
736
|
+
return loadMoreSessionMessagesHelper.call(this);
|
|
737
737
|
},
|
|
738
738
|
|
|
739
739
|
suspendSessionTabRender() {
|
|
@@ -268,6 +268,7 @@ const en = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': 'Export JSON',
|
|
269
269
|
'dashboard.doctor.export.md': 'Export Markdown',
|
|
270
270
|
'dashboard.doctor.open': 'Open',
|
|
271
|
+
'dashboard.doctor.empty': 'No checks have been run yet. Run checks to diagnose the current setup.',
|
|
271
272
|
'doctor.action.openConfig': 'Open Config',
|
|
272
273
|
'doctor.action.checkProvider': 'Check provider config',
|
|
273
274
|
'doctor.action.openUsage': 'Open Usage',
|
|
@@ -270,6 +270,7 @@ const ja = Object.freeze({
|
|
|
270
270
|
'dashboard.doctor.export.json': 'JSON エクスポート',
|
|
271
271
|
'dashboard.doctor.export.md': 'Markdown エクスポート',
|
|
272
272
|
'dashboard.doctor.open': '開く',
|
|
273
|
+
'dashboard.doctor.empty': 'まだチェックは実行されていません。「チェックを実行」で現在のセットアップを診断します。',
|
|
273
274
|
'doctor.action.openConfig': 'Config を開く',
|
|
274
275
|
'doctor.action.checkProvider': 'Provider 設定をチェック',
|
|
275
276
|
'doctor.action.openUsage': 'Usage を開く',
|
|
@@ -539,6 +539,7 @@ const vi = Object.freeze({
|
|
|
539
539
|
'dashboard.doctor.export.json': 'Xuất JSON',
|
|
540
540
|
'dashboard.doctor.export.md': 'Xuất Markdown',
|
|
541
541
|
'dashboard.doctor.open': 'Mở',
|
|
542
|
+
'dashboard.doctor.empty': 'Chưa chạy lần kiểm tra nào. Nhấn "Chạy kiểm tra" để chẩn đoán cấu hình hiện tại.',
|
|
542
543
|
'doctor.action.openConfig': 'Mở cấu hình',
|
|
543
544
|
'doctor.action.checkProvider': 'Kiểm tra cấu hình nhà cung cấp',
|
|
544
545
|
'doctor.action.openUsage': 'Mở thống kê',
|
|
@@ -268,6 +268,7 @@ const zhTw = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': '匯出 JSON',
|
|
269
269
|
'dashboard.doctor.export.md': '匯出 Markdown',
|
|
270
270
|
'dashboard.doctor.open': '打開',
|
|
271
|
+
'dashboard.doctor.empty': '尚未執行檢查。點擊「運行檢查」診斷目前設定。',
|
|
271
272
|
'doctor.action.openConfig': '打開 Config',
|
|
272
273
|
'doctor.action.checkProvider': '檢查 Provider 設定',
|
|
273
274
|
'doctor.action.openUsage': '打開 Usage',
|
|
@@ -268,6 +268,7 @@ const zh = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': '导出 JSON',
|
|
269
269
|
'dashboard.doctor.export.md': '导出 Markdown',
|
|
270
270
|
'dashboard.doctor.open': '打开',
|
|
271
|
+
'dashboard.doctor.empty': '尚未运行检查。点击上方“运行检查”诊断当前配置。',
|
|
271
272
|
'doctor.action.openConfig': '打开 Config',
|
|
272
273
|
'doctor.action.checkProvider': '检查 Provider 配置',
|
|
273
274
|
'doctor.action.openUsage': '打开 Usage',
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
role="tabpanel"
|
|
6
6
|
:aria-labelledby="'tab-dashboard'">
|
|
7
7
|
<div class="selector-section doctor-hero">
|
|
8
|
-
<div class="selector-header">
|
|
8
|
+
<div class="selector-header doctor-header">
|
|
9
9
|
<span class="selector-title">{{ t('dashboard.doctor.title') }}</span>
|
|
10
10
|
<div class="selector-actions">
|
|
11
11
|
<button
|
|
12
|
-
class="btn-tool btn-tool-compact"
|
|
12
|
+
class="btn-tool btn-tool-compact doctor-run-btn"
|
|
13
13
|
@click="runHealthCheck"
|
|
14
14
|
:disabled="loading || !!initError || healthCheckLoading">
|
|
15
15
|
{{ healthCheckLoading ? t('dashboard.doctor.checking') : t('dashboard.doctor.runChecks') }}
|
|
@@ -30,52 +30,59 @@
|
|
|
30
30
|
<strong>{{ inspectorModelLoadStatus }}</strong>
|
|
31
31
|
</div>
|
|
32
32
|
</div>
|
|
33
|
-
<div
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div v-if="healthCheckResult && healthCheckResult.report" class="doctor-action-list">
|
|
40
|
-
<template v-if="healthCheckResult.report.issues && healthCheckResult.report.issues.length">
|
|
41
|
-
<div v-for="issue in healthCheckResult.report.issues" :key="issue.id" class="doctor-action-card">
|
|
42
|
-
<div class="doctor-action-head">
|
|
43
|
-
<div class="doctor-action-title">{{ issue.problem || (issue.problemKey ? t(issue.problemKey, issue.problemParams) : '') }}</div>
|
|
44
|
-
<div :class="['doctor-action-severity', issue.severity]">{{ issue.severityLabel || issue.severity }}</div>
|
|
33
|
+
<div class="doctor-result-section">
|
|
34
|
+
<template v-if="healthCheckResult">
|
|
35
|
+
<div class="doctor-health-result" :class="healthCheckResult.ok ? 'ok' : 'error'">
|
|
36
|
+
<div class="doctor-health-title">
|
|
37
|
+
{{ healthCheckResult.ok ? t('dashboard.health.ok') : t('dashboard.health.fail') }}
|
|
38
|
+
<span v-if="healthCheckResult.issues && healthCheckResult.issues.length">({{ t('dashboard.health.issues', { count: healthCheckResult.issues.length }) }})</span>
|
|
45
39
|
</div>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class="doctor-action-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
</div>
|
|
41
|
+
<div v-if="healthCheckResult.report" class="doctor-action-list">
|
|
42
|
+
<template v-if="healthCheckResult.report.issues && healthCheckResult.report.issues.length">
|
|
43
|
+
<div v-for="issue in healthCheckResult.report.issues" :key="issue.id" class="doctor-action-card">
|
|
44
|
+
<div class="doctor-action-head">
|
|
45
|
+
<div class="doctor-action-title">{{ issue.problem || (issue.problemKey ? t(issue.problemKey, issue.problemParams) : '') }}</div>
|
|
46
|
+
<div :class="['doctor-action-severity', issue.severity]">{{ issue.severityLabel || issue.severity }}</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="doctor-action-impact">{{ issue.impact || (issue.impactKey ? t(issue.impactKey, issue.impactParams) : '') }}</div>
|
|
49
|
+
<div
|
|
50
|
+
v-if="issue.actions && issue.actions.some(action => action && action.type === 'navigate' && action.target)"
|
|
51
|
+
class="doctor-action-buttons">
|
|
52
|
+
<template v-for="(action, index) in issue.actions" :key="issue.id + '-action-' + index">
|
|
53
|
+
<button
|
|
54
|
+
v-if="action.type === 'navigate' && action.target"
|
|
55
|
+
type="button"
|
|
56
|
+
class="btn-tool btn-tool-compact"
|
|
57
|
+
@click="action.target ? switchMainTab(action.target) : null">
|
|
58
|
+
{{ action.label || (action.labelKey ? t(action.labelKey, action.labelParams) : t('dashboard.doctor.open')) }}
|
|
59
|
+
</button>
|
|
60
|
+
</template>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
<div class="doctor-action-footer">
|
|
65
|
+
<button
|
|
66
|
+
type="button"
|
|
67
|
+
class="btn-tool btn-tool-compact"
|
|
68
|
+
@click="healthCheckResult && healthCheckResult.report
|
|
69
|
+
? downloadTextFile('codexmate-doctor.json', JSON.stringify(healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
70
|
+
: null">
|
|
71
|
+
{{ t('dashboard.doctor.export.json') }}
|
|
72
|
+
</button>
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
class="btn-tool btn-tool-compact"
|
|
76
|
+
@click="healthCheckResult && healthCheckResult.report
|
|
77
|
+
? downloadTextFile('codexmate-doctor.md', String(healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
78
|
+
: null">
|
|
79
|
+
{{ t('dashboard.doctor.export.md') }}
|
|
80
|
+
</button>
|
|
59
81
|
</div>
|
|
60
82
|
</div>
|
|
61
83
|
</template>
|
|
62
|
-
<div class="doctor-
|
|
63
|
-
<
|
|
64
|
-
type="button"
|
|
65
|
-
class="btn-tool btn-tool-compact"
|
|
66
|
-
@click="healthCheckResult && healthCheckResult.report
|
|
67
|
-
? downloadTextFile('codexmate-doctor.json', JSON.stringify(healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
68
|
-
: null">
|
|
69
|
-
{{ t('dashboard.doctor.export.json') }}
|
|
70
|
-
</button>
|
|
71
|
-
<button
|
|
72
|
-
type="button"
|
|
73
|
-
class="btn-tool btn-tool-compact"
|
|
74
|
-
@click="healthCheckResult && healthCheckResult.report
|
|
75
|
-
? downloadTextFile('codexmate-doctor.md', String(healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
76
|
-
: null">
|
|
77
|
-
{{ t('dashboard.doctor.export.md') }}
|
|
78
|
-
</button>
|
|
84
|
+
<div v-else class="doctor-result-empty">
|
|
85
|
+
<span class="doctor-result-empty-text">{{ t('dashboard.doctor.empty') }}</span>
|
|
79
86
|
</div>
|
|
80
87
|
</div>
|
|
81
88
|
<div class="doctor-grid">
|
|
@@ -819,11 +819,11 @@ return function render(_ctx, _cache) {
|
|
|
819
819
|
"aria-labelledby": 'tab-dashboard'
|
|
820
820
|
}, [
|
|
821
821
|
_createElementVNode("div", { class: "selector-section doctor-hero" }, [
|
|
822
|
-
_createElementVNode("div", { class: "selector-header" }, [
|
|
822
|
+
_createElementVNode("div", { class: "selector-header doctor-header" }, [
|
|
823
823
|
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('dashboard.doctor.title')), 1 /* TEXT */),
|
|
824
824
|
_createElementVNode("div", { class: "selector-actions" }, [
|
|
825
825
|
_createElementVNode("button", {
|
|
826
|
-
class: "btn-tool btn-tool-compact",
|
|
826
|
+
class: "btn-tool btn-tool-compact doctor-run-btn",
|
|
827
827
|
onClick: _ctx.runHealthCheck,
|
|
828
828
|
disabled: _ctx.loading || !!_ctx.initError || _ctx.healthCheckLoading
|
|
829
829
|
}, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('dashboard.doctor.checking') : _ctx.t('dashboard.doctor.runChecks')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
@@ -845,79 +845,87 @@ return function render(_ctx, _cache) {
|
|
|
845
845
|
_createElementVNode("strong", null, _toDisplayString(_ctx.inspectorModelLoadStatus), 1 /* TEXT */)
|
|
846
846
|
])
|
|
847
847
|
]),
|
|
848
|
-
(
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
}, [
|
|
866
|
-
(_ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
|
|
867
|
-
? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
|
|
868
|
-
return (_openBlock(), _createElementBlock("div", {
|
|
869
|
-
key: issue.id,
|
|
870
|
-
class: "doctor-action-card"
|
|
848
|
+
_createElementVNode("div", { class: "doctor-result-section" }, [
|
|
849
|
+
(_ctx.healthCheckResult)
|
|
850
|
+
? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
|
|
851
|
+
_createElementVNode("div", {
|
|
852
|
+
class: _normalizeClass(["doctor-health-result", _ctx.healthCheckResult.ok ? 'ok' : 'error'])
|
|
853
|
+
}, [
|
|
854
|
+
_createElementVNode("div", { class: "doctor-health-title" }, [
|
|
855
|
+
_createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('dashboard.health.ok') : _ctx.t('dashboard.health.fail')) + " ", 1 /* TEXT */),
|
|
856
|
+
(_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
|
|
857
|
+
? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('dashboard.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
|
|
858
|
+
: _createCommentVNode("v-if", true)
|
|
859
|
+
])
|
|
860
|
+
], 2 /* CLASS */),
|
|
861
|
+
(_ctx.healthCheckResult.report)
|
|
862
|
+
? (_openBlock(), _createElementBlock("div", {
|
|
863
|
+
key: 0,
|
|
864
|
+
class: "doctor-action-list"
|
|
871
865
|
}, [
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
866
|
+
(_ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
|
|
867
|
+
? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
|
|
868
|
+
return (_openBlock(), _createElementBlock("div", {
|
|
869
|
+
key: issue.id,
|
|
870
|
+
class: "doctor-action-card"
|
|
871
|
+
}, [
|
|
872
|
+
_createElementVNode("div", { class: "doctor-action-head" }, [
|
|
873
|
+
_createElementVNode("div", { class: "doctor-action-title" }, _toDisplayString(issue.problem || (issue.problemKey ? _ctx.t(issue.problemKey, issue.problemParams) : '')), 1 /* TEXT */),
|
|
874
|
+
_createElementVNode("div", {
|
|
875
|
+
class: _normalizeClass(['doctor-action-severity', issue.severity])
|
|
876
|
+
}, _toDisplayString(issue.severityLabel || issue.severity), 3 /* TEXT, CLASS */)
|
|
877
|
+
]),
|
|
878
|
+
_createElementVNode("div", { class: "doctor-action-impact" }, _toDisplayString(issue.impact || (issue.impactKey ? _ctx.t(issue.impactKey, issue.impactParams) : '')), 1 /* TEXT */),
|
|
879
|
+
(issue.actions && issue.actions.some(action => action && action.type === 'navigate' && action.target))
|
|
880
|
+
? (_openBlock(), _createElementBlock("div", {
|
|
881
|
+
key: 0,
|
|
882
|
+
class: "doctor-action-buttons"
|
|
883
|
+
}, [
|
|
884
|
+
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(issue.actions, (action, index) => {
|
|
885
|
+
return (_openBlock(), _createElementBlock(_Fragment, {
|
|
886
|
+
key: issue.id + '-action-' + index
|
|
887
|
+
}, [
|
|
888
|
+
(action.type === 'navigate' && action.target)
|
|
889
|
+
? (_openBlock(), _createElementBlock("button", {
|
|
890
|
+
key: 0,
|
|
891
|
+
type: "button",
|
|
892
|
+
class: "btn-tool btn-tool-compact",
|
|
893
|
+
onClick: $event => (action.target ? _ctx.switchMainTab(action.target) : null)
|
|
894
|
+
}, _toDisplayString(action.label || (action.labelKey ? _ctx.t(action.labelKey, action.labelParams) : _ctx.t('dashboard.doctor.open'))), 9 /* TEXT, PROPS */, ["onClick"]))
|
|
895
|
+
: _createCommentVNode("v-if", true)
|
|
896
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
897
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
898
|
+
]))
|
|
899
|
+
: _createCommentVNode("v-if", true)
|
|
900
|
+
]))
|
|
901
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
902
|
+
: _createCommentVNode("v-if", true),
|
|
903
|
+
_createElementVNode("div", { class: "doctor-action-footer" }, [
|
|
904
|
+
_createElementVNode("button", {
|
|
905
|
+
type: "button",
|
|
906
|
+
class: "btn-tool btn-tool-compact",
|
|
907
|
+
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
908
|
+
? _ctx.downloadTextFile('codexmate-doctor.json', JSON.stringify(_ctx.healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
909
|
+
: null}
|
|
910
|
+
}, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
|
|
911
|
+
_createElementVNode("button", {
|
|
912
|
+
type: "button",
|
|
913
|
+
class: "btn-tool btn-tool-compact",
|
|
914
|
+
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
915
|
+
? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
916
|
+
: null}
|
|
917
|
+
}, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
|
|
918
|
+
])
|
|
900
919
|
]))
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
|
|
911
|
-
_createElementVNode("button", {
|
|
912
|
-
type: "button",
|
|
913
|
-
class: "btn-tool btn-tool-compact",
|
|
914
|
-
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
915
|
-
? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
916
|
-
: null}
|
|
917
|
-
}, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
|
|
918
|
-
])
|
|
919
|
-
]))
|
|
920
|
-
: _createCommentVNode("v-if", true),
|
|
920
|
+
: _createCommentVNode("v-if", true)
|
|
921
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
922
|
+
: (_openBlock(), _createElementBlock("div", {
|
|
923
|
+
key: 1,
|
|
924
|
+
class: "doctor-result-empty"
|
|
925
|
+
}, [
|
|
926
|
+
_createElementVNode("span", { class: "doctor-result-empty-text" }, _toDisplayString(_ctx.t('dashboard.doctor.empty')), 1 /* TEXT */)
|
|
927
|
+
]))
|
|
928
|
+
]),
|
|
921
929
|
_createElementVNode("div", { class: "doctor-grid" }, [
|
|
922
930
|
_createElementVNode("button", {
|
|
923
931
|
type: "button",
|
|
@@ -530,7 +530,7 @@ export async function loadActiveSessionDetail(api, options = {}) {
|
|
|
530
530
|
}
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
-
export async function loadMoreSessionMessages(
|
|
533
|
+
export async function loadMoreSessionMessages() {
|
|
534
534
|
if (this.mainTab !== 'sessions' || !this.sessionPreviewRenderEnabled) {
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
@@ -541,19 +541,6 @@ export async function loadMoreSessionMessages(stepSize) {
|
|
|
541
541
|
this.sessionPreviewVisibleCount = 0;
|
|
542
542
|
return;
|
|
543
543
|
}
|
|
544
|
-
const step = Number.isFinite(stepSize)
|
|
545
|
-
? Math.max(1, Math.floor(stepSize))
|
|
546
|
-
: (Number.isFinite(this.sessionPreviewLoadStep)
|
|
547
|
-
? Math.max(1, Math.floor(this.sessionPreviewLoadStep))
|
|
548
|
-
: 40);
|
|
549
|
-
const current = Number.isFinite(this.sessionPreviewVisibleCount)
|
|
550
|
-
? Math.max(0, Math.floor(this.sessionPreviewVisibleCount))
|
|
551
|
-
: 0;
|
|
552
|
-
const targetVisible = current + step;
|
|
553
|
-
if (targetVisible <= total) {
|
|
554
|
-
this.sessionPreviewVisibleCount = Math.min(total, targetVisible);
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
544
|
|
|
558
545
|
this.sessionPreviewVisibleCount = total;
|
|
559
546
|
if (this.sessionDetailLoading) {
|
|
@@ -573,24 +560,19 @@ export async function loadMoreSessionMessages(stepSize) {
|
|
|
573
560
|
const currentLimit = Number.isFinite(currentLimitRaw)
|
|
574
561
|
? Math.max(1, Math.floor(currentLimitRaw))
|
|
575
562
|
: Math.max(1, total);
|
|
576
|
-
const fetchStep = Number.isFinite(this.sessionDetailFetchStep)
|
|
577
|
-
? Math.max(1, Math.floor(this.sessionDetailFetchStep))
|
|
578
|
-
: 80;
|
|
579
563
|
const limitCapRaw = Number(this.sessionDetailMessageLimitCap);
|
|
580
564
|
const limitCap = Number.isFinite(limitCapRaw)
|
|
581
565
|
? Math.max(1, Math.floor(limitCapRaw))
|
|
582
566
|
: 1000;
|
|
583
567
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
nextLimit = Math.min(nextLimit, limitCap);
|
|
568
|
+
const nextLimit = totalKnown > 0
|
|
569
|
+
? Math.min(totalKnown, limitCap)
|
|
570
|
+
: limitCap;
|
|
589
571
|
if (nextLimit <= currentLimit) {
|
|
590
572
|
return;
|
|
591
573
|
}
|
|
592
574
|
|
|
593
|
-
this.sessionPreviewPendingVisibleCount =
|
|
575
|
+
this.sessionPreviewPendingVisibleCount = nextLimit;
|
|
594
576
|
this.sessionDetailMessageLimit = nextLimit;
|
|
595
577
|
this.sessionPreviewLoadingMore = true;
|
|
596
578
|
try {
|
|
@@ -598,4 +580,11 @@ export async function loadMoreSessionMessages(stepSize) {
|
|
|
598
580
|
} finally {
|
|
599
581
|
this.sessionPreviewLoadingMore = false;
|
|
600
582
|
}
|
|
583
|
+
|
|
584
|
+
const loadedTotal = Array.isArray(this.activeSessionMessages)
|
|
585
|
+
? this.activeSessionMessages.length
|
|
586
|
+
: 0;
|
|
587
|
+
if (loadedTotal > this.sessionPreviewVisibleCount) {
|
|
588
|
+
this.sessionPreviewVisibleCount = loadedTotal;
|
|
589
|
+
}
|
|
601
590
|
}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
.doctor-grid {
|
|
6
6
|
display: grid;
|
|
7
|
-
grid-template-columns: repeat(
|
|
7
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
8
8
|
gap: 12px;
|
|
9
9
|
margin-top: 12px;
|
|
10
|
+
align-items: stretch;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
.doctor-card {
|
|
@@ -102,14 +103,16 @@
|
|
|
102
103
|
display: inline-flex;
|
|
103
104
|
align-items: center;
|
|
104
105
|
gap: 8px;
|
|
105
|
-
|
|
106
|
+
min-width: 150px;
|
|
107
|
+
padding: 8px 12px;
|
|
106
108
|
border-radius: 999px;
|
|
107
109
|
border: 1px solid var(--color-border-soft);
|
|
108
110
|
background: rgba(255, 255, 255, 0.78);
|
|
109
111
|
font-size: var(--font-size-caption);
|
|
110
112
|
color: var(--color-text-secondary);
|
|
111
|
-
justify-content:
|
|
112
|
-
text-align:
|
|
113
|
+
justify-content: space-between;
|
|
114
|
+
text-align: left;
|
|
115
|
+
font-variant-numeric: tabular-nums;
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
.doctor-status-chip strong {
|
|
@@ -162,27 +165,6 @@
|
|
|
162
165
|
text-align: left;
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
.doctor-health-issues {
|
|
166
|
-
display: flex;
|
|
167
|
-
flex-direction: column;
|
|
168
|
-
gap: 6px;
|
|
169
|
-
font-size: var(--font-size-caption);
|
|
170
|
-
align-items: center;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.doctor-health-issue {
|
|
174
|
-
padding: 8px 10px;
|
|
175
|
-
border-radius: 12px;
|
|
176
|
-
border: 1px solid rgba(220, 95, 108, 0.2);
|
|
177
|
-
background: rgba(255, 255, 255, 0.75);
|
|
178
|
-
color: var(--color-text-secondary);
|
|
179
|
-
overflow-wrap: anywhere;
|
|
180
|
-
word-break: break-word;
|
|
181
|
-
text-align: center;
|
|
182
|
-
width: 100%;
|
|
183
|
-
max-width: 720px;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
168
|
.doctor-action-list {
|
|
187
169
|
margin-top: 14px;
|
|
188
170
|
display: grid;
|
|
@@ -212,8 +194,11 @@
|
|
|
212
194
|
color: var(--color-text-primary);
|
|
213
195
|
min-width: 0;
|
|
214
196
|
overflow: hidden;
|
|
215
|
-
|
|
216
|
-
|
|
197
|
+
display: -webkit-box;
|
|
198
|
+
-webkit-box-orient: vertical;
|
|
199
|
+
-webkit-line-clamp: 2;
|
|
200
|
+
overflow-wrap: anywhere;
|
|
201
|
+
word-break: break-word;
|
|
217
202
|
max-width: 100%;
|
|
218
203
|
flex: 1 1 220px;
|
|
219
204
|
}
|
|
@@ -271,6 +256,46 @@
|
|
|
271
256
|
margin-top: 2px;
|
|
272
257
|
}
|
|
273
258
|
|
|
259
|
+
.doctor-result-section {
|
|
260
|
+
margin-top: 14px;
|
|
261
|
+
display: flex;
|
|
262
|
+
flex-direction: column;
|
|
263
|
+
gap: 12px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.doctor-result-section > .doctor-health-result,
|
|
267
|
+
.doctor-result-section > .doctor-action-list {
|
|
268
|
+
margin-top: 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.doctor-result-empty {
|
|
272
|
+
border: 1px dashed var(--color-border-soft);
|
|
273
|
+
border-radius: var(--radius-lg);
|
|
274
|
+
background: rgba(255, 255, 255, 0.5);
|
|
275
|
+
padding: 16px;
|
|
276
|
+
text-align: center;
|
|
277
|
+
font-size: var(--font-size-caption);
|
|
278
|
+
color: var(--color-text-tertiary);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.doctor-header .selector-actions > .doctor-run-btn {
|
|
282
|
+
background: linear-gradient(135deg, var(--color-brand) 0%, var(--color-brand-dark) 100%);
|
|
283
|
+
border-color: var(--color-brand-dark);
|
|
284
|
+
color: #fff;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.doctor-header .selector-actions > .doctor-run-btn:not(:disabled):hover {
|
|
288
|
+
border-color: var(--color-brand-dark);
|
|
289
|
+
color: #fff;
|
|
290
|
+
filter: brightness(1.05);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
@media (max-width: 1280px) {
|
|
294
|
+
.doctor-grid {
|
|
295
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
274
299
|
@media (max-width: 520px) {
|
|
275
300
|
.doctor-grid {
|
|
276
301
|
grid-template-columns: 1fr;
|
|
@@ -305,134 +330,3 @@
|
|
|
305
330
|
}
|
|
306
331
|
}
|
|
307
332
|
|
|
308
|
-
.doctor-providers-health {
|
|
309
|
-
margin-top: 12px;
|
|
310
|
-
padding: 12px;
|
|
311
|
-
border-radius: var(--radius-lg);
|
|
312
|
-
border: 1px solid var(--color-border-soft);
|
|
313
|
-
background: rgba(255, 255, 255, 0.78);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.doctor-providers-health-title {
|
|
317
|
-
font-size: var(--font-size-body);
|
|
318
|
-
font-weight: var(--font-weight-title);
|
|
319
|
-
color: var(--color-text-primary);
|
|
320
|
-
margin-bottom: 10px;
|
|
321
|
-
display: flex;
|
|
322
|
-
align-items: center;
|
|
323
|
-
gap: 8px;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.doctor-providers-health-summary {
|
|
327
|
-
font-size: var(--font-size-caption);
|
|
328
|
-
font-weight: var(--font-weight-primary);
|
|
329
|
-
color: var(--color-text-tertiary);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.doctor-providers-grid {
|
|
333
|
-
display: flex;
|
|
334
|
-
flex-wrap: wrap;
|
|
335
|
-
gap: 8px;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.doctor-provider-chip {
|
|
339
|
-
display: inline-flex;
|
|
340
|
-
align-items: center;
|
|
341
|
-
gap: 6px;
|
|
342
|
-
padding: 6px 12px;
|
|
343
|
-
border-radius: 999px;
|
|
344
|
-
border: 1px solid var(--color-border-soft);
|
|
345
|
-
background: rgba(255, 255, 255, 0.85);
|
|
346
|
-
font-size: var(--font-size-caption);
|
|
347
|
-
color: var(--color-text-secondary);
|
|
348
|
-
max-width: 100%;
|
|
349
|
-
overflow: hidden;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.doctor-provider-chip.green {
|
|
353
|
-
border-color: rgba(57, 181, 97, 0.25);
|
|
354
|
-
background: rgba(57, 181, 97, 0.08);
|
|
355
|
-
color: #2b6a3b;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
.doctor-provider-chip.yellow {
|
|
359
|
-
border-color: rgba(246, 211, 106, 0.45);
|
|
360
|
-
background: rgba(246, 211, 106, 0.16);
|
|
361
|
-
color: #6f4b00;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.doctor-provider-chip.red {
|
|
365
|
-
border-color: rgba(220, 95, 108, 0.28);
|
|
366
|
-
background: rgba(220, 95, 108, 0.08);
|
|
367
|
-
color: #8a2f36;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
.doctor-provider-name {
|
|
371
|
-
overflow: hidden;
|
|
372
|
-
text-overflow: ellipsis;
|
|
373
|
-
white-space: nowrap;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
.doctor-provider-current {
|
|
377
|
-
font-size: 0.85em;
|
|
378
|
-
opacity: 0.7;
|
|
379
|
-
margin-left: 2px;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.doctor-provider-status-dot {
|
|
383
|
-
width: 8px;
|
|
384
|
-
height: 8px;
|
|
385
|
-
border-radius: 50%;
|
|
386
|
-
flex-shrink: 0;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.doctor-provider-chip.green .doctor-provider-status-dot {
|
|
390
|
-
background: rgba(57, 181, 97, 0.7);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.doctor-provider-chip.yellow .doctor-provider-status-dot {
|
|
394
|
-
background: rgba(246, 211, 106, 0.85);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.doctor-provider-chip.red .doctor-provider-status-dot {
|
|
398
|
-
background: rgba(220, 95, 108, 0.7);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.doctor-provider-issues {
|
|
402
|
-
margin-top: 10px;
|
|
403
|
-
display: flex;
|
|
404
|
-
flex-direction: column;
|
|
405
|
-
gap: 6px;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.doctor-provider-issue-card {
|
|
409
|
-
padding: 8px 10px;
|
|
410
|
-
border-radius: 10px;
|
|
411
|
-
border: 1px solid rgba(220, 95, 108, 0.15);
|
|
412
|
-
background: rgba(255, 255, 255, 0.7);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.doctor-provider-issue-name {
|
|
416
|
-
font-weight: var(--font-weight-secondary);
|
|
417
|
-
color: var(--color-text-primary);
|
|
418
|
-
margin-bottom: 4px;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
.doctor-provider-issue-row {
|
|
422
|
-
font-size: var(--font-size-caption);
|
|
423
|
-
color: var(--color-text-secondary);
|
|
424
|
-
display: flex;
|
|
425
|
-
flex-direction: column;
|
|
426
|
-
gap: 2px;
|
|
427
|
-
padding-left: 8px;
|
|
428
|
-
margin-top: 4px;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
.doctor-provider-issue-text {
|
|
432
|
-
color: #8a2f36;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
.doctor-provider-issue-fix {
|
|
436
|
-
color: var(--color-text-tertiary);
|
|
437
|
-
font-style: italic;
|
|
438
|
-
}
|