- 新增api目录下多个接口路径代理处理文件,支持动态拼接目标URL - 根据环境变量选择不同的后端服务地址(如dev和生产环境) - 统一添加TenantId和Authorization请求头传递租户及身份信息 - 实现请求参数及搜索参数的完整转发 - 引入better-sqlite3及node内建模块支持服务端功能 - 新增专家详情页面,实现文章、成果及预约咨询功能展示 - 页面实现加载骨架屏、标签页切换及空状态提示优化体验
462 lines
23 KiB
JavaScript
462 lines
23 KiB
JavaScript
import { a as _export_sfc, c as useHead, n as navigateTo } from './server.mjs';
|
|
import { defineComponent, ref, reactive, resolveComponent, mergeProps, unref, withCtx, createTextVNode, createVNode, toDisplayString, createBlock, openBlock, Fragment, renderList, createCommentVNode, useSSRContext } from 'vue';
|
|
import { ssrRenderAttrs, ssrInterpolate, ssrRenderComponent, ssrRenderList, ssrRenderClass, ssrRenderStyle } from 'vue/server-renderer';
|
|
import { ReloadOutlined, RightOutlined } from '@ant-design/icons-vue';
|
|
import '../nitro/nitro.mjs';
|
|
import 'node:http';
|
|
import 'node:https';
|
|
import 'node:events';
|
|
import 'node:buffer';
|
|
import 'node:fs';
|
|
import 'node:path';
|
|
import 'node:crypto';
|
|
import 'node:url';
|
|
import 'better-sqlite3';
|
|
import 'vue-router';
|
|
import 'ant-design-vue';
|
|
import '@babel/runtime/helpers/esm/extends';
|
|
import 'stylis';
|
|
import 'dayjs';
|
|
import '../routes/renderer.mjs';
|
|
import 'vue-bundle-renderer/runtime';
|
|
import 'unhead/server';
|
|
import 'devalue';
|
|
import 'unhead/plugins';
|
|
import 'unhead/utils';
|
|
|
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
__name: "index",
|
|
__ssrInlineRender: true,
|
|
setup(__props) {
|
|
useHead({ title: "管理后台首页" });
|
|
const adminName = ref("管理员");
|
|
const loadingStats = ref(false);
|
|
const coreStats = reactive([
|
|
{ icon: "📝", label: "文章总数", value: 0, desc: "全部文章", color: "blue" },
|
|
{ icon: "👥", label: "用户总数", value: 0, desc: "注册用户", color: "green" },
|
|
{ icon: "🎓", label: "专家总数", value: 0, desc: "认证专家", color: "purple" },
|
|
{ icon: "💼", label: "会员总数", value: 0, desc: "企业/个人会员", color: "orange" }
|
|
]);
|
|
const todoItems = reactive([
|
|
{ label: "待审核专家", value: 0, to: "/admin/experts/review", tagColor: "orange", dotColor: "dot-orange", urgent: false },
|
|
{ label: "待审核会员", value: 0, to: "/admin/members/review", tagColor: "cyan", dotColor: "dot-cyan", urgent: false },
|
|
{ label: "待处理建言", value: 0, to: "/admin/suggestions", tagColor: "blue", dotColor: "dot-blue", urgent: false },
|
|
{ label: "待审核文章", value: 0, to: "/admin/articles", tagColor: "red", dotColor: "dot-red", urgent: false }
|
|
]);
|
|
const quickLinks = [
|
|
{ to: "/admin/articles", icon: "📝", label: "文章管理", bg: "#fff7ed" },
|
|
{ to: "/admin/categories", icon: "🗂️", label: "栏目管理", bg: "#eff6ff" },
|
|
{ to: "/admin/experts", icon: "🎓", label: "专家管理", bg: "#faf5ff" },
|
|
{ to: "/admin/members", icon: "💼", label: "会员管理", bg: "#f0fdf4" },
|
|
{ to: "/admin/suggestions", icon: "💬", label: "建言管理", bg: "#fdf4ff" },
|
|
{ to: "/admin/users", icon: "👥", label: "用户管理", bg: "#f0f9ff" },
|
|
{ to: "/admin/announcements", icon: "📢", label: "公告管理", bg: "#fff1f2" },
|
|
{ to: "/admin/settings", icon: "⚙️", label: "系统设置", bg: "#f9fafb" }
|
|
];
|
|
async function loadStats() {
|
|
loadingStats.value = true;
|
|
try {
|
|
todoItems[0].value = 0;
|
|
todoItems[1].value = 0;
|
|
todoItems[2].value = 0;
|
|
todoItems[3].value = 0;
|
|
} catch {
|
|
} finally {
|
|
loadingStats.value = false;
|
|
}
|
|
}
|
|
return (_ctx, _push, _parent, _attrs) => {
|
|
const _component_a_space = resolveComponent("a-space");
|
|
const _component_a_tag = resolveComponent("a-tag");
|
|
const _component_a_button = resolveComponent("a-button");
|
|
const _component_a_row = resolveComponent("a-row");
|
|
const _component_a_col = resolveComponent("a-col");
|
|
const _component_a_skeleton_input = resolveComponent("a-skeleton-input");
|
|
_push(`<div${ssrRenderAttrs(mergeProps({ class: "admin-home" }, _attrs))} data-v-26805697><div class="welcome-banner" data-v-26805697><div class="welcome-left" data-v-26805697><h2 class="welcome-title" data-v-26805697>🎛️ 决策咨询网管理后台</h2><p class="welcome-sub" data-v-26805697>欢迎回来,${ssrInterpolate(unref(adminName))},今日数据已更新</p></div><div class="welcome-right" data-v-26805697>`);
|
|
_push(ssrRenderComponent(_component_a_space, null, {
|
|
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
|
if (_push2) {
|
|
_push2(ssrRenderComponent(_component_a_tag, {
|
|
color: "red",
|
|
style: { "font-size": "13px", "padding": "4px 12px" }
|
|
}, {
|
|
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(`超级管理员`);
|
|
} else {
|
|
return [
|
|
createTextVNode("超级管理员")
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent2, _scopeId));
|
|
_push2(ssrRenderComponent(_component_a_button, {
|
|
size: "small",
|
|
onClick: loadStats,
|
|
loading: unref(loadingStats)
|
|
}, {
|
|
icon: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(ssrRenderComponent(unref(ReloadOutlined), null, null, _parent3, _scopeId2));
|
|
} else {
|
|
return [
|
|
createVNode(unref(ReloadOutlined))
|
|
];
|
|
}
|
|
}),
|
|
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(` 刷新数据 `);
|
|
} else {
|
|
return [
|
|
createTextVNode(" 刷新数据 ")
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent2, _scopeId));
|
|
} else {
|
|
return [
|
|
createVNode(_component_a_tag, {
|
|
color: "red",
|
|
style: { "font-size": "13px", "padding": "4px 12px" }
|
|
}, {
|
|
default: withCtx(() => [
|
|
createTextVNode("超级管理员")
|
|
]),
|
|
_: 1
|
|
}),
|
|
createVNode(_component_a_button, {
|
|
size: "small",
|
|
onClick: loadStats,
|
|
loading: unref(loadingStats)
|
|
}, {
|
|
icon: withCtx(() => [
|
|
createVNode(unref(ReloadOutlined))
|
|
]),
|
|
default: withCtx(() => [
|
|
createTextVNode(" 刷新数据 ")
|
|
]),
|
|
_: 1
|
|
}, 8, ["loading"])
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent));
|
|
_push(`</div></div>`);
|
|
_push(ssrRenderComponent(_component_a_row, { gutter: [16, 16] }, {
|
|
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
|
if (_push2) {
|
|
_push2(`<!--[-->`);
|
|
ssrRenderList(unref(coreStats), (stat) => {
|
|
_push2(ssrRenderComponent(_component_a_col, {
|
|
xs: 12,
|
|
sm: 12,
|
|
md: 6,
|
|
key: stat.label
|
|
}, {
|
|
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(`<div class="${ssrRenderClass([stat.color, "stat-block"])}" data-v-26805697${_scopeId2}><div class="stat-block-header" data-v-26805697${_scopeId2}><span class="stat-block-icon" data-v-26805697${_scopeId2}>${ssrInterpolate(stat.icon)}</span><span class="stat-block-label" data-v-26805697${_scopeId2}>${ssrInterpolate(stat.label)}</span></div><div class="stat-block-value" data-v-26805697${_scopeId2}>`);
|
|
if (unref(loadingStats)) {
|
|
_push3(ssrRenderComponent(_component_a_skeleton_input, {
|
|
active: true,
|
|
size: "small",
|
|
style: { "width": "60px" }
|
|
}, null, _parent3, _scopeId2));
|
|
} else {
|
|
_push3(`<!--[-->${ssrInterpolate(stat.value)}<!--]-->`);
|
|
}
|
|
_push3(`</div><div class="stat-block-desc" data-v-26805697${_scopeId2}>${ssrInterpolate(stat.desc)}</div></div>`);
|
|
} else {
|
|
return [
|
|
createVNode("div", {
|
|
class: ["stat-block", stat.color]
|
|
}, [
|
|
createVNode("div", { class: "stat-block-header" }, [
|
|
createVNode("span", { class: "stat-block-icon" }, toDisplayString(stat.icon), 1),
|
|
createVNode("span", { class: "stat-block-label" }, toDisplayString(stat.label), 1)
|
|
]),
|
|
createVNode("div", { class: "stat-block-value" }, [
|
|
unref(loadingStats) ? (openBlock(), createBlock(_component_a_skeleton_input, {
|
|
key: 0,
|
|
active: true,
|
|
size: "small",
|
|
style: { "width": "60px" }
|
|
})) : (openBlock(), createBlock(Fragment, { key: 1 }, [
|
|
createTextVNode(toDisplayString(stat.value), 1)
|
|
], 64))
|
|
]),
|
|
createVNode("div", { class: "stat-block-desc" }, toDisplayString(stat.desc), 1)
|
|
], 2)
|
|
];
|
|
}
|
|
}),
|
|
_: 2
|
|
}, _parent2, _scopeId));
|
|
});
|
|
_push2(`<!--]-->`);
|
|
} else {
|
|
return [
|
|
(openBlock(true), createBlock(Fragment, null, renderList(unref(coreStats), (stat) => {
|
|
return openBlock(), createBlock(_component_a_col, {
|
|
xs: 12,
|
|
sm: 12,
|
|
md: 6,
|
|
key: stat.label
|
|
}, {
|
|
default: withCtx(() => [
|
|
createVNode("div", {
|
|
class: ["stat-block", stat.color]
|
|
}, [
|
|
createVNode("div", { class: "stat-block-header" }, [
|
|
createVNode("span", { class: "stat-block-icon" }, toDisplayString(stat.icon), 1),
|
|
createVNode("span", { class: "stat-block-label" }, toDisplayString(stat.label), 1)
|
|
]),
|
|
createVNode("div", { class: "stat-block-value" }, [
|
|
unref(loadingStats) ? (openBlock(), createBlock(_component_a_skeleton_input, {
|
|
key: 0,
|
|
active: true,
|
|
size: "small",
|
|
style: { "width": "60px" }
|
|
})) : (openBlock(), createBlock(Fragment, { key: 1 }, [
|
|
createTextVNode(toDisplayString(stat.value), 1)
|
|
], 64))
|
|
]),
|
|
createVNode("div", { class: "stat-block-desc" }, toDisplayString(stat.desc), 1)
|
|
], 2)
|
|
]),
|
|
_: 2
|
|
}, 1024);
|
|
}), 128))
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent));
|
|
_push(ssrRenderComponent(_component_a_row, { gutter: [16, 16] }, {
|
|
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
|
if (_push2) {
|
|
_push2(ssrRenderComponent(_component_a_col, {
|
|
xs: 24,
|
|
md: 12
|
|
}, {
|
|
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(`<div class="panel" data-v-26805697${_scopeId2}><div class="panel-header" data-v-26805697${_scopeId2}><span class="panel-title" data-v-26805697${_scopeId2}>🔔 待处理事项</span></div><div class="todo-list" data-v-26805697${_scopeId2}><!--[-->`);
|
|
ssrRenderList(unref(todoItems), (todo) => {
|
|
_push3(`<div class="${ssrRenderClass([{ "todo-item-urgent": todo.urgent }, "todo-item"])}" data-v-26805697${_scopeId2}><div class="${ssrRenderClass([todo.dotColor, "todo-dot"])}" data-v-26805697${_scopeId2}></div><div class="todo-content" data-v-26805697${_scopeId2}><span class="todo-label" data-v-26805697${_scopeId2}>${ssrInterpolate(todo.label)}</span>`);
|
|
_push3(ssrRenderComponent(_component_a_tag, {
|
|
color: todo.tagColor
|
|
}, {
|
|
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
|
if (_push4) {
|
|
if (unref(loadingStats)) {
|
|
_push4(`<!--[-->...<!--]-->`);
|
|
} else {
|
|
_push4(`<!--[-->${ssrInterpolate(todo.value)}<!--]-->`);
|
|
}
|
|
} else {
|
|
return [
|
|
unref(loadingStats) ? (openBlock(), createBlock(Fragment, { key: 0 }, [
|
|
createTextVNode("...")
|
|
], 64)) : (openBlock(), createBlock(Fragment, { key: 1 }, [
|
|
createTextVNode(toDisplayString(todo.value), 1)
|
|
], 64))
|
|
];
|
|
}
|
|
}),
|
|
_: 2
|
|
}, _parent3, _scopeId2));
|
|
_push3(`</div>`);
|
|
_push3(ssrRenderComponent(unref(RightOutlined), { class: "todo-arrow" }, null, _parent3, _scopeId2));
|
|
_push3(`</div>`);
|
|
});
|
|
_push3(`<!--]-->`);
|
|
if (!unref(loadingStats) && unref(todoItems).every((t) => t.value === 0)) {
|
|
_push3(`<div class="todo-empty" data-v-26805697${_scopeId2}> 🎉 暂无待处理事项,一切正常! </div>`);
|
|
} else {
|
|
_push3(`<!---->`);
|
|
}
|
|
_push3(`</div></div>`);
|
|
} else {
|
|
return [
|
|
createVNode("div", { class: "panel" }, [
|
|
createVNode("div", { class: "panel-header" }, [
|
|
createVNode("span", { class: "panel-title" }, "🔔 待处理事项")
|
|
]),
|
|
createVNode("div", { class: "todo-list" }, [
|
|
(openBlock(true), createBlock(Fragment, null, renderList(unref(todoItems), (todo) => {
|
|
return openBlock(), createBlock("div", {
|
|
key: todo.label,
|
|
class: ["todo-item", { "todo-item-urgent": todo.urgent }],
|
|
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))(todo.to)
|
|
}, [
|
|
createVNode("div", {
|
|
class: ["todo-dot", todo.dotColor]
|
|
}, null, 2),
|
|
createVNode("div", { class: "todo-content" }, [
|
|
createVNode("span", { class: "todo-label" }, toDisplayString(todo.label), 1),
|
|
createVNode(_component_a_tag, {
|
|
color: todo.tagColor
|
|
}, {
|
|
default: withCtx(() => [
|
|
unref(loadingStats) ? (openBlock(), createBlock(Fragment, { key: 0 }, [
|
|
createTextVNode("...")
|
|
], 64)) : (openBlock(), createBlock(Fragment, { key: 1 }, [
|
|
createTextVNode(toDisplayString(todo.value), 1)
|
|
], 64))
|
|
]),
|
|
_: 2
|
|
}, 1032, ["color"])
|
|
]),
|
|
createVNode(unref(RightOutlined), { class: "todo-arrow" })
|
|
], 10, ["onClick"]);
|
|
}), 128)),
|
|
!unref(loadingStats) && unref(todoItems).every((t) => t.value === 0) ? (openBlock(), createBlock("div", {
|
|
key: 0,
|
|
class: "todo-empty"
|
|
}, " 🎉 暂无待处理事项,一切正常! ")) : createCommentVNode("", true)
|
|
])
|
|
])
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent2, _scopeId));
|
|
_push2(ssrRenderComponent(_component_a_col, {
|
|
xs: 24,
|
|
md: 12
|
|
}, {
|
|
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
|
if (_push3) {
|
|
_push3(`<div class="panel" data-v-26805697${_scopeId2}><div class="panel-header" data-v-26805697${_scopeId2}><span class="panel-title" data-v-26805697${_scopeId2}>⚡ 快速入口</span></div><div class="quick-grid" data-v-26805697${_scopeId2}><!--[-->`);
|
|
ssrRenderList(quickLinks, (item) => {
|
|
_push3(`<div class="quick-card" data-v-26805697${_scopeId2}><div class="quick-icon" style="${ssrRenderStyle({ background: item.bg })}" data-v-26805697${_scopeId2}>${ssrInterpolate(item.icon)}</div><div class="quick-label" data-v-26805697${_scopeId2}>${ssrInterpolate(item.label)}</div></div>`);
|
|
});
|
|
_push3(`<!--]--></div></div>`);
|
|
} else {
|
|
return [
|
|
createVNode("div", { class: "panel" }, [
|
|
createVNode("div", { class: "panel-header" }, [
|
|
createVNode("span", { class: "panel-title" }, "⚡ 快速入口")
|
|
]),
|
|
createVNode("div", { class: "quick-grid" }, [
|
|
(openBlock(), createBlock(Fragment, null, renderList(quickLinks, (item) => {
|
|
return createVNode("div", {
|
|
key: item.to,
|
|
class: "quick-card",
|
|
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))(item.to)
|
|
}, [
|
|
createVNode("div", {
|
|
class: "quick-icon",
|
|
style: { background: item.bg }
|
|
}, toDisplayString(item.icon), 5),
|
|
createVNode("div", { class: "quick-label" }, toDisplayString(item.label), 1)
|
|
], 8, ["onClick"]);
|
|
}), 64))
|
|
])
|
|
])
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent2, _scopeId));
|
|
} else {
|
|
return [
|
|
createVNode(_component_a_col, {
|
|
xs: 24,
|
|
md: 12
|
|
}, {
|
|
default: withCtx(() => [
|
|
createVNode("div", { class: "panel" }, [
|
|
createVNode("div", { class: "panel-header" }, [
|
|
createVNode("span", { class: "panel-title" }, "🔔 待处理事项")
|
|
]),
|
|
createVNode("div", { class: "todo-list" }, [
|
|
(openBlock(true), createBlock(Fragment, null, renderList(unref(todoItems), (todo) => {
|
|
return openBlock(), createBlock("div", {
|
|
key: todo.label,
|
|
class: ["todo-item", { "todo-item-urgent": todo.urgent }],
|
|
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))(todo.to)
|
|
}, [
|
|
createVNode("div", {
|
|
class: ["todo-dot", todo.dotColor]
|
|
}, null, 2),
|
|
createVNode("div", { class: "todo-content" }, [
|
|
createVNode("span", { class: "todo-label" }, toDisplayString(todo.label), 1),
|
|
createVNode(_component_a_tag, {
|
|
color: todo.tagColor
|
|
}, {
|
|
default: withCtx(() => [
|
|
unref(loadingStats) ? (openBlock(), createBlock(Fragment, { key: 0 }, [
|
|
createTextVNode("...")
|
|
], 64)) : (openBlock(), createBlock(Fragment, { key: 1 }, [
|
|
createTextVNode(toDisplayString(todo.value), 1)
|
|
], 64))
|
|
]),
|
|
_: 2
|
|
}, 1032, ["color"])
|
|
]),
|
|
createVNode(unref(RightOutlined), { class: "todo-arrow" })
|
|
], 10, ["onClick"]);
|
|
}), 128)),
|
|
!unref(loadingStats) && unref(todoItems).every((t) => t.value === 0) ? (openBlock(), createBlock("div", {
|
|
key: 0,
|
|
class: "todo-empty"
|
|
}, " 🎉 暂无待处理事项,一切正常! ")) : createCommentVNode("", true)
|
|
])
|
|
])
|
|
]),
|
|
_: 1
|
|
}),
|
|
createVNode(_component_a_col, {
|
|
xs: 24,
|
|
md: 12
|
|
}, {
|
|
default: withCtx(() => [
|
|
createVNode("div", { class: "panel" }, [
|
|
createVNode("div", { class: "panel-header" }, [
|
|
createVNode("span", { class: "panel-title" }, "⚡ 快速入口")
|
|
]),
|
|
createVNode("div", { class: "quick-grid" }, [
|
|
(openBlock(), createBlock(Fragment, null, renderList(quickLinks, (item) => {
|
|
return createVNode("div", {
|
|
key: item.to,
|
|
class: "quick-card",
|
|
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))(item.to)
|
|
}, [
|
|
createVNode("div", {
|
|
class: "quick-icon",
|
|
style: { background: item.bg }
|
|
}, toDisplayString(item.icon), 5),
|
|
createVNode("div", { class: "quick-label" }, toDisplayString(item.label), 1)
|
|
], 8, ["onClick"]);
|
|
}), 64))
|
|
])
|
|
])
|
|
]),
|
|
_: 1
|
|
})
|
|
];
|
|
}
|
|
}),
|
|
_: 1
|
|
}, _parent));
|
|
_push(`</div>`);
|
|
};
|
|
}
|
|
});
|
|
const _sfc_setup = _sfc_main.setup;
|
|
_sfc_main.setup = (props, ctx) => {
|
|
const ssrContext = useSSRContext();
|
|
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/admin/index.vue");
|
|
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
|
|
};
|
|
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-26805697"]]);
|
|
|
|
export { index as default };
|
|
//# sourceMappingURL=index-DhQFY9Jt.mjs.map
|