smart-admin-web 10.20.0 → 10.21.0
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/dist/api/index.d.ts +19 -1
- package/dist/api/index.js +85 -66
- package/dist/api/index.js.map +1 -1
- package/dist/api/schema.d.ts +448 -1
- package/dist/assets/icons/ph-subset.json.js +1 -1
- package/dist/components/FormContainer/index.vue.js +87 -75
- package/dist/components/FormContainer/index.vue.js.map +1 -1
- package/dist/components/UserPicker/UserAvatar.vue.d.ts +8 -0
- package/dist/components/UserPicker/UserAvatar.vue.js +8 -0
- package/dist/components/UserPicker/UserAvatar.vue.js.map +1 -0
- package/dist/components/UserPicker/UserAvatar2.vue.js +38 -0
- package/dist/components/UserPicker/UserAvatar2.vue.js.map +1 -0
- package/dist/components/UserPicker/index.vue.js +1 -1
- package/dist/components/UserPicker/index2.vue.js +328 -186
- package/dist/components/UserPicker/index2.vue.js.map +1 -1
- package/dist/index.js +248 -246
- package/dist/layouts/NoticeBell.vue.js +2 -2
- package/dist/layouts/NoticeBell2.vue.js +18 -17
- package/dist/layouts/NoticeBell2.vue.js.map +1 -1
- package/dist/lib/runtime.js +1 -1
- package/dist/lib/watermark.d.ts +1 -1
- package/dist/locales/en-US.d.ts +62 -3
- package/dist/locales/en-US.js +66 -7
- package/dist/locales/en-US.js.map +1 -1
- package/dist/locales/kernelMenuTitles.js +2 -1
- package/dist/locales/kernelMenuTitles.js.map +1 -1
- package/dist/locales/zh-CN.d.ts +62 -3
- package/dist/locales/zh-CN.js +66 -7
- package/dist/locales/zh-CN.js.map +1 -1
- package/dist/router/viewRegistry.js +6 -6
- package/dist/router/viewRegistry.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/theme/naive-theme.js +72 -67
- package/dist/theme/naive-theme.js.map +1 -1
- package/dist/types/api.d.ts +91 -0
- package/dist/types/api.js +17 -15
- package/dist/types/api.js.map +1 -1
- package/dist/utils/shake.d.ts +1 -0
- package/dist/utils/shake.js +30 -0
- package/dist/utils/shake.js.map +1 -0
- package/dist/views/login/LoginForm.vue.js +2 -2
- package/dist/views/login/LoginForm2.vue.js +135 -135
- package/dist/views/login/LoginForm2.vue.js.map +1 -1
- package/dist/views/login/components/LoginDesk.vue.js +1 -1
- package/dist/views/login/components/LoginDesk2.vue.js +59 -47
- package/dist/views/login/components/LoginDesk2.vue.js.map +1 -1
- package/dist/views/personal/notice2.vue.js +1 -1
- package/dist/views/personal/notice2.vue.js.map +1 -1
- package/dist/views/personal/sessions.vue.js +2 -2
- package/dist/views/personal/sessions2.vue.js +41 -40
- package/dist/views/personal/sessions2.vue.js.map +1 -1
- package/dist/views/system/ai-usage/index.vue.js +3 -3
- package/dist/views/system/ai-usage/index2.vue.js +13 -12
- package/dist/views/system/ai-usage/index2.vue.js.map +1 -1
- package/dist/views/system/config/components/AdvancedSection.vue.js +3 -3
- package/dist/views/system/config/components/AdvancedSection2.vue.js +2 -1
- package/dist/views/system/config/components/AdvancedSection2.vue.js.map +1 -1
- package/dist/views/system/dict/index.vue.js +2 -2
- package/dist/views/system/dict/index2.vue.js +12 -1
- package/dist/views/system/dict/index2.vue.js.map +1 -1
- package/dist/views/system/file/index2.vue.js +1 -0
- package/dist/views/system/file/index2.vue.js.map +1 -1
- package/dist/views/system/job/index.vue.js +3 -3
- package/dist/views/system/job/index2.vue.js +182 -181
- package/dist/views/system/job/index2.vue.js.map +1 -1
- package/dist/views/system/job-log/components/AttemptTable2.vue.js +8 -3
- package/dist/views/system/job-log/components/AttemptTable2.vue.js.map +1 -1
- package/dist/views/system/job-log/index.vue.js +1 -1
- package/dist/views/system/job-log/index2.vue.js +5 -5
- package/dist/views/system/job-log/index2.vue.js.map +1 -1
- package/dist/views/system/log/exception/index.vue.js +2 -2
- package/dist/views/system/log/exception/index2.vue.js +8 -5
- package/dist/views/system/log/exception/index2.vue.js.map +1 -1
- package/dist/views/system/log/login/index2.vue.js +21 -12
- package/dist/views/system/log/login/index2.vue.js.map +1 -1
- package/dist/views/system/log/op/index.vue.js +2 -2
- package/dist/views/system/log/op/index2.vue.js +50 -40
- package/dist/views/system/log/op/index2.vue.js.map +1 -1
- package/dist/views/system/menu/components/ButtonManager.vue.js +2 -2
- package/dist/views/system/menu/components/ButtonManager2.vue.js +45 -36
- package/dist/views/system/menu/components/ButtonManager2.vue.js.map +1 -1
- package/dist/views/system/menu/index.vue.js +2 -2
- package/dist/views/system/menu/index2.vue.js +11 -11
- package/dist/views/system/menu/index2.vue.js.map +1 -1
- package/dist/views/system/module/index.vue.js +1 -1
- package/dist/views/system/module/index2.vue.js +171 -117
- package/dist/views/system/module/index2.vue.js.map +1 -1
- package/dist/views/system/notice/index.vue.js +3 -3
- package/dist/views/system/notice/index2.vue.js +1 -0
- package/dist/views/system/notice/index2.vue.js.map +1 -1
- package/dist/views/system/org/index.vue.js +2 -2
- package/dist/views/system/org/index2.vue.js +70 -67
- package/dist/views/system/org/index2.vue.js.map +1 -1
- package/dist/views/system/position/index.vue.js +2 -2
- package/dist/views/system/position/index2.vue.js +57 -48
- package/dist/views/system/position/index2.vue.js.map +1 -1
- package/dist/views/system/recycle/index.vue.js +1 -1
- package/dist/views/system/recycle/index2.vue.js +3 -1
- package/dist/views/system/recycle/index2.vue.js.map +1 -1
- package/dist/views/system/role/components/GrantMenuSheet.vue.d.ts +2 -0
- package/dist/views/system/role/components/GrantMenuSheet.vue.js +2 -2
- package/dist/views/system/role/components/GrantMenuSheet2.vue.js +54 -49
- package/dist/views/system/role/components/GrantMenuSheet2.vue.js.map +1 -1
- package/dist/views/system/role/components/GrantMenuTable.vue.js +1 -1
- package/dist/views/system/role/components/GrantMenuTable2.vue.js +159 -195
- package/dist/views/system/role/components/GrantMenuTable2.vue.js.map +1 -1
- package/dist/views/system/role/components/grantMenuGroups.d.ts +54 -0
- package/dist/views/system/role/components/grantMenuGroups.js +116 -76
- package/dist/views/system/role/components/grantMenuGroups.js.map +1 -1
- package/dist/views/system/role/index.vue.js +2 -2
- package/dist/views/system/role/index2.vue.js +152 -145
- package/dist/views/system/role/index2.vue.js.map +1 -1
- package/dist/views/system/session/index2.vue.js +39 -35
- package/dist/views/system/session/index2.vue.js.map +1 -1
- package/dist/views/system/user/components/UserGrantEffectiveTable.vue.d.ts +10 -0
- package/dist/views/system/user/components/UserGrantEffectiveTable.vue.js +5 -0
- package/dist/views/system/user/components/UserGrantEffectiveTable.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantEffectiveTable2.vue.js +96 -0
- package/dist/views/system/user/components/UserGrantEffectiveTable2.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantMenuSheet.vue.d.ts +13 -0
- package/dist/views/system/user/components/UserGrantMenuSheet.vue.js +8 -0
- package/dist/views/system/user/components/UserGrantMenuSheet.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantMenuSheet2.vue.js +216 -0
- package/dist/views/system/user/components/UserGrantMenuSheet2.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantMenuTable.vue.d.ts +13 -0
- package/dist/views/system/user/components/UserGrantMenuTable.vue.js +8 -0
- package/dist/views/system/user/components/UserGrantMenuTable.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantMenuTable2.vue.js +186 -0
- package/dist/views/system/user/components/UserGrantMenuTable2.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantNodeRow.vue.d.ts +31 -0
- package/dist/views/system/user/components/UserGrantNodeRow.vue.js +8 -0
- package/dist/views/system/user/components/UserGrantNodeRow.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantNodeRow2.vue.js +171 -0
- package/dist/views/system/user/components/UserGrantNodeRow2.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.d.ts +21 -0
- package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.js +5 -0
- package/dist/views/system/user/components/UserGrantOverviewDrawer.vue.js.map +1 -0
- package/dist/views/system/user/components/UserGrantOverviewDrawer2.vue.js +178 -0
- package/dist/views/system/user/components/UserGrantOverviewDrawer2.vue.js.map +1 -0
- package/dist/views/system/user/components/userGrantState.d.ts +64 -0
- package/dist/views/system/user/components/userGrantState.js +117 -0
- package/dist/views/system/user/components/userGrantState.js.map +1 -0
- package/dist/views/system/user/index.vue.js +2 -2
- package/dist/views/system/user/index2.vue.js +250 -207
- package/dist/views/system/user/index2.vue.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent as W, ref as u, openBlock as l, createElementBlock as d, Fragment as R, createVNode as n, unref as e, withCtx as o, createElementVNode as
|
|
1
|
+
import { defineComponent as W, ref as u, openBlock as l, createElementBlock as d, Fragment as R, createVNode as n, unref as e, withCtx as o, createElementVNode as f, toDisplayString as c, createTextVNode as p, renderList as I, normalizeClass as L, createCommentVNode as T, createBlock as S, createSlots as X } from "vue";
|
|
2
2
|
import { useRouter as Y } from "vue-router";
|
|
3
3
|
import { useMessage as Z, NPopover as ee, NButton as k, NSpin as te, NScrollbar as ae, NEmpty as oe, NTag as ne, NEllipsis as ie, NText as U, NBadge as le, NModal as se, NSpace as ce } from "naive-ui";
|
|
4
4
|
import { Icon as N } from "@iconify/vue";
|
|
@@ -8,9 +8,9 @@ import { noticeApi as b } from "../api/index.js";
|
|
|
8
8
|
import { noticeBus as de } from "../composables/useRealtime.js";
|
|
9
9
|
import { useNoticeAction as pe } from "../composables/useNoticeAction.js";
|
|
10
10
|
import { NoticeType as x } from "../types/api.js";
|
|
11
|
-
import
|
|
11
|
+
import fe from "../components/MarkdownEditor/MarkdownView.vue.js";
|
|
12
12
|
import { translateError as D } from "../utils/error.js";
|
|
13
|
-
import { fmtDateTime as
|
|
13
|
+
import { fmtDateTime as me } from "../utils/format.js";
|
|
14
14
|
const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { class: "notice-title" }, _e = {
|
|
15
15
|
key: 0,
|
|
16
16
|
class: "notice-empty"
|
|
@@ -24,7 +24,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
24
24
|
__name: "NoticeBell",
|
|
25
25
|
setup(Ae) {
|
|
26
26
|
const { t: s } = ue(), F = Y(), z = Z(), A = pe(), y = u(0), _ = u([]), C = u(!1), w = u(!1);
|
|
27
|
-
async function
|
|
27
|
+
async function m() {
|
|
28
28
|
try {
|
|
29
29
|
y.value = await b.unreadCount();
|
|
30
30
|
} catch {
|
|
@@ -48,7 +48,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
48
48
|
async function j(t) {
|
|
49
49
|
if (!t.isRead)
|
|
50
50
|
try {
|
|
51
|
-
await b.markRead(t.id), t.isRead = !0, await
|
|
51
|
+
await b.markRead(t.id), t.isRead = !0, await m();
|
|
52
52
|
} catch (i) {
|
|
53
53
|
z.error(D(i));
|
|
54
54
|
}
|
|
@@ -67,7 +67,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
67
67
|
}
|
|
68
68
|
async function H() {
|
|
69
69
|
try {
|
|
70
|
-
await b.markAllRead(), await Promise.all([
|
|
70
|
+
await b.markAllRead(), await Promise.all([m(), B()]);
|
|
71
71
|
} catch (t) {
|
|
72
72
|
z.error(D(t));
|
|
73
73
|
}
|
|
@@ -82,8 +82,8 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
82
82
|
return i.length > 60 ? i.slice(0, 60) + "…" : i;
|
|
83
83
|
}
|
|
84
84
|
return de.on(() => {
|
|
85
|
-
|
|
86
|
-
}), re(
|
|
85
|
+
m();
|
|
86
|
+
}), re(m, 3e4), m(), (t, i) => {
|
|
87
87
|
var M, V, $;
|
|
88
88
|
return l(), d(R, null, [
|
|
89
89
|
n(e(ee), {
|
|
@@ -101,7 +101,8 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
101
101
|
n(e(le), {
|
|
102
102
|
value: y.value,
|
|
103
103
|
max: 99,
|
|
104
|
-
show: y.value > 0
|
|
104
|
+
show: y.value > 0,
|
|
105
|
+
offset: [0, 5]
|
|
105
106
|
}, {
|
|
106
107
|
default: o(() => [
|
|
107
108
|
n(e(k), {
|
|
@@ -122,9 +123,9 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
122
123
|
}, 8, ["value", "show"])
|
|
123
124
|
]),
|
|
124
125
|
default: o(() => [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
f("div", he, [
|
|
127
|
+
f("div", ve, [
|
|
128
|
+
f("span", ye, c(e(s)("app.notice.title")), 1),
|
|
128
129
|
n(e(k), {
|
|
129
130
|
text: "",
|
|
130
131
|
size: "tiny",
|
|
@@ -161,8 +162,8 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
161
162
|
onClick: (Q) => q(a)
|
|
162
163
|
}, [
|
|
163
164
|
a.isRead ? T("", !0) : (l(), d("span", ke)),
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
f("div", Ne, [
|
|
166
|
+
f("div", be, [
|
|
166
167
|
n(e(ne), {
|
|
167
168
|
type: K(a.type),
|
|
168
169
|
size: "tiny",
|
|
@@ -204,7 +205,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
204
205
|
class: "item-time"
|
|
205
206
|
}, {
|
|
206
207
|
default: o(() => [
|
|
207
|
-
p(c(e(
|
|
208
|
+
p(c(e(me)(a.publishTime, { seconds: !1 })), 1)
|
|
208
209
|
]),
|
|
209
210
|
_: 2
|
|
210
211
|
}, 1024)
|
|
@@ -218,7 +219,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
218
219
|
]),
|
|
219
220
|
_: 1
|
|
220
221
|
}, 8, ["show"]),
|
|
221
|
-
|
|
222
|
+
f("div", xe, [
|
|
222
223
|
n(e(k), {
|
|
223
224
|
text: "",
|
|
224
225
|
size: "small",
|
|
@@ -250,7 +251,7 @@ const he = { class: "notice-panel" }, ve = { class: "notice-head" }, ye = { clas
|
|
|
250
251
|
default: o(() => {
|
|
251
252
|
var a;
|
|
252
253
|
return [
|
|
253
|
-
n(
|
|
254
|
+
n(fe, {
|
|
254
255
|
value: (a = h.value) == null ? void 0 : a.content
|
|
255
256
|
}, null, 8, ["value"])
|
|
256
257
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoticeBell2.vue.js","sources":["../../src/layouts/NoticeBell.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 顶栏消息通知铃铛。富面板(n-popover):无页签单列表 + 正文弹层。\n// 未读=圆点+加粗+淡主色底,已读=整行变淡;\"读没读\"是过滤器不是分类,不做成页签(筛选在个人通知页)。\n// 未读数每 30s 轮询;面板展开时拉取列表。\n// 通知带动作列表时,正文弹层底部渲染成按钮(useNoticeAction):铃铛里直接\"办\",不必先跳到目标页面找按钮。\nimport { ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n NPopover,\n NBadge,\n NButton,\n NTag,\n NEllipsis,\n NScrollbar,\n NSpace,\n NText,\n NEmpty,\n NModal,\n NSpin,\n useMessage,\n} from 'naive-ui'\nimport { Icon } from '@iconify/vue'\nimport { useIntervalFn } from '@vueuse/core'\nimport { useI18n } from 'vue-i18n'\nimport { noticeApi } from '#/api'\nimport { noticeBus } from '#/composables/useRealtime'\nimport { useNoticeAction } from '#/composables/useNoticeAction'\nimport { NoticeType, type NoticeAction, type NoticeMineItem } from '#/types/api'\nimport MarkdownView from '#/components/MarkdownEditor/MarkdownView.vue'\nimport { translateError } from '#/utils/error'\nimport { fmtDateTime } from '#/utils/format'\n\nconst { t } = useI18n()\nconst router = useRouter()\nconst message = useMessage()\nconst noticeAction = useNoticeAction()\n\nconst unread = ref(0)\nconst items = ref<NoticeMineItem[]>([])\nconst loading = ref(false)\nconst panelShow = ref(false)\n\nasync function fetchUnread() {\n try {\n unread.value = await noticeApi.unreadCount()\n } catch {\n /* 轮询失败静默,下次自愈 */\n }\n}\n// 无页签单列表:恒拉最近一页混排,未读靠条目样式强调;筛选能力在\"查看全部\"的个人通知页。\nasync function fetchList() {\n loading.value = true\n try {\n const { items: list } = await noticeApi.mine({ page: 1, pageSize: 10 })\n items.value = list\n } catch {\n items.value = []\n } finally {\n loading.value = false\n }\n}\nfunction onShow(show: boolean) {\n if (show) fetchList()\n}\n\n// 正文弹层:内容随列表取回,直接渲染(Markdown,不能纯文本直出);点条目即标记已读。\nconst showNotice = ref(false)\nconst viewNotice = ref<NoticeMineItem | null>(null)\nasync function markRead(item: NoticeMineItem) {\n if (item.isRead) return\n try {\n await noticeApi.markRead(item.id)\n item.isRead = true\n await fetchUnread()\n } catch (e) {\n message.error(translateError(e))\n }\n}\nasync function openNotice(item: NoticeMineItem) {\n viewNotice.value = item\n showNotice.value = true\n await markRead(item)\n}\n// 动作:成功后关掉弹层与面板(页面跳转时尤其要关,否则面板盖在新页面上)。\nconst running = ref<number | null>(null)\nasync function onAction(a: NoticeAction, index: number) {\n running.value = index\n try {\n if (await noticeAction.run(a)) {\n showNotice.value = false\n panelShow.value = false\n }\n } finally {\n running.value = null\n }\n}\nasync function markAllRead() {\n try {\n await noticeApi.markAllRead()\n await Promise.all([fetchUnread(), fetchList()])\n } catch (e) {\n message.error(translateError(e))\n }\n}\nfunction viewAll() {\n panelShow.value = false\n router.push('/personal/notice')\n}\n\n// 类型 → 标签色/文案。新增类型在此补一行即可。\nconst tagType = (ty: NoticeType) =>\n ty === NoticeType.Announcement ? 'warning' : ty === NoticeType.Message ? 'success' : 'info'\nconst typeLabel = (ty: NoticeType) =>\n ty === NoticeType.Announcement\n ? t('notice.typeAnnouncement')\n : ty === NoticeType.Message\n ? t('notice.typeMessage')\n : t('notice.typeNotice')\n\n// 正文摘要:去掉常见 Markdown 记号,压空白,截断。ponytail: 正则够用,要精准渲染再引 md 解析。\nfunction snippet(md?: string | null) {\n if (!md) return ''\n const s = md\n .replace(/!\\[[^\\]]*\\]\\([^)]*\\)/g, '') // 图片\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1') // 链接留文字\n .replace(/[#>*_`~-]/g, '') // 记号\n .replace(/\\s+/g, ' ')\n .trim()\n return s.length > 60 ? s.slice(0, 60) + '…' : s\n}\n\n// 双腿:实时推送到达即刷新未读(SignalR 开启时,即时);30s 轮询兜底(实时关闭/连接掉线时)。\n// VueUse 的 useEventBus.on 在组件卸载时自动退订。\nnoticeBus.on(() => {\n fetchUnread()\n})\nuseIntervalFn(fetchUnread, 30000)\nfetchUnread()\n</script>\n\n<template>\n <n-popover\n v-model:show=\"panelShow\"\n trigger=\"click\"\n placement=\"bottom-end\"\n :show-arrow=\"false\"\n style=\"padding: 0\"\n @update:show=\"onShow\"\n >\n <template #trigger>\n <n-badge :value=\"unread\" :max=\"99\" :show=\"unread > 0\">\n <n-button quaternary circle :aria-label=\"t('app.notice.title')\">\n <Icon icon=\"ph:bell\" :width=\"19\" />\n </n-button>\n </n-badge>\n </template>\n\n <div class=\"notice-panel\">\n <div class=\"notice-head\">\n <span class=\"notice-title\">{{ t('app.notice.title') }}</span>\n <n-button text size=\"tiny\" :disabled=\"unread === 0\" @click=\"markAllRead\">\n <template #icon><Icon icon=\"ph:checks\" :width=\"15\" /></template>\n {{ t('app.notice.markAllRead') }}\n </n-button>\n </div>\n\n <n-spin :show=\"loading\">\n <n-scrollbar style=\"max-height: 360px\">\n <div v-if=\"items.length === 0\" class=\"notice-empty\">\n <n-empty :description=\"t('app.notice.empty')\" size=\"small\" />\n </div>\n <ul v-else class=\"notice-list\">\n <li\n v-for=\"n in items\"\n :key=\"n.id\"\n :class=\"['notice-item', n.isRead ? 'read' : 'unread']\"\n @click=\"openNotice(n)\"\n >\n <span v-if=\"!n.isRead\" class=\"dot\" />\n <div class=\"notice-body\">\n <div class=\"line1\">\n <n-tag :type=\"tagType(n.type)\" size=\"tiny\" :bordered=\"false\" round>\n {{ typeLabel(n.type) }}\n </n-tag>\n <n-ellipsis class=\"item-title\" :class=\"{ unread: !n.isRead }\">\n {{ n.title }}\n </n-ellipsis>\n <Icon\n v-if=\"n.actions?.length\"\n icon=\"ph:lightning\"\n :width=\"13\"\n class=\"item-actions-mark\"\n />\n </div>\n <n-text v-if=\"snippet(n.content)\" depth=\"3\" class=\"item-snippet\">\n {{ snippet(n.content) }}\n </n-text>\n <n-text depth=\"3\" class=\"item-time\">\n {{ fmtDateTime(n.publishTime, { seconds: false }) }}\n </n-text>\n </div>\n </li>\n </ul>\n </n-scrollbar>\n </n-spin>\n\n <div class=\"notice-foot\">\n <n-button text size=\"small\" @click=\"viewAll\">\n {{ t('app.notice.viewAll') }}\n <template #icon><Icon icon=\"ph:arrow-right\" :width=\"14\" /></template>\n </n-button>\n </div>\n </div>\n </n-popover>\n\n <n-modal\n v-model:show=\"showNotice\"\n preset=\"card\"\n :title=\"viewNotice?.title || t('notice.detailTitle')\"\n style=\"width: 640px; max-width: 92vw\"\n >\n <MarkdownView :value=\"viewNotice?.content\" />\n <template v-if=\"viewNotice?.actions?.length\" #footer>\n <n-space justify=\"end\">\n <n-button\n v-for=\"(a, i) in viewNotice.actions\"\n :key=\"i\"\n size=\"small\"\n :type=\"noticeAction.buttonType(a)\"\n :loading=\"running === i\"\n :disabled=\"running !== null && running !== i\"\n @click=\"onAction(a, i)\"\n >\n {{ noticeAction.label(a) }}\n </n-button>\n </n-space>\n </template>\n </n-modal>\n</template>\n\n<style scoped>\n.notice-panel {\n width: 360px;\n max-width: 92vw;\n}\n.notice-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px 4px;\n}\n.notice-title {\n font-weight: 600;\n font-size: 15px;\n}\n.notice-empty {\n padding: 32px 0;\n}\n.notice-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.notice-item {\n position: relative;\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n cursor: pointer;\n border-top: 1px solid var(--separator);\n transition: background-color var(--transition-fast);\n}\n.notice-item:hover {\n background-color: var(--hover);\n}\n/* 未读:整行淡主色底(明暗主题都成立);已读:整行变淡 */\n.notice-item.unread {\n background-color: color-mix(in srgb, var(--signal) 5%, transparent);\n}\n.notice-item.unread:hover {\n background-color: color-mix(in srgb, var(--signal) 10%, transparent);\n}\n.notice-item.read {\n opacity: 0.55;\n}\n.dot {\n position: absolute;\n left: 6px;\n top: 18px;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--signal);\n}\n.notice-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.line1 {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n.item-title {\n flex: 1;\n min-width: 0;\n font-size: 14px;\n}\n.item-title.unread {\n font-weight: 600;\n}\n.item-actions-mark {\n flex-shrink: 0;\n color: var(--signal);\n}\n.item-snippet {\n font-size: 13px;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.item-time {\n font-size: 12.5px;\n}\n.notice-foot {\n display: flex;\n justify-content: center;\n padding: 8px;\n border-top: 1px solid var(--separator);\n}\n</style>\n"],"names":["t","useI18n","router","useRouter","message","useMessage","noticeAction","useNoticeAction","unread","ref","items","loading","panelShow","fetchUnread","noticeApi","fetchList","list","onShow","show","showNotice","viewNotice","markRead","item","e","translateError","openNotice","running","onAction","a","index","markAllRead","viewAll","tagType","ty","NoticeType","typeLabel","snippet","md","s","noticeBus","useIntervalFn","_createVNode","_unref","NPopover","$event","NBadge","NButton","Icon","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_toDisplayString","_createTextVNode","NSpin","NScrollbar","_openBlock","_createElementBlock","_hoisted_4","NEmpty","_hoisted_5","_Fragment","_renderList","n","_normalizeClass","_hoisted_7","_hoisted_8","_hoisted_9","NTag","NEllipsis","_a","_createBlock","NText","fmtDateTime","_hoisted_10","NModal","MarkdownView","_c","_b","NSpace","i"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NoticeBell2.vue.js","sources":["../../src/layouts/NoticeBell.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// 顶栏消息通知铃铛。富面板(n-popover):无页签单列表 + 正文弹层。\n// 未读=圆点+加粗+淡主色底,已读=整行变淡;\"读没读\"是过滤器不是分类,不做成页签(筛选在个人通知页)。\n// 未读数每 30s 轮询;面板展开时拉取列表。\n// 通知带动作列表时,正文弹层底部渲染成按钮(useNoticeAction):铃铛里直接\"办\",不必先跳到目标页面找按钮。\nimport { ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport {\n NPopover,\n NBadge,\n NButton,\n NTag,\n NEllipsis,\n NScrollbar,\n NSpace,\n NText,\n NEmpty,\n NModal,\n NSpin,\n useMessage,\n} from 'naive-ui'\nimport { Icon } from '@iconify/vue'\nimport { useIntervalFn } from '@vueuse/core'\nimport { useI18n } from 'vue-i18n'\nimport { noticeApi } from '#/api'\nimport { noticeBus } from '#/composables/useRealtime'\nimport { useNoticeAction } from '#/composables/useNoticeAction'\nimport { NoticeType, type NoticeAction, type NoticeMineItem } from '#/types/api'\nimport MarkdownView from '#/components/MarkdownEditor/MarkdownView.vue'\nimport { translateError } from '#/utils/error'\nimport { fmtDateTime } from '#/utils/format'\n\nconst { t } = useI18n()\nconst router = useRouter()\nconst message = useMessage()\nconst noticeAction = useNoticeAction()\n\nconst unread = ref(0)\nconst items = ref<NoticeMineItem[]>([])\nconst loading = ref(false)\nconst panelShow = ref(false)\n\nasync function fetchUnread() {\n try {\n unread.value = await noticeApi.unreadCount()\n } catch {\n /* 轮询失败静默,下次自愈 */\n }\n}\n// 无页签单列表:恒拉最近一页混排,未读靠条目样式强调;筛选能力在\"查看全部\"的个人通知页。\nasync function fetchList() {\n loading.value = true\n try {\n const { items: list } = await noticeApi.mine({ page: 1, pageSize: 10 })\n items.value = list\n } catch {\n items.value = []\n } finally {\n loading.value = false\n }\n}\nfunction onShow(show: boolean) {\n if (show) fetchList()\n}\n\n// 正文弹层:内容随列表取回,直接渲染(Markdown,不能纯文本直出);点条目即标记已读。\nconst showNotice = ref(false)\nconst viewNotice = ref<NoticeMineItem | null>(null)\nasync function markRead(item: NoticeMineItem) {\n if (item.isRead) return\n try {\n await noticeApi.markRead(item.id)\n item.isRead = true\n await fetchUnread()\n } catch (e) {\n message.error(translateError(e))\n }\n}\nasync function openNotice(item: NoticeMineItem) {\n viewNotice.value = item\n showNotice.value = true\n await markRead(item)\n}\n// 动作:成功后关掉弹层与面板(页面跳转时尤其要关,否则面板盖在新页面上)。\nconst running = ref<number | null>(null)\nasync function onAction(a: NoticeAction, index: number) {\n running.value = index\n try {\n if (await noticeAction.run(a)) {\n showNotice.value = false\n panelShow.value = false\n }\n } finally {\n running.value = null\n }\n}\nasync function markAllRead() {\n try {\n await noticeApi.markAllRead()\n await Promise.all([fetchUnread(), fetchList()])\n } catch (e) {\n message.error(translateError(e))\n }\n}\nfunction viewAll() {\n panelShow.value = false\n router.push('/personal/notice')\n}\n\n// 类型 → 标签色/文案。新增类型在此补一行即可。\nconst tagType = (ty: NoticeType) =>\n ty === NoticeType.Announcement ? 'warning' : ty === NoticeType.Message ? 'success' : 'info'\nconst typeLabel = (ty: NoticeType) =>\n ty === NoticeType.Announcement\n ? t('notice.typeAnnouncement')\n : ty === NoticeType.Message\n ? t('notice.typeMessage')\n : t('notice.typeNotice')\n\n// 正文摘要:去掉常见 Markdown 记号,压空白,截断。ponytail: 正则够用,要精准渲染再引 md 解析。\nfunction snippet(md?: string | null) {\n if (!md) return ''\n const s = md\n .replace(/!\\[[^\\]]*\\]\\([^)]*\\)/g, '') // 图片\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1') // 链接留文字\n .replace(/[#>*_`~-]/g, '') // 记号\n .replace(/\\s+/g, ' ')\n .trim()\n return s.length > 60 ? s.slice(0, 60) + '…' : s\n}\n\n// 双腿:实时推送到达即刷新未读(SignalR 开启时,即时);30s 轮询兜底(实时关闭/连接掉线时)。\n// VueUse 的 useEventBus.on 在组件卸载时自动退订。\nnoticeBus.on(() => {\n fetchUnread()\n})\nuseIntervalFn(fetchUnread, 30000)\nfetchUnread()\n</script>\n\n<template>\n <n-popover\n v-model:show=\"panelShow\"\n trigger=\"click\"\n placement=\"bottom-end\"\n :show-arrow=\"false\"\n style=\"padding: 0\"\n @update:show=\"onShow\"\n >\n <template #trigger>\n <!-- offset 的 y 把徽标整体下移:默认它以按钮右上角为中心、一半在按钮顶边之上,\n 顶栏面板 overflow:hidden,两三位数(99+)的胶囊顶边会被切平 -->\n <n-badge :value=\"unread\" :max=\"99\" :show=\"unread > 0\" :offset=\"[0, 5]\">\n <n-button quaternary circle :aria-label=\"t('app.notice.title')\">\n <Icon icon=\"ph:bell\" :width=\"19\" />\n </n-button>\n </n-badge>\n </template>\n\n <div class=\"notice-panel\">\n <div class=\"notice-head\">\n <span class=\"notice-title\">{{ t('app.notice.title') }}</span>\n <n-button text size=\"tiny\" :disabled=\"unread === 0\" @click=\"markAllRead\">\n <template #icon><Icon icon=\"ph:checks\" :width=\"15\" /></template>\n {{ t('app.notice.markAllRead') }}\n </n-button>\n </div>\n\n <n-spin :show=\"loading\">\n <n-scrollbar style=\"max-height: 360px\">\n <div v-if=\"items.length === 0\" class=\"notice-empty\">\n <n-empty :description=\"t('app.notice.empty')\" size=\"small\" />\n </div>\n <ul v-else class=\"notice-list\">\n <li\n v-for=\"n in items\"\n :key=\"n.id\"\n :class=\"['notice-item', n.isRead ? 'read' : 'unread']\"\n @click=\"openNotice(n)\"\n >\n <span v-if=\"!n.isRead\" class=\"dot\" />\n <div class=\"notice-body\">\n <div class=\"line1\">\n <n-tag :type=\"tagType(n.type)\" size=\"tiny\" :bordered=\"false\" round>\n {{ typeLabel(n.type) }}\n </n-tag>\n <n-ellipsis class=\"item-title\" :class=\"{ unread: !n.isRead }\">\n {{ n.title }}\n </n-ellipsis>\n <Icon\n v-if=\"n.actions?.length\"\n icon=\"ph:lightning\"\n :width=\"13\"\n class=\"item-actions-mark\"\n />\n </div>\n <n-text v-if=\"snippet(n.content)\" depth=\"3\" class=\"item-snippet\">\n {{ snippet(n.content) }}\n </n-text>\n <n-text depth=\"3\" class=\"item-time\">\n {{ fmtDateTime(n.publishTime, { seconds: false }) }}\n </n-text>\n </div>\n </li>\n </ul>\n </n-scrollbar>\n </n-spin>\n\n <div class=\"notice-foot\">\n <n-button text size=\"small\" @click=\"viewAll\">\n {{ t('app.notice.viewAll') }}\n <template #icon><Icon icon=\"ph:arrow-right\" :width=\"14\" /></template>\n </n-button>\n </div>\n </div>\n </n-popover>\n\n <n-modal\n v-model:show=\"showNotice\"\n preset=\"card\"\n :title=\"viewNotice?.title || t('notice.detailTitle')\"\n style=\"width: 640px; max-width: 92vw\"\n >\n <MarkdownView :value=\"viewNotice?.content\" />\n <template v-if=\"viewNotice?.actions?.length\" #footer>\n <n-space justify=\"end\">\n <n-button\n v-for=\"(a, i) in viewNotice.actions\"\n :key=\"i\"\n size=\"small\"\n :type=\"noticeAction.buttonType(a)\"\n :loading=\"running === i\"\n :disabled=\"running !== null && running !== i\"\n @click=\"onAction(a, i)\"\n >\n {{ noticeAction.label(a) }}\n </n-button>\n </n-space>\n </template>\n </n-modal>\n</template>\n\n<style scoped>\n.notice-panel {\n width: 360px;\n max-width: 92vw;\n}\n.notice-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px 4px;\n}\n.notice-title {\n font-weight: 600;\n font-size: 15px;\n}\n.notice-empty {\n padding: 32px 0;\n}\n.notice-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.notice-item {\n position: relative;\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n cursor: pointer;\n border-top: 1px solid var(--separator);\n transition: background-color var(--transition-fast);\n}\n.notice-item:hover {\n background-color: var(--hover);\n}\n/* 未读:整行淡主色底(明暗主题都成立);已读:整行变淡 */\n.notice-item.unread {\n background-color: color-mix(in srgb, var(--signal) 5%, transparent);\n}\n.notice-item.unread:hover {\n background-color: color-mix(in srgb, var(--signal) 10%, transparent);\n}\n.notice-item.read {\n opacity: 0.55;\n}\n.dot {\n position: absolute;\n left: 6px;\n top: 18px;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--signal);\n}\n.notice-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.line1 {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n.item-title {\n flex: 1;\n min-width: 0;\n font-size: 14px;\n}\n.item-title.unread {\n font-weight: 600;\n}\n.item-actions-mark {\n flex-shrink: 0;\n color: var(--signal);\n}\n.item-snippet {\n font-size: 13px;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.item-time {\n font-size: 12.5px;\n}\n.notice-foot {\n display: flex;\n justify-content: center;\n padding: 8px;\n border-top: 1px solid var(--separator);\n}\n</style>\n"],"names":["t","useI18n","router","useRouter","message","useMessage","noticeAction","useNoticeAction","unread","ref","items","loading","panelShow","fetchUnread","noticeApi","fetchList","list","onShow","show","showNotice","viewNotice","markRead","item","e","translateError","openNotice","running","onAction","a","index","markAllRead","viewAll","tagType","ty","NoticeType","typeLabel","snippet","md","s","noticeBus","useIntervalFn","_createVNode","_unref","NPopover","$event","NBadge","NButton","Icon","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_toDisplayString","_createTextVNode","NSpin","NScrollbar","_openBlock","_createElementBlock","_hoisted_4","NEmpty","_hoisted_5","_Fragment","_renderList","n","_normalizeClass","_hoisted_7","_hoisted_8","_hoisted_9","NTag","NEllipsis","_a","_createBlock","NText","fmtDateTime","_hoisted_10","NModal","MarkdownView","_c","_b","NSpace","i"],"mappings":"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"}
|
package/dist/lib/runtime.js
CHANGED
package/dist/lib/watermark.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare function normalizeWatermarkFields(raw: unknown): WatermarkField[]
|
|
|
57
57
|
/** 站点信息里的 watermark 节点(或任何半成品)→ 合法设置。 */
|
|
58
58
|
export declare function normalizeWatermark(raw?: Partial<Record<keyof WatermarkSettings, unknown>> | null): {
|
|
59
59
|
enabled: boolean;
|
|
60
|
-
fields: ("name" | "
|
|
60
|
+
fields: ("name" | "org" | "account" | "phone" | "time" | "text")[];
|
|
61
61
|
text: string;
|
|
62
62
|
timeFormat: "YYYY-MM-DD" | "YYYY-MM-DD HH:mm" | "YYYY-MM-DD HH:mm:ss" | "MM-DD HH:mm";
|
|
63
63
|
layout: WatermarkLayout;
|
package/dist/locales/en-US.d.ts
CHANGED
|
@@ -61,11 +61,19 @@ declare const _default: {
|
|
|
61
61
|
};
|
|
62
62
|
userPicker: {
|
|
63
63
|
title: string;
|
|
64
|
+
org: string;
|
|
64
65
|
available: string;
|
|
65
66
|
selected: string;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
searchName: string;
|
|
68
|
+
searchAccount: string;
|
|
69
|
+
selectPage: string;
|
|
70
|
+
unselectPage: string;
|
|
71
|
+
total: string;
|
|
72
|
+
existing: string;
|
|
73
|
+
remove: string;
|
|
74
|
+
emptySelected: string;
|
|
75
|
+
prevPage: string;
|
|
76
|
+
nextPage: string;
|
|
69
77
|
clear: string;
|
|
70
78
|
};
|
|
71
79
|
app: {
|
|
@@ -241,6 +249,9 @@ declare const _default: {
|
|
|
241
249
|
deleteConfirm: string;
|
|
242
250
|
disableConfirm: string;
|
|
243
251
|
builtinNoDisable: string;
|
|
252
|
+
delegatable: string;
|
|
253
|
+
delegatableHint: string;
|
|
254
|
+
builtinNotDelegatable: string;
|
|
244
255
|
saved: string;
|
|
245
256
|
deleted: string;
|
|
246
257
|
};
|
|
@@ -355,6 +366,7 @@ declare const _default: {
|
|
|
355
366
|
userToggle: string;
|
|
356
367
|
userImport: string;
|
|
357
368
|
userExport: string;
|
|
369
|
+
userGrantMenus: string;
|
|
358
370
|
roleQuery: string;
|
|
359
371
|
roleCreate: string;
|
|
360
372
|
roleUpdate: string;
|
|
@@ -551,6 +563,47 @@ declare const _default: {
|
|
|
551
563
|
totpInviteToken: string;
|
|
552
564
|
totpInviteExpires: string;
|
|
553
565
|
};
|
|
566
|
+
userGrant: {
|
|
567
|
+
action: string;
|
|
568
|
+
title: string;
|
|
569
|
+
tabGrant: string;
|
|
570
|
+
tabEffective: string;
|
|
571
|
+
hint: string;
|
|
572
|
+
noRoles: string;
|
|
573
|
+
readonly: string;
|
|
574
|
+
readonlyNoReason: string;
|
|
575
|
+
follow: string;
|
|
576
|
+
allow: string;
|
|
577
|
+
deny: string;
|
|
578
|
+
effective: string;
|
|
579
|
+
ineffective: string;
|
|
580
|
+
expired: string;
|
|
581
|
+
deniedByAncestor: string;
|
|
582
|
+
notGrantable: string;
|
|
583
|
+
expireLongTerm: string;
|
|
584
|
+
remark: string;
|
|
585
|
+
leaked: string;
|
|
586
|
+
leakedFrom: string;
|
|
587
|
+
summary: string;
|
|
588
|
+
unsaved: string;
|
|
589
|
+
invalidExpiry: string;
|
|
590
|
+
saved: string;
|
|
591
|
+
overview: string;
|
|
592
|
+
colUser: string;
|
|
593
|
+
colMenu: string;
|
|
594
|
+
colState: string;
|
|
595
|
+
colSource: string;
|
|
596
|
+
colEffect: string;
|
|
597
|
+
colStatus: string;
|
|
598
|
+
colExpire: string;
|
|
599
|
+
colGrantor: string;
|
|
600
|
+
colGrantTime: string;
|
|
601
|
+
colRemark: string;
|
|
602
|
+
adjust: string;
|
|
603
|
+
statusActive: string;
|
|
604
|
+
statusExpiring: string;
|
|
605
|
+
statusExpired: string;
|
|
606
|
+
};
|
|
554
607
|
mfa: {
|
|
555
608
|
bindTitle: string;
|
|
556
609
|
recoveryTitle: string;
|
|
@@ -1247,6 +1300,7 @@ declare const _default: {
|
|
|
1247
1300
|
grantSummary: string;
|
|
1248
1301
|
grantSummarySplit: string;
|
|
1249
1302
|
grantUnsaved: string;
|
|
1303
|
+
systemMenusBuiltinOnly: string;
|
|
1250
1304
|
dataScope: string;
|
|
1251
1305
|
scopeType: string;
|
|
1252
1306
|
customOrgs: string;
|
|
@@ -1747,6 +1801,9 @@ declare const _default: {
|
|
|
1747
1801
|
denied: string;
|
|
1748
1802
|
demoReadOnly: string;
|
|
1749
1803
|
superAdminRequired: string;
|
|
1804
|
+
menuNotGrantable: string;
|
|
1805
|
+
targetIsDelegatedAdmin: string;
|
|
1806
|
+
delegatedGrantExpiryInvalid: string;
|
|
1750
1807
|
};
|
|
1751
1808
|
user: {
|
|
1752
1809
|
notFound: string;
|
|
@@ -1757,11 +1814,13 @@ declare const _default: {
|
|
|
1757
1814
|
outOfDataScope: string;
|
|
1758
1815
|
avatarUrlInvalid: string;
|
|
1759
1816
|
cannotOperateSelf: string;
|
|
1817
|
+
menuGrantInvalid: string;
|
|
1760
1818
|
};
|
|
1761
1819
|
role: {
|
|
1762
1820
|
notFound: string;
|
|
1763
1821
|
codeExists: string;
|
|
1764
1822
|
notDelegatable: string;
|
|
1823
|
+
systemMenuNotAssignable: string;
|
|
1765
1824
|
};
|
|
1766
1825
|
org: {
|
|
1767
1826
|
notFound: string;
|
package/dist/locales/en-US.js
CHANGED
|
@@ -63,11 +63,19 @@ const e = {
|
|
|
63
63
|
},
|
|
64
64
|
userPicker: {
|
|
65
65
|
title: "Select users",
|
|
66
|
+
org: "Organizations",
|
|
66
67
|
available: "Available",
|
|
67
68
|
selected: "Selected",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
searchName: "Search by name",
|
|
70
|
+
searchAccount: "Search by account",
|
|
71
|
+
selectPage: "Select page",
|
|
72
|
+
unselectPage: "Deselect page",
|
|
73
|
+
total: "{n} users",
|
|
74
|
+
existing: "Existing",
|
|
75
|
+
remove: "Remove",
|
|
76
|
+
emptySelected: "No users selected",
|
|
77
|
+
prevPage: "Previous page",
|
|
78
|
+
nextPage: "Next page",
|
|
71
79
|
clear: "Clear"
|
|
72
80
|
},
|
|
73
81
|
app: {
|
|
@@ -243,6 +251,9 @@ const e = {
|
|
|
243
251
|
deleteConfirm: 'Delete app "{title}"?',
|
|
244
252
|
disableConfirm: 'Disable app "{title}"? It will disappear from the portal',
|
|
245
253
|
builtinNoDisable: "The built-in app cannot be disabled",
|
|
254
|
+
delegatable: "Delegatable",
|
|
255
|
+
delegatableHint: "When on, administrators can grant or deny this app's menus to individual users (time-limited)",
|
|
256
|
+
builtinNotDelegatable: "The built-in app is never delegatable",
|
|
246
257
|
saved: "Saved",
|
|
247
258
|
deleted: "Deleted"
|
|
248
259
|
},
|
|
@@ -312,7 +323,7 @@ const e = {
|
|
|
312
323
|
ops: "System Operations",
|
|
313
324
|
schedule: "Job Scheduling",
|
|
314
325
|
audit: "Audit Logs",
|
|
315
|
-
ai: "AI
|
|
326
|
+
ai: "AI Gateway"
|
|
316
327
|
},
|
|
317
328
|
page: {
|
|
318
329
|
workbench: "Workbench",
|
|
@@ -358,6 +369,7 @@ const e = {
|
|
|
358
369
|
userToggle: "User - Enable / Disable",
|
|
359
370
|
userImport: "User - Import",
|
|
360
371
|
userExport: "User - Export",
|
|
372
|
+
userGrantMenus: "User - Grant Menus",
|
|
361
373
|
roleQuery: "Role - Query",
|
|
362
374
|
roleCreate: "Role - Create",
|
|
363
375
|
roleUpdate: "Role - Update",
|
|
@@ -560,6 +572,47 @@ const e = {
|
|
|
560
572
|
totpInviteToken: "Invite token",
|
|
561
573
|
totpInviteExpires: "Expires at"
|
|
562
574
|
},
|
|
575
|
+
userGrant: {
|
|
576
|
+
action: "Grant menus",
|
|
577
|
+
title: "Grant menus · {name}",
|
|
578
|
+
tabGrant: "Individual grants",
|
|
579
|
+
tabEffective: "Effective access",
|
|
580
|
+
hint: "Grant through roles as usual and keep only exceptions here. Allow covers that one node; Deny also revokes everything below it and beats any allow.",
|
|
581
|
+
noRoles: 'This user has no role, so the data scope is "self only": granted pages open but show only data the user created.',
|
|
582
|
+
readonly: "View only: {reason}",
|
|
583
|
+
readonlyNoReason: "View only",
|
|
584
|
+
follow: "Follow roles",
|
|
585
|
+
allow: "Allow",
|
|
586
|
+
deny: "Deny",
|
|
587
|
+
effective: "Effective",
|
|
588
|
+
ineffective: "Not effective",
|
|
589
|
+
expired: "Expired",
|
|
590
|
+
deniedByAncestor: "Denied by parent",
|
|
591
|
+
notGrantable: "Only a super admin can grant menus in this module",
|
|
592
|
+
expireLongTerm: "No expiry",
|
|
593
|
+
remark: "Reason (optional)",
|
|
594
|
+
leaked: "These APIs stay callable:",
|
|
595
|
+
leakedFrom: "{code} (from {from})",
|
|
596
|
+
summary: "Allow {allow} · Deny {deny}",
|
|
597
|
+
unsaved: "Unsaved changes",
|
|
598
|
+
invalidExpiry: "{count} record(s) have a missing or out-of-range expiry date",
|
|
599
|
+
saved: "Grants saved",
|
|
600
|
+
overview: "Individual grants",
|
|
601
|
+
colUser: "User",
|
|
602
|
+
colMenu: "Menu",
|
|
603
|
+
colState: "State",
|
|
604
|
+
colSource: "Source",
|
|
605
|
+
colEffect: "Effect",
|
|
606
|
+
colStatus: "Validity",
|
|
607
|
+
colExpire: "Expires",
|
|
608
|
+
colGrantor: "Granted by",
|
|
609
|
+
colGrantTime: "Granted at",
|
|
610
|
+
colRemark: "Reason",
|
|
611
|
+
adjust: "Adjust",
|
|
612
|
+
statusActive: "Active",
|
|
613
|
+
statusExpiring: "Expiring in 7 days",
|
|
614
|
+
statusExpired: "Expired"
|
|
615
|
+
},
|
|
563
616
|
mfa: {
|
|
564
617
|
bindTitle: "Set up authenticator",
|
|
565
618
|
recoveryTitle: "Use recovery code",
|
|
@@ -1250,6 +1303,7 @@ const e = {
|
|
|
1250
1303
|
grantSummary: "Granted {on} / {total}",
|
|
1251
1304
|
grantSummarySplit: "{pages} pages · {buttons} buttons",
|
|
1252
1305
|
grantUnsaved: "Unsaved changes",
|
|
1306
|
+
systemMenusBuiltinOnly: "Apart from User Management and Role Management, menus that ship with the system can only be granted to built-in roles and are hidden here",
|
|
1253
1307
|
dataScope: "Data scope",
|
|
1254
1308
|
scopeType: "Scope type",
|
|
1255
1309
|
customOrgs: "Custom orgs",
|
|
@@ -1747,7 +1801,10 @@ const e = {
|
|
|
1747
1801
|
perm: {
|
|
1748
1802
|
denied: "Access denied",
|
|
1749
1803
|
demoReadOnly: "Demo environment is read-only",
|
|
1750
|
-
superAdminRequired: "This action requires super admin privileges"
|
|
1804
|
+
superAdminRequired: "This action requires super admin privileges",
|
|
1805
|
+
menuNotGrantable: "This menu's module does not allow delegated grants",
|
|
1806
|
+
targetIsDelegatedAdmin: "The user is an administrator; only a super admin can grant them menus individually",
|
|
1807
|
+
delegatedGrantExpiryInvalid: "An allow grant needs an expiry date at most {maxDays} days away"
|
|
1751
1808
|
},
|
|
1752
1809
|
user: {
|
|
1753
1810
|
notFound: "User not found",
|
|
@@ -1757,12 +1814,14 @@ const e = {
|
|
|
1757
1814
|
passwordReused: "New password must differ from your current and recently used passwords",
|
|
1758
1815
|
outOfDataScope: "Target user is outside your data scope",
|
|
1759
1816
|
avatarUrlInvalid: "Avatar URL is not allowed",
|
|
1760
|
-
cannotOperateSelf: "You cannot perform this action on yourself"
|
|
1817
|
+
cannotOperateSelf: "You cannot perform this action on yourself",
|
|
1818
|
+
menuGrantInvalid: "Invalid grant changes: each menu at most once, and the expiry must be in the future"
|
|
1761
1819
|
},
|
|
1762
1820
|
role: {
|
|
1763
1821
|
notFound: "Role not found",
|
|
1764
1822
|
codeExists: "Role code already exists",
|
|
1765
|
-
notDelegatable: "Role is not delegatable"
|
|
1823
|
+
notDelegatable: "Role is not delegatable",
|
|
1824
|
+
systemMenuNotAssignable: "Apart from User Management and Role Management, menus that ship with the system can only be granted to built-in roles"
|
|
1766
1825
|
},
|
|
1767
1826
|
org: {
|
|
1768
1827
|
notFound: "Org not found",
|