Files
console-dev/app/components/home/HomeNoticePanel.vue
T

448 lines
16 KiB
Vue

<script>
/**
* 首页公告:最多 5 条,详情弹窗另行请求正文。列表与详情序号独立,卸载后废弃旧响应。
* 刷新失败保留旧列表但禁止交互,避免把旧内容当作最新成功结果。
*/
import "~/assets/styles/HomeNoticePanel.e5-qgzAs.css";
import { toDisplayString } from "vue";
import { renderList } from "vue";
import { onMounted } from "vue";
import { onBeforeUnmount } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import dialog from "primevue/dialog";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import { n as dict_n } from "~/lib/dict.js";
import { r as dict_r } from "~/lib/dict.js";
import ListEmpty from "~/components/ListEmpty.vue";
import skeleton from "primevue/skeleton";
import { n as sanitize_n } from "~/lib/sanitize.js";
var O = [`aria-busy`],
k = {
class: `home-card-head`,
},
A = {
key: 1,
class: `home-list`,
},
j = [`inert`, `aria-disabled`],
M = [`onClick`],
N = {
class: `home-row-title notice-title`,
},
P = {
class: `home-row-sub`,
},
F = {
class: `home-card-foot`,
},
I = {
key: 0,
},
L = {
key: 2,
class: `detail`,
},
R = {
class: `detail-time`,
},
z = [`innerHTML`],
B = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `HomeNoticePanel`,
setup(m) {
let x = useApi(),
B = ref([]),
V = ref(!0),
H = ref(!1),
U = ref(``),
W = !1,
G = 0,
K = ref(!1),
q = ref(null),
J = ref(!1),
Y = ref(``),
X = ref(null),
Z = 0;
// 互斥加载;已加载标记区分首次失败与刷新失败,后者保留原数据并提供重试。
async function Q() {
if (W) return;
let e = ++G;
((W = !0), (V.value = !0), (U.value = ``));
try {
let t = await x.get(`/announcement`, {
page: 1,
limit: 5,
});
if (e !== G) return;
((B.value = t.list ?? []), (H.value = !0));
} catch (t) {
if (e !== G) return;
U.value = t instanceof Error ? t.message : `公告加载失败`;
} finally {
e === G && ((V.value = !1), (W = !1));
}
}
(onMounted(Q),
onBeforeUnmount(() => {
(G++, Z++);
}));
// 切换详情先清空旧正文,再按最新请求序号接纳结果;已删除公告明确报错。
async function $(e) {
let t = ++Z;
((K.value = !0),
(J.value = !0),
(X.value = e),
(Y.value = ``),
(q.value = null));
try {
let n = await x.get(`/announcement/${e.id}`);
if (t !== Z) return;
if (!n.announcement) throw Error(`公告不存在或已删除`);
q.value = n.announcement;
} catch (e) {
t === Z &&
(Y.value =
e instanceof Error ? e.message : `正文加载失败,请重试`);
} finally {
t === Z && (J.value = !1);
}
}
// 正文经过公共 sanitizeHtml 清理再注入;列表出错时 inert 关闭旧条目交互。
return (n, r) => {
let a = NuxtLink,
m = button,
v = message,
x = skeleton,
W = ListEmpty,
G = dialog;
return (
openBlock(),
createElementBlock(
`div`,
{
class: `home-card`,
"aria-busy": unref(V),
},
[
createElementVNode(`div`, k, [
(r[4] ||= createElementVNode(
`div`,
{
class: `home-card-title`,
},
`公告板`,
-1,
)),
createVNode(
a,
{
to: `/notices`,
class: `home-card-more`,
"aria-label": `全部公告`,
},
{
default: withCtx(() => [
...(r[3] ||= [
createElementVNode(
`i`,
{
class: `pi pi-angle-right`,
},
null,
-1,
),
]),
]),
_: 1,
},
),
]),
unref(U) && unref(H)
? (openBlock(),
createBlock(
v,
{
key: 0,
severity: `error`,
closable: !1,
role: `alert`,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(U)), 1),
createVNode(
m,
{
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
text: ``,
disabled: unref(V),
onClick: Q,
},
null,
8,
[`disabled`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(V) && !unref(H)
? (openBlock(),
createElementBlock(`div`, A, [
(openBlock(),
createElementBlock(
Fragment,
null,
renderList(5, (e) =>
createElementVNode(
`div`,
{
key: e,
class: `home-row-skeleton`,
},
[
createVNode(x, {
height: `14px`,
width: `70%`,
}),
],
),
),
64,
)),
]))
: unref(U) && !unref(H)
? (openBlock(),
createBlock(
W,
{
key: 2,
icon: `pi pi-exclamation-circle`,
title: `公告加载失败`,
description: unref(U),
},
{
default: withCtx(() => [
createVNode(m, {
label: `重新加载`,
icon: `pi pi-refresh`,
severity: `secondary`,
size: `small`,
onClick: Q,
}),
]),
_: 1,
},
8,
[`description`],
))
: unref(B).length
? (openBlock(),
createElementBlock(
`div`,
{
key: 4,
class: `home-list`,
inert: unref(U) ? !0 : void 0,
"aria-disabled": !!unref(U),
},
[
(openBlock(!0),
createElementBlock(
Fragment,
null,
renderList(
unref(B),
(t) => (
openBlock(),
createElementBlock(
`button`,
{
key: t.id,
type: `button`,
class: `home-row notice-row`,
onClick: (e) => $(t),
},
[
createElementVNode(
`span`,
N,
toDisplayString(t.title),
1,
),
createElementVNode(
`span`,
P,
toDisplayString(
(`formatDate` in n
? n.formatDate
: unref(dict_n))(t.create_time),
),
1,
),
],
8,
M,
)
),
),
128,
)),
],
8,
j,
))
: (openBlock(),
createBlock(W, {
key: 3,
icon: `pi pi-megaphone`,
title: `暂无公告`,
description: `平台公告与通知会显示在这里`,
})),
createElementVNode(`div`, F, [
createVNode(
a,
{
to: `/notices`,
class: `home-button secondary`,
},
{
default: withCtx(() => [
...(r[5] ||= [createTextVNode(`查看全部`, -1)]),
]),
_: 1,
},
),
]),
createVNode(
G,
{
visible: unref(K),
"onUpdate:visible": (r[2] ||= (e) =>
isRef(K) ? (K.value = e) : null),
header: unref(X)?.title || `公告详情`,
modal: ``,
draggable: !1,
style: {
width: `640px`,
},
},
{
footer: withCtx(() => [
unref(Y) && unref(X)
? (openBlock(),
createBlock(m, {
key: 0,
label: `重新加载正文`,
icon: `pi pi-refresh`,
severity: `secondary`,
onClick: (r[0] ||= (e) => $(unref(X))),
}))
: createCommentVNode(``, !0),
createVNode(m, {
label: `关闭`,
severity: `secondary`,
text: ``,
onClick: (r[1] ||= (e) => (K.value = !1)),
}),
]),
default: withCtx(() => [
unref(J)
? (openBlock(),
createElementBlock(`div`, I, [
createVNode(x, {
height: `120px`,
}),
]))
: unref(Y)
? (openBlock(),
createBlock(
v,
{
key: 1,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(unref(Y)),
1,
),
]),
_: 1,
},
))
: unref(q)
? (openBlock(),
createElementBlock(`div`, L, [
createElementVNode(
`div`,
R,
toDisplayString(
(`formatTime` in n
? n.formatTime
: unref(dict_r))(unref(q).create_time),
),
1,
),
createElementVNode(
`div`,
{
class: `detail-content`,
innerHTML: (`sanitizeHtml` in n
? n.sanitizeHtml
: unref(sanitize_n))(
unref(q).content || ``,
),
},
null,
8,
z,
),
]))
: createCommentVNode(``, !0),
]),
_: 1,
},
8,
[`visible`, `header`],
),
],
8,
O,
)
);
};
},
}),
[[`__scopeId`, `data-v-a93c47c1`]],
),
{
__name: `HomeNoticePanel`,
},
);
export {};
export default B;
</script>