448 lines
16 KiB
Vue
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>
|