555 lines
19 KiB
Vue
555 lines
19 KiB
Vue
<script>
|
|
/**
|
|
* 平台公告:分类、关键词和排序分页查询;详情路由与资源中心嵌入共用加载逻辑,列表和详情分别维护请求代次。
|
|
*/
|
|
import { definePageMeta } from "#imports";
|
|
import "~/assets/styles/notices.BXNGOj-Q.css";
|
|
definePageMeta({
|
|
key: (e) => e.fullPath,
|
|
alias: [`/notices/notice`],
|
|
});
|
|
import { toDisplayString } from "vue";
|
|
import { renderList } from "vue";
|
|
import { onMounted } from "vue";
|
|
import { onBeforeUnmount } from "vue";
|
|
import { watch } 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 { withKeys } from "vue";
|
|
import { useRoute } from "#app";
|
|
import { NuxtLink } from "#components";
|
|
import { useApi } from "~/lib/auth.js";
|
|
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 inputtext from "primevue/inputtext";
|
|
import { r as dict_r } from "~/lib/dict.js";
|
|
import paginator from "primevue/paginator";
|
|
import select from "primevue/select";
|
|
import ListEmpty from "~/components/ListEmpty.vue";
|
|
import skeleton from "primevue/skeleton";
|
|
import { n as sanitize_n } from "~/lib/sanitize.js";
|
|
import { t as composables_t } from "~/lib/composables-2.js";
|
|
import { t as content_route_t } from "~/lib/content-route.js";
|
|
var ue = {
|
|
key: 0,
|
|
class: `list-page notices-page`,
|
|
},
|
|
w = {
|
|
class: `list-toolbar`,
|
|
},
|
|
de = {
|
|
key: 1,
|
|
class: `notice-list`,
|
|
},
|
|
fe = {
|
|
key: 2,
|
|
class: `notice-list`,
|
|
},
|
|
T = {
|
|
class: `notice-title`,
|
|
},
|
|
pe = {
|
|
class: `notice-time`,
|
|
},
|
|
me = {
|
|
key: 1,
|
|
class: `notice-article`,
|
|
},
|
|
he = {
|
|
key: 0,
|
|
},
|
|
ge = {
|
|
class: `detail-time`,
|
|
},
|
|
E = [`innerHTML`],
|
|
D = _plugin_vue_export_helper_t(
|
|
defineComponent({
|
|
__name: `index`,
|
|
props: {
|
|
embedded: {
|
|
type: Boolean,
|
|
},
|
|
},
|
|
setup(h) {
|
|
let b = h,
|
|
D = useApi(),
|
|
O = useRoute();
|
|
composables_t({
|
|
alias: `/notices/notice`,
|
|
key: (e) => e.fullPath,
|
|
});
|
|
let k = ref([]),
|
|
A = ref(0),
|
|
j = ref(!0),
|
|
M = ref(``),
|
|
N = ref(1),
|
|
P = ref(10),
|
|
F = ref(``),
|
|
I = ref(``),
|
|
L = ref(`desc`),
|
|
R = ref(null),
|
|
z = ref([]),
|
|
B = ref(``),
|
|
V = 0,
|
|
H = !1;
|
|
// 公告分类独立加载;失败单独显示分类错误,不混淆正文状态。
|
|
async function U() {
|
|
B.value = ``;
|
|
try {
|
|
let e = await D.get(`/announcement/type`);
|
|
H || (z.value = e.list || []);
|
|
} catch (e) {
|
|
H ||
|
|
(B.value = e instanceof Error ? e.message : `公告分类加载失败`);
|
|
}
|
|
}
|
|
// 应用搜索词并回到第一页。
|
|
function W() {
|
|
((I.value = F.value.trim()), (N.value = 1), Z());
|
|
}
|
|
let G = ref(!1),
|
|
K = ref(null),
|
|
q = ref(!1),
|
|
J = ref(``),
|
|
Y = ref(null),
|
|
X = 0;
|
|
// 读取当前分页和筛选的公告;较早的响应或离页响应不再覆盖列表。
|
|
async function Z() {
|
|
let e = ++V;
|
|
((j.value = !0), (M.value = ``));
|
|
try {
|
|
let t = await D.get(`/announcement`, {
|
|
page: N.value,
|
|
limit: P.value,
|
|
keywords: I.value,
|
|
addon_idcsmart_announcement_type_id: R.value ?? void 0,
|
|
orderby: `id`,
|
|
sort: L.value,
|
|
});
|
|
if (H || e !== V) return;
|
|
((k.value = t.list), (A.value = t.count));
|
|
} catch (t) {
|
|
if (H || e !== V) return;
|
|
((M.value = t instanceof Error ? t.message : `加载公告失败`),
|
|
(k.value = []),
|
|
(A.value = 0));
|
|
} finally {
|
|
!H && e === V && (j.value = !1);
|
|
}
|
|
}
|
|
// 打开公告详情前清空上一条正文,只有当前详情请求可以更新弹窗。
|
|
async function Q(e) {
|
|
let t = ++X;
|
|
((G.value = !0),
|
|
(q.value = !0),
|
|
(Y.value = e),
|
|
(J.value = ``),
|
|
(K.value = null));
|
|
try {
|
|
let n = await D.get(`/announcement/${e.id}`);
|
|
if (t !== X) return;
|
|
if (!n.announcement) throw Error(`公告不存在或已删除`);
|
|
K.value = n.announcement;
|
|
} catch (e) {
|
|
t === X &&
|
|
(J.value =
|
|
e instanceof Error ? e.message : `正文加载失败,请重试`);
|
|
} finally {
|
|
t === X && (q.value = !1);
|
|
}
|
|
}
|
|
// 把零基分页器事件转换为接口页码,并使用事件给出的每页条数。
|
|
function _e(e) {
|
|
((N.value = e.page + 1), (P.value = e.rows), Z());
|
|
}
|
|
// 从公告详情路由解析 ID,无效编号只提示,不发送详情请求。
|
|
async function $() {
|
|
if (H) return;
|
|
let e = O.query.id !== void 0 || O.path === `/notices/notice`,
|
|
t = content_route_t(O.query.id);
|
|
if (!e || !t) {
|
|
(X++,
|
|
(G.value = e),
|
|
(q.value = !1),
|
|
(K.value = null),
|
|
(Y.value = null),
|
|
(J.value = e ? `公告编号无效,请从列表重新选择` : ``));
|
|
return;
|
|
}
|
|
await Q(
|
|
k.value.find((e) => e.id === t) ?? {
|
|
id: t,
|
|
title: `公告详情`,
|
|
create_time: 0,
|
|
},
|
|
);
|
|
}
|
|
return (
|
|
onMounted(async () => {
|
|
(U(), await Promise.all([Z(), $()]));
|
|
}),
|
|
watch(() => O.query.id, $),
|
|
onBeforeUnmount(() => {
|
|
((H = !0), (X += 1), V++);
|
|
}),
|
|
// 公告列表与正文弹窗使用不同错误/加载状态,详情内容经公共清理工具处理后渲染。
|
|
(n, r) => {
|
|
let i = inputtext,
|
|
o = select,
|
|
h = button,
|
|
v = message,
|
|
y = skeleton,
|
|
S = NuxtLink,
|
|
C = ListEmpty,
|
|
D = paginator;
|
|
return unref(G)
|
|
? (openBlock(),
|
|
createElementBlock(`article`, me, [
|
|
createVNode(
|
|
S,
|
|
{
|
|
to: b.embedded
|
|
? `/resources?section=notices`
|
|
: `/notices`,
|
|
class: `article-back`,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
...(r[5] ||= [
|
|
createElementVNode(
|
|
`i`,
|
|
{
|
|
class: `pi pi-arrow-left`,
|
|
},
|
|
null,
|
|
-1,
|
|
),
|
|
createTextVNode(` 返回公告`, -1),
|
|
]),
|
|
]),
|
|
_: 1,
|
|
},
|
|
8,
|
|
[`to`],
|
|
),
|
|
createElementVNode(
|
|
`h1`,
|
|
null,
|
|
toDisplayString(
|
|
unref(K)?.title || unref(Y)?.title || `公告详情`,
|
|
),
|
|
1,
|
|
),
|
|
unref(q)
|
|
? (openBlock(),
|
|
createElementBlock(`div`, he, [
|
|
createVNode(y, {
|
|
height: `180px`,
|
|
}),
|
|
]))
|
|
: unref(J)
|
|
? (openBlock(),
|
|
createBlock(
|
|
v,
|
|
{
|
|
key: 1,
|
|
severity: `error`,
|
|
closable: !1,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
createTextVNode(toDisplayString(unref(J)), 1),
|
|
unref(Y)
|
|
? (openBlock(),
|
|
createBlock(h, {
|
|
key: 0,
|
|
label: `重新加载正文`,
|
|
text: ``,
|
|
onClick: (r[3] ||= (e) => Q(unref(Y))),
|
|
}))
|
|
: createCommentVNode(``, !0),
|
|
]),
|
|
_: 1,
|
|
},
|
|
))
|
|
: unref(K)
|
|
? (openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
{
|
|
key: 2,
|
|
},
|
|
[
|
|
createElementVNode(
|
|
`p`,
|
|
ge,
|
|
`发布时间\u3000` +
|
|
toDisplayString(
|
|
(`formatTime` in n
|
|
? n.formatTime
|
|
: unref(dict_r))(unref(K).create_time),
|
|
),
|
|
1,
|
|
),
|
|
createElementVNode(
|
|
`div`,
|
|
{
|
|
class: `detail-content`,
|
|
innerHTML: (`sanitizeHtml` in n
|
|
? n.sanitizeHtml
|
|
: unref(sanitize_n))(
|
|
unref(K).content || ``,
|
|
),
|
|
},
|
|
null,
|
|
8,
|
|
E,
|
|
),
|
|
],
|
|
64,
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
]))
|
|
: (openBlock(),
|
|
createElementBlock(`div`, ue, [
|
|
(r[4] ||= createElementVNode(
|
|
`div`,
|
|
{
|
|
class: `notice-heading`,
|
|
},
|
|
[
|
|
createElementVNode(`h2`, null, `公告`),
|
|
createElementVNode(
|
|
`p`,
|
|
null,
|
|
`我们会在这里发布重要公告与服务信息,帮助您及时了解平台动态。`,
|
|
),
|
|
],
|
|
-1,
|
|
)),
|
|
createElementVNode(`div`, w, [
|
|
createVNode(
|
|
i,
|
|
{
|
|
modelValue: unref(F),
|
|
"onUpdate:modelValue": (r[0] ||= (e) =>
|
|
isRef(F) ? (F.value = e) : null),
|
|
placeholder: `搜索公告标题`,
|
|
"aria-label": `搜索公告标题`,
|
|
onKeyup: withKeys(W, [`enter`]),
|
|
},
|
|
null,
|
|
8,
|
|
[`modelValue`],
|
|
),
|
|
createVNode(
|
|
o,
|
|
{
|
|
modelValue: unref(R),
|
|
"onUpdate:modelValue": (r[1] ||= (e) =>
|
|
isRef(R) ? (R.value = e) : null),
|
|
options: [
|
|
{
|
|
id: null,
|
|
name: `全部分类`,
|
|
},
|
|
...unref(z),
|
|
],
|
|
"option-label": `name`,
|
|
"option-value": `id`,
|
|
"aria-label": `公告分类`,
|
|
onChange: W,
|
|
},
|
|
null,
|
|
8,
|
|
[`modelValue`, `options`],
|
|
),
|
|
createVNode(
|
|
o,
|
|
{
|
|
modelValue: unref(L),
|
|
"onUpdate:modelValue": (r[2] ||= (e) =>
|
|
isRef(L) ? (L.value = e) : null),
|
|
options: [
|
|
{
|
|
label: `最新优先`,
|
|
value: `desc`,
|
|
},
|
|
{
|
|
label: `最早优先`,
|
|
value: `asc`,
|
|
},
|
|
],
|
|
"option-label": `label`,
|
|
"option-value": `value`,
|
|
"aria-label": `公告排序`,
|
|
onChange: W,
|
|
},
|
|
null,
|
|
8,
|
|
[`modelValue`],
|
|
),
|
|
createVNode(h, {
|
|
label: `搜索`,
|
|
text: ``,
|
|
onClick: W,
|
|
}),
|
|
]),
|
|
unref(B)
|
|
? (openBlock(),
|
|
createBlock(
|
|
v,
|
|
{
|
|
key: 0,
|
|
severity: `warn`,
|
|
closable: !1,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
createTextVNode(toDisplayString(unref(B)) + ` `, 1),
|
|
createVNode(h, {
|
|
label: `重试分类`,
|
|
text: ``,
|
|
onClick: U,
|
|
}),
|
|
]),
|
|
_: 1,
|
|
},
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
unref(j) && !unref(k).length
|
|
? (openBlock(),
|
|
createElementBlock(`div`, de, [
|
|
(openBlock(),
|
|
createElementBlock(
|
|
Fragment,
|
|
null,
|
|
renderList(5, (e) =>
|
|
createVNode(y, {
|
|
key: e,
|
|
height: `48px`,
|
|
}),
|
|
),
|
|
64,
|
|
)),
|
|
]))
|
|
: unref(k).length
|
|
? (openBlock(),
|
|
createElementBlock(`div`, fe, [
|
|
(openBlock(!0),
|
|
createElementBlock(
|
|
Fragment,
|
|
null,
|
|
renderList(
|
|
unref(k),
|
|
(t) => (
|
|
openBlock(),
|
|
createBlock(
|
|
S,
|
|
{
|
|
key: t.id,
|
|
to: b.embedded
|
|
? `/resources?section=notices&id=${t.id}`
|
|
: `/notices/notice?id=${t.id}`,
|
|
class: `notice-item`,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
createElementVNode(
|
|
`span`,
|
|
T,
|
|
toDisplayString(t.title),
|
|
1,
|
|
),
|
|
createElementVNode(
|
|
`span`,
|
|
pe,
|
|
toDisplayString(
|
|
(`formatTime` in n
|
|
? n.formatTime
|
|
: unref(dict_r))(t.create_time),
|
|
),
|
|
1,
|
|
),
|
|
]),
|
|
_: 2,
|
|
},
|
|
1032,
|
|
[`to`],
|
|
)
|
|
),
|
|
),
|
|
128,
|
|
)),
|
|
]))
|
|
: unref(M)
|
|
? (openBlock(),
|
|
createBlock(
|
|
v,
|
|
{
|
|
key: 3,
|
|
severity: `error`,
|
|
closable: !1,
|
|
},
|
|
{
|
|
default: withCtx(() => [
|
|
createTextVNode(
|
|
toDisplayString(unref(M)) + ` `,
|
|
1,
|
|
),
|
|
createVNode(h, {
|
|
label: `重试`,
|
|
text: ``,
|
|
onClick: Z,
|
|
}),
|
|
]),
|
|
_: 1,
|
|
},
|
|
))
|
|
: (openBlock(),
|
|
createBlock(C, {
|
|
key: 4,
|
|
icon: `pi pi-megaphone`,
|
|
title: `暂无公告`,
|
|
description: `平台公告与通知会显示在这里`,
|
|
})),
|
|
unref(A) > 0
|
|
? (openBlock(),
|
|
createBlock(
|
|
D,
|
|
{
|
|
key: 5,
|
|
rows: unref(P),
|
|
totalRecords: unref(A),
|
|
first: (unref(N) - 1) * unref(P),
|
|
rowsPerPageOptions: [10, 20, 50],
|
|
onPage: _e,
|
|
},
|
|
null,
|
|
8,
|
|
[`rows`, `totalRecords`, `first`],
|
|
))
|
|
: createCommentVNode(``, !0),
|
|
]));
|
|
}
|
|
);
|
|
},
|
|
}),
|
|
[[`__scopeId`, `data-v-4ba0157b`]],
|
|
);
|
|
export {};
|
|
export default D;
|
|
</script>
|