功能(提醒):统一项目提醒中心与桌面通知链路
增加通用提醒状态、数据库迁移和定时同步,覆盖风险时效、文件回执、项目里程碑、访视窗口与协作申请。 新增网页端和桌面端提醒中心、真实投递诊断与固定隐私通知正文,并补齐登录来源聚合、测试和说明文档。
This commit is contained in:
@@ -260,6 +260,9 @@ describe("ApiEndpointPermissions.vue", () => {
|
||||
]);
|
||||
expect((wrapper.vm as any).filteredOperations.filter((operation: any) => operation.operation_key === "subject_aes:read")).toHaveLength(2);
|
||||
expect((wrapper.vm as any).filteredOperations.filter((operation: any) => operation.operation_key === "subject_pds:list")).toHaveLength(2);
|
||||
expect((wrapper.vm as any).displayOperations).toHaveLength(5);
|
||||
expect((wrapper.vm as any).totalPermissionCount).toBe(3);
|
||||
expect((wrapper.vm as any).filteredPermissionCount).toBe(3);
|
||||
});
|
||||
|
||||
it("keeps contract fee permissions as one module section", () => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<span class="toolbar-title">有效权限矩阵</span>
|
||||
<el-tag size="small" effect="plain" type="info">只读</el-tag>
|
||||
</div>
|
||||
<span class="toolbar-result">显示 {{ filteredOperations.length }} / {{ displayOperations.length }} 项权限</span>
|
||||
<span class="toolbar-result">显示 {{ filteredPermissionCount }} / {{ totalPermissionCount }} 项权限</span>
|
||||
</div>
|
||||
<div class="toolbar-filters">
|
||||
<el-input
|
||||
@@ -266,6 +266,12 @@ const filteredOperations = computed(() => {
|
||||
return filtered;
|
||||
});
|
||||
|
||||
const countUniquePermissions = (rows: DisplayOperation[]): number =>
|
||||
new Set(rows.map((operation) => operation.operation_key)).size;
|
||||
|
||||
const totalPermissionCount = computed(() => countUniquePermissions(displayOperations.value));
|
||||
const filteredPermissionCount = computed(() => countUniquePermissions(filteredOperations.value));
|
||||
|
||||
// 权限类型、模块与模块细分列合并行
|
||||
const spanMethod = ({ row, rowIndex, columnIndex }: { row: DisplayOperation; rowIndex: number; column: any; columnIndex: number }) => {
|
||||
if (columnIndex === 0) {
|
||||
|
||||
@@ -296,6 +296,18 @@
|
||||
<div v-else class="reminder-empty">
|
||||
{{ headerRemindersLoading ? TEXT.common.loading : TEXT.common.labels.projectRemindersEmpty }}
|
||||
</div>
|
||||
<div class="reminder-actions">
|
||||
<el-dropdown-item command="notification:center" class="reminder-footer">
|
||||
查看全部提醒
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="headerReminderTotal > 0"
|
||||
command="notification:read-all"
|
||||
class="reminder-footer is-secondary"
|
||||
>
|
||||
全部已读
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@@ -2148,6 +2160,28 @@ useDesktopShortcuts(
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.reminder-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
margin-top: 6px;
|
||||
border-top: 1px solid rgba(138, 155, 176, 0.2);
|
||||
}
|
||||
|
||||
.reminder-actions .reminder-footer:only-child {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.reminder-footer {
|
||||
justify-content: center;
|
||||
color: #2f6fed !important;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.reminder-footer.is-secondary {
|
||||
color: #718096 !important;
|
||||
}
|
||||
|
||||
.activity-button {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ const readTauriLibSource = () => readSource(resolve(__dirname, "../../src-tauri/
|
||||
const readDesktopPreferencesSource = () => readSource(resolve(__dirname, "../views/DesktopPreferences.vue"));
|
||||
const readDesktopServerSettingsSource = () => readSource(resolve(__dirname, "../views/DesktopServerSettings.vue"));
|
||||
const readDesktopUpdateManagerSource = () => readSource(resolve(__dirname, "../session/desktopUpdateManager.ts"));
|
||||
const readDesktopNotificationManagerSource = () => readSource(resolve(__dirname, "../session/desktopNotificationManager.ts"));
|
||||
const readDesktopActivityCenterSource = () => readSource(resolve(__dirname, "../session/desktopActivityCenter.ts"));
|
||||
const readProfileSettingsSource = () => readSource(resolve(__dirname, "../views/ProfileSettings.vue"));
|
||||
const readLoginSource = () => readSource(resolve(__dirname, "../views/Login.vue"));
|
||||
@@ -484,9 +485,10 @@ describe("desktop layout shell", () => {
|
||||
expect(navigation).toContain("item.children?.length ? item.children : [item]");
|
||||
});
|
||||
|
||||
it("keeps notification and update preferences lightweight", () => {
|
||||
it("shows the real notification delivery path and keeps native notification access constrained", () => {
|
||||
const serverSettings = readDesktopServerSettingsSource();
|
||||
const preferences = readDesktopPreferencesSource();
|
||||
const desktopNotificationManager = readDesktopNotificationManagerSource();
|
||||
const desktopUpdateManager = readDesktopUpdateManagerSource();
|
||||
const desktopLayout = readDesktopLayoutSource();
|
||||
|
||||
@@ -503,17 +505,25 @@ describe("desktop layout shell", () => {
|
||||
expect(preferences).not.toContain("服务器连通性正常");
|
||||
expect(preferences).not.toContain("服务器连接已确认");
|
||||
expect(preferences).toContain("auth.logout({ rememberCurrentStudy: false })");
|
||||
expect(preferences).not.toContain("系统通知已开启");
|
||||
expect(preferences).not.toContain("系统通知已关闭");
|
||||
expect(preferences).not.toContain("已授权");
|
||||
expect(preferences).toContain("showNotificationPermissionTag");
|
||||
expect(preferences).toContain("系统权限:{{ notificationPermissionText }}");
|
||||
expect(preferences).toContain("服务端订阅");
|
||||
expect(preferences).toContain("真实业务路径");
|
||||
expect(preferences).toContain("授权并开启");
|
||||
expect(preferences).toContain("重新检测权限");
|
||||
expect(preferences).toContain("立即检查业务提醒");
|
||||
expect(preferences).toContain("系统设置 → 通知 → CTMS");
|
||||
expect(preferences).toContain("设置 → 系统 → 通知 → CTMS");
|
||||
expect(preferences).toContain("showSystemNotificationProbe");
|
||||
expect(preferences).toContain("sendDesktopNotificationTest");
|
||||
expect(preferences).toContain("测试通知");
|
||||
expect(preferences).not.toContain("通知诊断");
|
||||
expect(preferences).toContain("发送测试通知");
|
||||
expect(preferences).toContain("openProjectNotificationCenter");
|
||||
expect(preferences).toContain("listenDesktopNotificationStatus");
|
||||
expect(preferences).not.toContain("更新诊断");
|
||||
expect(preferences).not.toContain("listenDesktopNotificationDiagnostics");
|
||||
expect(preferences).not.toContain(["@tauri-apps", "plugin-notification"].join("/"));
|
||||
expect(desktopNotificationManager).toContain("claimDesktopNotifications");
|
||||
expect(desktopNotificationManager).toContain("acknowledgeDesktopNotifications");
|
||||
expect(desktopNotificationManager).toContain('state: "permission-required"');
|
||||
expect(desktopNotificationManager).toContain('state: deliveredIds.length ? "delivered" : "ready"');
|
||||
expect(preferences).toContain("listenDesktopUpdateStatus");
|
||||
expect(preferences).toContain("promptForPendingDesktopUpdate");
|
||||
expect(preferences).toContain("当前已是最新版本");
|
||||
@@ -603,6 +613,10 @@ describe("desktop layout shell", () => {
|
||||
expect(styles).toContain(".desktop-workbench .desktop-route-shell .el-table td.el-table__cell");
|
||||
expect(styles).toContain("padding: 7px 10px;");
|
||||
expect(styles).toContain(".desktop-workbench .desktop-route-shell .el-pagination");
|
||||
expect(styles).toContain(".desktop-workbench .desktop-route-shell .el-radio-button__inner");
|
||||
expect(styles).toContain("display: inline-flex;");
|
||||
expect(styles).toContain("align-items: center;");
|
||||
expect(styles).toContain("justify-content: center;");
|
||||
expect(styles).toContain(".desktop-workbench .desktop-route-shell .el-drawer__body");
|
||||
expect(styles).toContain(":root[data-ctms-theme=\"dark\"] .desktop-workbench .desktop-route-shell .hero-stat");
|
||||
});
|
||||
|
||||
@@ -289,7 +289,18 @@
|
||||
<div v-else class="header-reminder-empty">
|
||||
{{ headerRemindersLoading ? TEXT.common.loading : TEXT.common.labels.projectRemindersEmpty }}
|
||||
</div>
|
||||
|
||||
<div class="header-reminder-actions">
|
||||
<el-dropdown-item command="notification:center" class="header-reminder-footer">
|
||||
查看全部提醒
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="headerReminderTotal > 0"
|
||||
command="notification:read-all"
|
||||
class="header-reminder-footer is-secondary"
|
||||
>
|
||||
全部已读
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@@ -1848,6 +1859,21 @@ useDesktopShortcuts(
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.header-reminder-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
margin-top: 6px;
|
||||
border-top: 1px solid rgba(148, 163, 184, 0.2);
|
||||
}
|
||||
|
||||
.header-reminder-actions .header-reminder-footer:only-child {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.header-reminder-footer.is-secondary {
|
||||
color: #64748b !important;
|
||||
}
|
||||
|
||||
.collapse-btn {
|
||||
border: 1px solid transparent;
|
||||
color: var(--ctms-text-secondary);
|
||||
|
||||
Reference in New Issue
Block a user