- 新增api目录下多个接口路径代理处理文件,支持动态拼接目标URL - 根据环境变量选择不同的后端服务地址(如dev和生产环境) - 统一添加TenantId和Authorization请求头传递租户及身份信息 - 实现请求参数及搜索参数的完整转发 - 引入better-sqlite3及node内建模块支持服务端功能 - 新增专家详情页面,实现文章、成果及预约咨询功能展示 - 页面实现加载骨架屏、标签页切换及空状态提示优化体验
3589 lines
164 KiB
JavaScript
3589 lines
164 KiB
JavaScript
import { a as _export_sfc, c as useHead, n as navigateTo } from './server.mjs';
|
||
import { defineComponent, ref, reactive, computed, watch, resolveComponent, mergeProps, withCtx, unref, createTextVNode, createVNode, toDisplayString, createBlock, openBlock, Fragment, renderList, isRef, createCommentVNode, withDirectives, vShow, nextTick, useSSRContext } from 'vue';
|
||
import { ssrRenderAttrs, ssrRenderComponent, ssrRenderList, ssrRenderClass, ssrInterpolate, ssrRenderAttr, ssrRenderStyle } from 'vue/server-renderer';
|
||
import { PlusOutlined, ReloadOutlined, LinkOutlined, PictureOutlined, UnorderedListOutlined, OrderedListOutlined, MinusOutlined, FullscreenOutlined, FullscreenExitOutlined } from '@ant-design/icons-vue';
|
||
import { message } from 'ant-design-vue';
|
||
import { l as listAppArticle, u as updateAppArticle, r as removeAppArticle, a as addAppArticle } from './index-DLTWNMRy.mjs';
|
||
import { u as uploadFile } from './index-SD8M3klL.mjs';
|
||
import { marked } from 'marked';
|
||
import hljs from 'highlight.js';
|
||
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 '@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';
|
||
import './request-BIxQh2im.mjs';
|
||
|
||
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
||
__name: "MarkdownEditor",
|
||
__ssrInlineRender: true,
|
||
props: {
|
||
modelValue: {},
|
||
placeholder: { default: "请输入 Markdown 内容..." },
|
||
showPreview: { type: Boolean, default: true },
|
||
minHeight: { default: "300px" }
|
||
},
|
||
emits: ["update:modelValue"],
|
||
setup(__props, { expose: __expose, emit: __emit }) {
|
||
const props = __props;
|
||
const emit = __emit;
|
||
marked.setOptions({
|
||
highlight: function(code, lang) {
|
||
if (lang && hljs.getLanguage(lang)) {
|
||
return hljs.highlight(code, { language: lang }).value;
|
||
}
|
||
return hljs.highlightAuto(code).value;
|
||
},
|
||
breaks: true,
|
||
gfm: true
|
||
});
|
||
const textareaRef = ref(null);
|
||
const uploadRef = ref(null);
|
||
const localValue = ref(props.modelValue);
|
||
const isFullscreen = ref(false);
|
||
const showLinkModal = ref(false);
|
||
const linkForm = reactive({
|
||
text: "",
|
||
url: ""
|
||
});
|
||
watch(() => props.modelValue, (newVal) => {
|
||
if (newVal !== localValue.value) {
|
||
localValue.value = newVal;
|
||
}
|
||
});
|
||
const renderedHtml = computed(() => {
|
||
if (!localValue.value) return '<p class="placeholder-hint">预览区域</p>';
|
||
try {
|
||
return marked.parse(localValue.value);
|
||
} catch (e) {
|
||
return '<p class="error-hint">渲染出错</p>';
|
||
}
|
||
});
|
||
const wordCount = computed(() => {
|
||
const text = localValue.value.trim();
|
||
if (!text) return 0;
|
||
return text.split(/\s+/).filter(Boolean).length;
|
||
});
|
||
const charCount = computed(() => localValue.value.length);
|
||
function insertAtCursor(text) {
|
||
const textarea = textareaRef.value;
|
||
if (!textarea) return;
|
||
const start = textarea.selectionStart;
|
||
const end = textarea.selectionEnd;
|
||
const before = localValue.value.substring(0, start);
|
||
const after = localValue.value.substring(end);
|
||
localValue.value = before + text + after;
|
||
emit("update:modelValue", localValue.value);
|
||
nextTick(() => {
|
||
textarea.focus();
|
||
textarea.selectionStart = textarea.selectionEnd = start + text.length;
|
||
});
|
||
}
|
||
function insertWrap(before, after) {
|
||
const textarea = textareaRef.value;
|
||
if (!textarea) return;
|
||
const start = textarea.selectionStart;
|
||
const end = textarea.selectionEnd;
|
||
const selectedText = localValue.value.substring(start, end) || "文本";
|
||
const text = before + selectedText + after;
|
||
localValue.value = localValue.value.substring(0, start) + text + localValue.value.substring(end);
|
||
emit("update:modelValue", localValue.value);
|
||
nextTick(() => {
|
||
textarea.focus();
|
||
textarea.selectionStart = start + before.length;
|
||
textarea.selectionEnd = start + before.length + selectedText.length;
|
||
});
|
||
}
|
||
function insertCodeBlock() {
|
||
const textarea = textareaRef.value;
|
||
if (!textarea) return;
|
||
const start = textarea.selectionStart;
|
||
const end = textarea.selectionEnd;
|
||
const selectedText = localValue.value.substring(start, end) || "代码";
|
||
const text = "\n```javascript\n" + selectedText + "\n```\n";
|
||
localValue.value = localValue.value.substring(0, start) + text + localValue.value.substring(end);
|
||
emit("update:modelValue", localValue.value);
|
||
nextTick(() => {
|
||
textarea.focus();
|
||
textarea.selectionStart = start + 14;
|
||
textarea.selectionEnd = start + 14 + selectedText.length;
|
||
});
|
||
}
|
||
function insertLink() {
|
||
const textarea = textareaRef.value;
|
||
if (textarea) {
|
||
const selectedText = localValue.value.substring(textarea.selectionStart, textarea.selectionEnd);
|
||
linkForm.text = selectedText || "";
|
||
}
|
||
showLinkModal.value = true;
|
||
}
|
||
function insertLinkConfirm() {
|
||
if (!linkForm.text.trim()) {
|
||
message.warning("请输入链接文本");
|
||
return;
|
||
}
|
||
if (!linkForm.url.trim()) {
|
||
message.warning("请输入链接地址");
|
||
return;
|
||
}
|
||
insertAtCursor(`[${linkForm.text}](${linkForm.url})`);
|
||
showLinkModal.value = false;
|
||
linkForm.text = "";
|
||
linkForm.url = "";
|
||
}
|
||
function handleImageUpload() {
|
||
const input = (void 0).createElement("input");
|
||
input.type = "file";
|
||
input.accept = "image/*";
|
||
input.onchange = async (e) => {
|
||
const file = e.target.files?.[0];
|
||
if (file) {
|
||
await uploadAndInsertImage(file);
|
||
}
|
||
};
|
||
input.click();
|
||
}
|
||
function beforeImageUpload(file) {
|
||
if (!file.type.startsWith("image/")) {
|
||
message.error("只能上传图片文件");
|
||
return false;
|
||
}
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
message.error("图片大小不能超过 5MB");
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
async function uploadAndInsertImage(file) {
|
||
try {
|
||
message.loading({ content: "上传图片中...", key: "upload" });
|
||
const record = await uploadFile(file);
|
||
const url = (record?.url || record?.downloadUrl || "").trim();
|
||
if (!url) throw new Error("上传成功但未返回图片地址");
|
||
insertAtCursor(``);
|
||
message.success({ content: "图片上传成功", key: "upload" });
|
||
} catch (e) {
|
||
message.error({ content: e?.message || "图片上传失败", key: "upload" });
|
||
}
|
||
}
|
||
async function handleCoverUpload(option) {
|
||
await uploadAndInsertImage(option.file);
|
||
option.onSuccess?.();
|
||
}
|
||
function toggleFullscreen() {
|
||
isFullscreen.value = !isFullscreen.value;
|
||
}
|
||
__expose({
|
||
focus: () => textareaRef.value?.focus(),
|
||
insertText: insertAtCursor
|
||
});
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
const _component_a_space = resolveComponent("a-space");
|
||
const _component_a_tooltip = resolveComponent("a-tooltip");
|
||
const _component_a_button = resolveComponent("a-button");
|
||
const _component_a_divider = resolveComponent("a-divider");
|
||
const _component_a_upload = resolveComponent("a-upload");
|
||
const _component_a_modal = resolveComponent("a-modal");
|
||
const _component_a_form = resolveComponent("a-form");
|
||
const _component_a_form_item = resolveComponent("a-form-item");
|
||
const _component_a_input = resolveComponent("a-input");
|
||
const _cssVars = { style: {
|
||
":--edb1d3d0": __props.minHeight
|
||
} };
|
||
_push(`<div${ssrRenderAttrs(mergeProps({
|
||
class: ["markdown-editor-wrapper", { "fullscreen": unref(isFullscreen) }]
|
||
}, _attrs, _cssVars))} data-v-32212c95><div class="editor-toolbar" data-v-32212c95><div class="toolbar-left" data-v-32212c95>`);
|
||
_push(ssrRenderComponent(_component_a_space, null, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "标题" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("# ")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon" data-v-32212c95${_scopeId3}>H</span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon" }, "H")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("# ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "H")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_divider, { type: "vertical" }, null, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "加粗" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("**", "**")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon bold" data-v-32212c95${_scopeId3}>B</span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon bold" }, "B")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("**", "**")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon bold" }, "B")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "斜体" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("*", "*")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon italic" data-v-32212c95${_scopeId3}>I</span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon italic" }, "I")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("*", "*")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon italic" }, "I")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "删除线" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("~~", "~~")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon" data-v-32212c95${_scopeId3}>S</span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon" }, "S")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("~~", "~~")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "S")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_divider, { type: "vertical" }, null, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "引用" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("> ")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon" data-v-32212c95${_scopeId3}>></span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon" }, ">")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("> ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, ">")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "代码块" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertCodeBlock
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon" data-v-32212c95${_scopeId3}></></span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon" }, "</>")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertCodeBlock
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "</>")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "行内代码" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("`", "`")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<span class="toolbar-icon" data-v-32212c95${_scopeId3}>\`</span>`);
|
||
} else {
|
||
return [
|
||
createVNode("span", { class: "toolbar-icon" }, "`")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("`", "`")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "`")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_divider, { type: "vertical" }, null, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "链接" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertLink
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(unref(LinkOutlined), null, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(unref(LinkOutlined))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertLink
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(LinkOutlined))
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "图片" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: handleImageUpload
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(unref(PictureOutlined), null, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(unref(PictureOutlined))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: handleImageUpload
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(PictureOutlined))
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_divider, { type: "vertical" }, null, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "有序列表" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("1. ")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(unref(UnorderedListOutlined), null, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(unref(UnorderedListOutlined))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("1. ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(UnorderedListOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "无序列表" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("- ")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(unref(OrderedListOutlined), null, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(unref(OrderedListOutlined))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("- ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(OrderedListOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_divider, { type: "vertical" }, null, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_tooltip, { title: "水平线" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("\n---\n")
|
||
}, {
|
||
icon: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(unref(MinusOutlined), null, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(unref(MinusOutlined))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("\n---\n")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(MinusOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_tooltip, { title: "标题" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("# ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "H")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_divider, { type: "vertical" }),
|
||
createVNode(_component_a_tooltip, { title: "加粗" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("**", "**")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon bold" }, "B")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "斜体" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("*", "*")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon italic" }, "I")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "删除线" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("~~", "~~")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "S")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_divider, { type: "vertical" }),
|
||
createVNode(_component_a_tooltip, { title: "引用" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("> ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, ">")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "代码块" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertCodeBlock
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "</>")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "行内代码" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertWrap("`", "`")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode("span", { class: "toolbar-icon" }, "`")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_divider, { type: "vertical" }),
|
||
createVNode(_component_a_tooltip, { title: "链接" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: insertLink
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(LinkOutlined))
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "图片" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: handleImageUpload
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(PictureOutlined))
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_divider, { type: "vertical" }),
|
||
createVNode(_component_a_tooltip, { title: "有序列表" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("1. ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(UnorderedListOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_tooltip, { title: "无序列表" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("- ")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(OrderedListOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_divider, { type: "vertical" }),
|
||
createVNode(_component_a_tooltip, { title: "水平线" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => insertAtCursor("\n---\n")
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(MinusOutlined))
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`</div><div class="toolbar-right" data-v-32212c95>`);
|
||
_push(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: toggleFullscreen
|
||
}, {
|
||
icon: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
if (!unref(isFullscreen)) {
|
||
_push2(ssrRenderComponent(unref(FullscreenOutlined), null, null, _parent2, _scopeId));
|
||
} else {
|
||
_push2(ssrRenderComponent(unref(FullscreenExitOutlined), null, null, _parent2, _scopeId));
|
||
}
|
||
} else {
|
||
return [
|
||
!unref(isFullscreen) ? (openBlock(), createBlock(unref(FullscreenOutlined), { key: 0 })) : (openBlock(), createBlock(unref(FullscreenExitOutlined), { key: 1 }))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`</div></div><div class="editor-body" data-v-32212c95><div class="editor-pane" data-v-32212c95><textarea class="markdown-textarea"${ssrRenderAttr("placeholder", __props.placeholder)} style="${ssrRenderStyle({ height: unref(isFullscreen) ? "100%" : "auto" })}" data-v-32212c95>${ssrInterpolate(unref(localValue))}</textarea></div>`);
|
||
if (__props.showPreview) {
|
||
_push(`<div class="preview-pane" data-v-32212c95><div class="preview-label" data-v-32212c95>预览</div><div class="markdown-preview" data-v-32212c95>${unref(renderedHtml) ?? ""}</div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div>`);
|
||
_push(ssrRenderComponent(_component_a_upload, {
|
||
ref_key: "uploadRef",
|
||
ref: uploadRef,
|
||
accept: "image/*",
|
||
"show-upload-list": false,
|
||
"before-upload": beforeImageUpload,
|
||
"custom-request": handleCoverUpload,
|
||
style: { "display": "none" }
|
||
}, null, _parent));
|
||
_push(ssrRenderComponent(_component_a_modal, {
|
||
open: unref(showLinkModal),
|
||
"onUpdate:open": ($event) => isRef(showLinkModal) ? showLinkModal.value = $event : null,
|
||
title: "插入链接",
|
||
width: 400,
|
||
onOk: insertLinkConfirm
|
||
}, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(ssrRenderComponent(_component_a_form, {
|
||
model: unref(linkForm),
|
||
layout: "vertical"
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_form_item, {
|
||
label: "链接文本",
|
||
required: ""
|
||
}, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_input, {
|
||
value: unref(linkForm).text,
|
||
"onUpdate:value": ($event) => unref(linkForm).text = $event,
|
||
placeholder: "显示的文本"
|
||
}, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).text,
|
||
"onUpdate:value": ($event) => unref(linkForm).text = $event,
|
||
placeholder: "显示的文本"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, {
|
||
label: "链接地址",
|
||
required: ""
|
||
}, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_input, {
|
||
value: unref(linkForm).url,
|
||
"onUpdate:value": ($event) => unref(linkForm).url = $event,
|
||
placeholder: "https://..."
|
||
}, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).url,
|
||
"onUpdate:value": ($event) => unref(linkForm).url = $event,
|
||
placeholder: "https://..."
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, {
|
||
label: "链接文本",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).text,
|
||
"onUpdate:value": ($event) => unref(linkForm).text = $event,
|
||
placeholder: "显示的文本"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, {
|
||
label: "链接地址",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).url,
|
||
"onUpdate:value": ($event) => unref(linkForm).url = $event,
|
||
placeholder: "https://..."
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form, {
|
||
model: unref(linkForm),
|
||
layout: "vertical"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, {
|
||
label: "链接文本",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).text,
|
||
"onUpdate:value": ($event) => unref(linkForm).text = $event,
|
||
placeholder: "显示的文本"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, {
|
||
label: "链接地址",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(linkForm).url,
|
||
"onUpdate:value": ($event) => unref(linkForm).url = $event,
|
||
placeholder: "https://..."
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["model"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`<div class="editor-footer" data-v-32212c95><span class="word-count" data-v-32212c95>${ssrInterpolate(unref(wordCount))} 字</span><span class="char-count" data-v-32212c95>${ssrInterpolate(unref(charCount))} 字符</span></div></div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup$2 = _sfc_main$2.setup;
|
||
_sfc_main$2.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/admin/MarkdownEditor.vue");
|
||
return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
|
||
};
|
||
const MarkdownEditor = /* @__PURE__ */ Object.assign(_export_sfc(_sfc_main$2, [["__scopeId", "data-v-32212c95"]]), { __name: "AdminMarkdownEditor" });
|
||
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
||
__name: "MarkdownRenderer",
|
||
__ssrInlineRender: true,
|
||
props: {
|
||
content: {}
|
||
},
|
||
setup(__props) {
|
||
const props = __props;
|
||
marked.setOptions({
|
||
highlight: function(code, lang) {
|
||
if (lang && hljs.getLanguage(lang)) {
|
||
return hljs.highlight(code, { language: lang }).value;
|
||
}
|
||
return hljs.highlightAuto(code).value;
|
||
},
|
||
breaks: true,
|
||
gfm: true
|
||
});
|
||
const renderedHtml = computed(() => {
|
||
if (!props.content) return "";
|
||
try {
|
||
return marked.parse(props.content);
|
||
} catch (e) {
|
||
return "<p>渲染出错</p>";
|
||
}
|
||
});
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "markdown-renderer" }, _attrs))} data-v-1fb533b6>${unref(renderedHtml) ?? ""}</div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup$1 = _sfc_main$1.setup;
|
||
_sfc_main$1.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/admin/MarkdownRenderer.vue");
|
||
return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
|
||
};
|
||
const MarkdownRenderer = /* @__PURE__ */ Object.assign(_export_sfc(_sfc_main$1, [["__scopeId", "data-v-1fb533b6"]]), { __name: "AdminMarkdownRenderer" });
|
||
const ANNOUNCE_MODEL = "announcement";
|
||
const _sfc_main = /* @__PURE__ */ defineComponent({
|
||
__name: "articles",
|
||
__ssrInlineRender: true,
|
||
setup(__props) {
|
||
useHead({ title: "文章管理 - 平台管理" });
|
||
const loading = ref(false);
|
||
const imageUploading = ref(false);
|
||
const allArticles = ref([]);
|
||
const categoryOptions = ref([]);
|
||
const filterStatus = ref(void 0);
|
||
const filterCategoryId = ref(void 0);
|
||
const searchKeyword = ref("");
|
||
const pagination = reactive({
|
||
current: 1,
|
||
pageSize: 20,
|
||
showSizeChanger: true,
|
||
showQuickJumper: true
|
||
});
|
||
const statCards = reactive([
|
||
{ key: 0, icon: "✅", label: "已发布", value: 0, color: "green" },
|
||
{ key: 1, icon: "⏳", label: "待审核", value: 0, color: "orange" },
|
||
{ key: 2, icon: "❌", label: "已驳回", value: 0, color: "red" },
|
||
{ key: -1, icon: "📝", label: "全部文章", value: 0, color: "blue" }
|
||
]);
|
||
const columns = [
|
||
{ title: "文章信息", key: "info", width: 360 },
|
||
{ title: "状态", key: "status", width: 110 },
|
||
{ title: "数据", key: "metrics", width: 120 },
|
||
{ title: "推荐", key: "recommend", width: 80 },
|
||
{ title: "创建时间", key: "createTime", width: 120 },
|
||
{ title: "操作", key: "action", width: 170 }
|
||
];
|
||
const showFormModal = ref(false);
|
||
const saving = ref(false);
|
||
const editingArticle = ref(null);
|
||
const formData = reactive({
|
||
title: "",
|
||
author: "",
|
||
source: "",
|
||
overview: "",
|
||
content: "",
|
||
status: 0,
|
||
categoryId: void 0,
|
||
image: ""
|
||
});
|
||
const formRecommend = ref(false);
|
||
const editorMode = ref("edit");
|
||
const isMarkdown = computed(() => {
|
||
return formData.content && (/[#*`_\[\]()!>-]/.test(formData.content) || /^(#{1,6}\s|[-*]\s|\d+\.\s|>)/m.test(formData.content));
|
||
});
|
||
const isPreviewMarkdown = computed(() => {
|
||
if (!previewData.value?.content) return false;
|
||
return /[#*`_\[\]()!>-]/.test(previewData.value.content) || /^(#{1,6}\s|[-*]\s|\d+\.\s|>)/m.test(previewData.value.content);
|
||
});
|
||
const showPreviewModal = ref(false);
|
||
const previewData = ref(null);
|
||
const showImagePreview = ref(false);
|
||
const previewImageUrl = ref("");
|
||
const categorySelectOptions = computed(
|
||
() => categoryOptions.value.map((item) => ({
|
||
value: item.categoryId,
|
||
label: item.title || `分类 ${item.categoryId}`
|
||
}))
|
||
);
|
||
const standardArticles = computed(() => allArticles.value.filter(isStandardArticle));
|
||
const filteredArticles = computed(() => {
|
||
const keyword = searchKeyword.value.trim().toLowerCase();
|
||
return [...standardArticles.value].filter((item) => filterStatus.value === void 0 || item.status === filterStatus.value).filter((item) => filterCategoryId.value === void 0 || item.categoryId === filterCategoryId.value).filter((item) => {
|
||
if (!keyword) return true;
|
||
return [item.title, item.overview, item.author, item.source].some((value) => String(value || "").toLowerCase().includes(keyword));
|
||
}).sort((a, b) => {
|
||
const timeA = a.createTime || "";
|
||
const timeB = b.createTime || "";
|
||
if (timeA && timeB && timeA !== timeB) {
|
||
return timeB.localeCompare(timeA);
|
||
}
|
||
return (b.articleId || 0) - (a.articleId || 0);
|
||
});
|
||
});
|
||
const pagedArticles = computed(() => {
|
||
const start = (pagination.current - 1) * pagination.pageSize;
|
||
return filteredArticles.value.slice(start, start + pagination.pageSize);
|
||
});
|
||
const tablePagination = computed(() => ({
|
||
current: pagination.current,
|
||
pageSize: pagination.pageSize,
|
||
total: filteredArticles.value.length,
|
||
showSizeChanger: pagination.showSizeChanger,
|
||
showQuickJumper: pagination.showQuickJumper
|
||
}));
|
||
async function loadArticles() {
|
||
loading.value = true;
|
||
try {
|
||
const list = await listAppArticle();
|
||
allArticles.value = list || [];
|
||
ensurePaginationInRange();
|
||
updateStats();
|
||
} catch (e) {
|
||
message.error(e?.message || "加载文章列表失败");
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
function updateStats() {
|
||
const list = standardArticles.value;
|
||
statCards[0].value = list.filter((item) => item.status === 0).length;
|
||
statCards[1].value = list.filter((item) => item.status === 1).length;
|
||
statCards[2].value = list.filter((item) => item.status === 2).length;
|
||
statCards[3].value = list.length;
|
||
}
|
||
function ensurePaginationInRange() {
|
||
const total = filteredArticles.value.length;
|
||
const maxPage = Math.max(1, Math.ceil(total / pagination.pageSize));
|
||
if (pagination.current > maxPage) {
|
||
pagination.current = maxPage;
|
||
}
|
||
}
|
||
function isStandardArticle(item) {
|
||
return (item.model || "").trim() !== ANNOUNCE_MODEL;
|
||
}
|
||
function handleStatFilter(key) {
|
||
filterStatus.value = key === -1 ? void 0 : key;
|
||
pagination.current = 1;
|
||
}
|
||
function handleSearch() {
|
||
pagination.current = 1;
|
||
}
|
||
function handleTableChange(pag) {
|
||
pagination.current = pag.current;
|
||
pagination.pageSize = pag.pageSize;
|
||
ensurePaginationInRange();
|
||
}
|
||
function resetForm() {
|
||
Object.assign(formData, {
|
||
articleId: void 0,
|
||
title: "",
|
||
author: "",
|
||
source: "",
|
||
overview: "",
|
||
content: "",
|
||
status: 0,
|
||
categoryId: void 0,
|
||
image: ""
|
||
});
|
||
formRecommend.value = false;
|
||
}
|
||
function handleCreate() {
|
||
editingArticle.value = null;
|
||
resetForm();
|
||
showFormModal.value = true;
|
||
}
|
||
function handleEdit(record) {
|
||
editingArticle.value = record;
|
||
Object.assign(formData, {
|
||
articleId: record.articleId,
|
||
title: record.title || "",
|
||
author: record.author || "",
|
||
source: record.source || "",
|
||
overview: record.overview || "",
|
||
content: record.content || "",
|
||
status: record.status ?? 0,
|
||
categoryId: record.categoryId,
|
||
image: record.image || ""
|
||
});
|
||
formRecommend.value = !!record.recommend;
|
||
showFormModal.value = true;
|
||
}
|
||
function handleView(record) {
|
||
previewData.value = {
|
||
...record,
|
||
categoryName: resolveCategoryName(record)
|
||
};
|
||
showPreviewModal.value = true;
|
||
}
|
||
async function handleSave() {
|
||
if (!formData.title?.trim()) {
|
||
message.warning("请输入文章标题");
|
||
return;
|
||
}
|
||
if (!formData.content?.trim()) {
|
||
message.warning("请输入文章内容");
|
||
return;
|
||
}
|
||
saving.value = true;
|
||
try {
|
||
const data = {
|
||
...formData,
|
||
model: void 0,
|
||
categoryName: resolveCategoryNameById(formData.categoryId),
|
||
recommend: formRecommend.value ? 1 : 0
|
||
};
|
||
if (editingArticle.value?.articleId) {
|
||
await updateAppArticle(data);
|
||
message.success("文章已更新");
|
||
} else {
|
||
await addAppArticle(data);
|
||
message.success("文章已创建");
|
||
}
|
||
showFormModal.value = false;
|
||
await loadArticles();
|
||
} catch (e) {
|
||
message.error(e?.message || "保存失败");
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
}
|
||
async function handleDelete(record) {
|
||
try {
|
||
await removeAppArticle(record.articleId);
|
||
message.success("文章已删除");
|
||
await loadArticles();
|
||
} catch (e) {
|
||
message.error(e?.message || "删除失败");
|
||
}
|
||
}
|
||
async function handleToggleRecommend(record, val) {
|
||
try {
|
||
await updateAppArticle({ articleId: record.articleId, recommend: val ? 1 : 0 });
|
||
message.success(val ? "已加入推荐" : "已取消推荐");
|
||
await loadArticles();
|
||
} catch (e) {
|
||
message.error(e?.message || "操作失败");
|
||
}
|
||
}
|
||
function beforeImageUpload(file) {
|
||
if (!file.type.startsWith("image/")) {
|
||
message.error("只能上传图片文件");
|
||
return false;
|
||
}
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
message.error("图片大小不能超过 5MB");
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
async function handleCoverUpload(option) {
|
||
const rawFile = option.file;
|
||
if (!rawFile) return;
|
||
imageUploading.value = true;
|
||
try {
|
||
const record = await uploadFile(rawFile);
|
||
const url = (record?.url || record?.downloadUrl || "").trim();
|
||
if (!url) throw new Error("上传成功但未返回图片地址");
|
||
formData.image = url;
|
||
option.onSuccess?.(record, rawFile);
|
||
message.success("封面上传成功");
|
||
} catch (e) {
|
||
option.onError?.(e);
|
||
message.error(e instanceof Error ? e.message : "封面上传失败");
|
||
} finally {
|
||
imageUploading.value = false;
|
||
}
|
||
}
|
||
function handleRemoveCover() {
|
||
formData.image = "";
|
||
}
|
||
function handlePreviewImage(url) {
|
||
if (!url) return;
|
||
previewImageUrl.value = url;
|
||
showImagePreview.value = true;
|
||
}
|
||
function resolveCategoryName(record) {
|
||
return record.categoryName || resolveCategoryNameById(record.categoryId);
|
||
}
|
||
function resolveCategoryNameById(categoryId) {
|
||
if (!categoryId) return "";
|
||
return categoryOptions.value.find((item) => item.categoryId === categoryId)?.title || "";
|
||
}
|
||
function statusText(status) {
|
||
const map = {
|
||
0: "已发布",
|
||
1: "待审核",
|
||
2: "已驳回",
|
||
3: "违规"
|
||
};
|
||
return map[status ?? -1] || "-";
|
||
}
|
||
function statusColor(status) {
|
||
const map = {
|
||
0: "success",
|
||
1: "orange",
|
||
2: "error",
|
||
3: "volcano"
|
||
};
|
||
return map[status ?? -1] || "default";
|
||
}
|
||
watch([filteredArticles, () => pagination.pageSize], () => {
|
||
ensurePaginationInRange();
|
||
});
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
const _component_a_space = resolveComponent("a-space");
|
||
const _component_a_button = resolveComponent("a-button");
|
||
const _component_a_row = resolveComponent("a-row");
|
||
const _component_a_col = resolveComponent("a-col");
|
||
const _component_a_select = resolveComponent("a-select");
|
||
const _component_a_select_option = resolveComponent("a-select-option");
|
||
const _component_a_input_search = resolveComponent("a-input-search");
|
||
const _component_a_table = resolveComponent("a-table");
|
||
const _component_a_tag = resolveComponent("a-tag");
|
||
const _component_a_switch = resolveComponent("a-switch");
|
||
const _component_a_popconfirm = resolveComponent("a-popconfirm");
|
||
const _component_a_modal = resolveComponent("a-modal");
|
||
const _component_a_form = resolveComponent("a-form");
|
||
const _component_a_form_item = resolveComponent("a-form-item");
|
||
const _component_a_input = resolveComponent("a-input");
|
||
const _component_a_upload = resolveComponent("a-upload");
|
||
const _component_a_textarea = resolveComponent("a-textarea");
|
||
const _component_a_radio_group = resolveComponent("a-radio-group");
|
||
const _component_a_radio_button = resolveComponent("a-radio-button");
|
||
const _component_a_divider = resolveComponent("a-divider");
|
||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "articles-page" }, _attrs))} data-v-fea264b4><div class="page-header" data-v-fea264b4><div data-v-fea264b4><h2 class="page-title" data-v-fea264b4>📝 文章管理</h2><p class="page-desc" data-v-fea264b4>管理平台文章内容,支持分类、封面、推荐与状态流转</p></div>`);
|
||
_push(ssrRenderComponent(_component_a_space, null, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(ssrRenderComponent(_component_a_button, {
|
||
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))("/admin/article-categories")
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(` 分类管理 `);
|
||
} else {
|
||
return [
|
||
createTextVNode(" 分类管理 ")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_button, {
|
||
type: "primary",
|
||
onClick: handleCreate
|
||
}, {
|
||
icon: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(unref(PlusOutlined), null, null, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(unref(PlusOutlined))
|
||
];
|
||
}
|
||
}),
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(` 新增文章 `);
|
||
} else {
|
||
return [
|
||
createTextVNode(" 新增文章 ")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_button, {
|
||
onClick: loadArticles,
|
||
loading: unref(loading)
|
||
}, {
|
||
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_button, {
|
||
onClick: ($event) => ("navigateTo" in _ctx ? _ctx.navigateTo : unref(navigateTo))("/admin/article-categories")
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(" 分类管理 ")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
type: "primary",
|
||
onClick: handleCreate
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(PlusOutlined))
|
||
]),
|
||
default: withCtx(() => [
|
||
createTextVNode(" 新增文章 ")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_button, {
|
||
onClick: loadArticles,
|
||
loading: unref(loading)
|
||
}, {
|
||
icon: withCtx(() => [
|
||
createVNode(unref(ReloadOutlined))
|
||
]),
|
||
default: withCtx(() => [
|
||
createTextVNode(" 刷新 ")
|
||
]),
|
||
_: 1
|
||
}, 8, ["loading"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`</div>`);
|
||
_push(ssrRenderComponent(_component_a_row, {
|
||
gutter: [16, 16],
|
||
class: "mb-6"
|
||
}, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(`<!--[-->`);
|
||
ssrRenderList(unref(statCards), (stat) => {
|
||
_push2(ssrRenderComponent(_component_a_col, {
|
||
xs: 12,
|
||
md: 6,
|
||
key: stat.key
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`<div class="${ssrRenderClass([[
|
||
stat.color,
|
||
{
|
||
active: unref(filterStatus) === void 0 && stat.key === -1 || unref(filterStatus) === stat.key
|
||
}
|
||
], "stat-card"])}" data-v-fea264b4${_scopeId2}><div class="stat-icon" data-v-fea264b4${_scopeId2}>${ssrInterpolate(stat.icon)}</div><div class="stat-info" data-v-fea264b4${_scopeId2}><div class="stat-value" data-v-fea264b4${_scopeId2}>${ssrInterpolate(stat.value)}</div><div class="stat-label" data-v-fea264b4${_scopeId2}>${ssrInterpolate(stat.label)}</div></div></div>`);
|
||
} else {
|
||
return [
|
||
createVNode("div", {
|
||
class: ["stat-card", [
|
||
stat.color,
|
||
{
|
||
active: unref(filterStatus) === void 0 && stat.key === -1 || unref(filterStatus) === stat.key
|
||
}
|
||
]],
|
||
onClick: ($event) => handleStatFilter(stat.key)
|
||
}, [
|
||
createVNode("div", { class: "stat-icon" }, toDisplayString(stat.icon), 1),
|
||
createVNode("div", { class: "stat-info" }, [
|
||
createVNode("div", { class: "stat-value" }, toDisplayString(stat.value), 1),
|
||
createVNode("div", { class: "stat-label" }, toDisplayString(stat.label), 1)
|
||
])
|
||
], 10, ["onClick"])
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent2, _scopeId));
|
||
});
|
||
_push2(`<!--]-->`);
|
||
} else {
|
||
return [
|
||
(openBlock(true), createBlock(Fragment, null, renderList(unref(statCards), (stat) => {
|
||
return openBlock(), createBlock(_component_a_col, {
|
||
xs: 12,
|
||
md: 6,
|
||
key: stat.key
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode("div", {
|
||
class: ["stat-card", [
|
||
stat.color,
|
||
{
|
||
active: unref(filterStatus) === void 0 && stat.key === -1 || unref(filterStatus) === stat.key
|
||
}
|
||
]],
|
||
onClick: ($event) => handleStatFilter(stat.key)
|
||
}, [
|
||
createVNode("div", { class: "stat-icon" }, toDisplayString(stat.icon), 1),
|
||
createVNode("div", { class: "stat-info" }, [
|
||
createVNode("div", { class: "stat-value" }, toDisplayString(stat.value), 1),
|
||
createVNode("div", { class: "stat-label" }, toDisplayString(stat.label), 1)
|
||
])
|
||
], 10, ["onClick"])
|
||
]),
|
||
_: 2
|
||
}, 1024);
|
||
}), 128))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`<div class="panel" data-v-fea264b4><div class="panel-header" data-v-fea264b4><span class="panel-title" data-v-fea264b4>📋 文章列表</span>`);
|
||
_push(ssrRenderComponent(_component_a_space, { wrap: "" }, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(ssrRenderComponent(_component_a_select, {
|
||
value: unref(filterStatus),
|
||
"onUpdate:value": ($event) => isRef(filterStatus) ? filterStatus.value = $event : null,
|
||
style: { "width": "120px" },
|
||
onChange: handleSearch
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_select_option, { value: void 0 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`全部状态`);
|
||
} else {
|
||
return [
|
||
createTextVNode("全部状态")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`已发布`);
|
||
} else {
|
||
return [
|
||
createTextVNode("已发布")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`待审核`);
|
||
} else {
|
||
return [
|
||
createTextVNode("待审核")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`已驳回`);
|
||
} else {
|
||
return [
|
||
createTextVNode("已驳回")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`违规`);
|
||
} else {
|
||
return [
|
||
createTextVNode("违规")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_select_option, { value: void 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("全部状态")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_select, {
|
||
value: unref(filterCategoryId),
|
||
"onUpdate:value": ($event) => isRef(filterCategoryId) ? filterCategoryId.value = $event : null,
|
||
"allow-clear": "",
|
||
placeholder: "全部分类",
|
||
style: { "width": "180px" },
|
||
onChange: handleSearch
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`<!--[-->`);
|
||
ssrRenderList(unref(categoryOptions), (item) => {
|
||
_push3(ssrRenderComponent(_component_a_select_option, {
|
||
key: item.categoryId,
|
||
value: item.categoryId
|
||
}, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`${ssrInterpolate(item.title)}`);
|
||
} else {
|
||
return [
|
||
createTextVNode(toDisplayString(item.title), 1)
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent3, _scopeId2));
|
||
});
|
||
_push3(`<!--]-->`);
|
||
} else {
|
||
return [
|
||
(openBlock(true), createBlock(Fragment, null, renderList(unref(categoryOptions), (item) => {
|
||
return openBlock(), createBlock(_component_a_select_option, {
|
||
key: item.categoryId,
|
||
value: item.categoryId
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(item.title), 1)
|
||
]),
|
||
_: 2
|
||
}, 1032, ["value"]);
|
||
}), 128))
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
_push2(ssrRenderComponent(_component_a_input_search, {
|
||
value: unref(searchKeyword),
|
||
"onUpdate:value": ($event) => isRef(searchKeyword) ? searchKeyword.value = $event : null,
|
||
placeholder: "搜索标题 / 摘要 / 作者",
|
||
style: { "width": "240px" },
|
||
onSearch: handleSearch
|
||
}, null, _parent2, _scopeId));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_select, {
|
||
value: unref(filterStatus),
|
||
"onUpdate:value": ($event) => isRef(filterStatus) ? filterStatus.value = $event : null,
|
||
style: { "width": "120px" },
|
||
onChange: handleSearch
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: void 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("全部状态")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"]),
|
||
createVNode(_component_a_select, {
|
||
value: unref(filterCategoryId),
|
||
"onUpdate:value": ($event) => isRef(filterCategoryId) ? filterCategoryId.value = $event : null,
|
||
"allow-clear": "",
|
||
placeholder: "全部分类",
|
||
style: { "width": "180px" },
|
||
onChange: handleSearch
|
||
}, {
|
||
default: withCtx(() => [
|
||
(openBlock(true), createBlock(Fragment, null, renderList(unref(categoryOptions), (item) => {
|
||
return openBlock(), createBlock(_component_a_select_option, {
|
||
key: item.categoryId,
|
||
value: item.categoryId
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(item.title), 1)
|
||
]),
|
||
_: 2
|
||
}, 1032, ["value"]);
|
||
}), 128))
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"]),
|
||
createVNode(_component_a_input_search, {
|
||
value: unref(searchKeyword),
|
||
"onUpdate:value": ($event) => isRef(searchKeyword) ? searchKeyword.value = $event : null,
|
||
placeholder: "搜索标题 / 摘要 / 作者",
|
||
style: { "width": "240px" },
|
||
onSearch: handleSearch
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`</div>`);
|
||
_push(ssrRenderComponent(_component_a_table, {
|
||
columns,
|
||
"data-source": unref(pagedArticles),
|
||
loading: unref(loading),
|
||
pagination: unref(tablePagination),
|
||
"row-key": "articleId",
|
||
onChange: handleTableChange,
|
||
size: "middle"
|
||
}, {
|
||
bodyCell: withCtx(({ column, record }, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
if (column.key === "info") {
|
||
_push2(`<div class="article-info-cell" data-v-fea264b4${_scopeId}>`);
|
||
if (record.image) {
|
||
_push2(`<img${ssrRenderAttr("src", record.image)} class="article-thumb" data-v-fea264b4${_scopeId}>`);
|
||
} else {
|
||
_push2(`<div class="article-thumb-empty" data-v-fea264b4${_scopeId}>📄</div>`);
|
||
}
|
||
_push2(`<div class="article-info-text" data-v-fea264b4${_scopeId}><div class="article-title" data-v-fea264b4${_scopeId}>${ssrInterpolate(record.title)}</div><div class="article-meta" data-v-fea264b4${_scopeId}>`);
|
||
if (record.author) {
|
||
_push2(`<span data-v-fea264b4${_scopeId}>✍️ ${ssrInterpolate(record.author)}</span>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (resolveCategoryName(record)) {
|
||
_push2(`<span class="meta-item" data-v-fea264b4${_scopeId}>📁 ${ssrInterpolate(resolveCategoryName(record))}</span>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
_push2(`</div><div class="article-overview" data-v-fea264b4${_scopeId}>${ssrInterpolate(record.overview || "暂无摘要")}</div></div></div>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (column.key === "status") {
|
||
_push2(ssrRenderComponent(_component_a_tag, {
|
||
color: statusColor(record.status)
|
||
}, {
|
||
default: withCtx((_, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`${ssrInterpolate(statusText(record.status))}`);
|
||
} else {
|
||
return [
|
||
createTextVNode(toDisplayString(statusText(record.status)), 1)
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (column.key === "metrics") {
|
||
_push2(`<div class="metrics-cell" data-v-fea264b4${_scopeId}><div data-v-fea264b4${_scopeId}>👁 ${ssrInterpolate(record.actualViews || 0)} 次阅读</div><div data-v-fea264b4${_scopeId}>❤️ ${ssrInterpolate(record.likes || 0)} 点赞</div></div>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (column.key === "recommend") {
|
||
_push2(ssrRenderComponent(_component_a_switch, {
|
||
checked: !!record.recommend,
|
||
size: "small",
|
||
onChange: (val) => handleToggleRecommend(record, val)
|
||
}, null, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (column.key === "createTime") {
|
||
_push2(`<span class="text-sm text-gray" data-v-fea264b4${_scopeId}>${ssrInterpolate(record.createTime?.substring(0, 10) || "-")}</span>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (column.key === "action") {
|
||
_push2(ssrRenderComponent(_component_a_space, null, {
|
||
default: withCtx((_, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleView(record)
|
||
}, {
|
||
default: withCtx((_2, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`预览`);
|
||
} else {
|
||
return [
|
||
createTextVNode("预览")
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleEdit(record)
|
||
}, {
|
||
default: withCtx((_2, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`编辑`);
|
||
} else {
|
||
return [
|
||
createTextVNode("编辑")
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_popconfirm, {
|
||
title: "确认删除此文章?",
|
||
onConfirm: ($event) => handleDelete(record)
|
||
}, {
|
||
default: withCtx((_2, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
danger: ""
|
||
}, {
|
||
default: withCtx((_3, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(`删除`);
|
||
} else {
|
||
return [
|
||
createTextVNode("删除")
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
danger: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("删除")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleView(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleEdit(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_popconfirm, {
|
||
title: "确认删除此文章?",
|
||
onConfirm: ($event) => handleDelete(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
danger: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("删除")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["onConfirm"])
|
||
];
|
||
}
|
||
}),
|
||
_: 2
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
} else {
|
||
return [
|
||
column.key === "info" ? (openBlock(), createBlock("div", {
|
||
key: 0,
|
||
class: "article-info-cell"
|
||
}, [
|
||
record.image ? (openBlock(), createBlock("img", {
|
||
key: 0,
|
||
src: record.image,
|
||
class: "article-thumb"
|
||
}, null, 8, ["src"])) : (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
class: "article-thumb-empty"
|
||
}, "📄")),
|
||
createVNode("div", { class: "article-info-text" }, [
|
||
createVNode("div", { class: "article-title" }, toDisplayString(record.title), 1),
|
||
createVNode("div", { class: "article-meta" }, [
|
||
record.author ? (openBlock(), createBlock("span", { key: 0 }, "✍️ " + toDisplayString(record.author), 1)) : createCommentVNode("", true),
|
||
resolveCategoryName(record) ? (openBlock(), createBlock("span", {
|
||
key: 1,
|
||
class: "meta-item"
|
||
}, "📁 " + toDisplayString(resolveCategoryName(record)), 1)) : createCommentVNode("", true)
|
||
]),
|
||
createVNode("div", { class: "article-overview" }, toDisplayString(record.overview || "暂无摘要"), 1)
|
||
])
|
||
])) : createCommentVNode("", true),
|
||
column.key === "status" ? (openBlock(), createBlock(_component_a_tag, {
|
||
key: 1,
|
||
color: statusColor(record.status)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(statusText(record.status)), 1)
|
||
]),
|
||
_: 2
|
||
}, 1032, ["color"])) : createCommentVNode("", true),
|
||
column.key === "metrics" ? (openBlock(), createBlock("div", {
|
||
key: 2,
|
||
class: "metrics-cell"
|
||
}, [
|
||
createVNode("div", null, "👁 " + toDisplayString(record.actualViews || 0) + " 次阅读", 1),
|
||
createVNode("div", null, "❤️ " + toDisplayString(record.likes || 0) + " 点赞", 1)
|
||
])) : createCommentVNode("", true),
|
||
column.key === "recommend" ? (openBlock(), createBlock(_component_a_switch, {
|
||
key: 3,
|
||
checked: !!record.recommend,
|
||
size: "small",
|
||
onChange: (val) => handleToggleRecommend(record, val)
|
||
}, null, 8, ["checked", "onChange"])) : createCommentVNode("", true),
|
||
column.key === "createTime" ? (openBlock(), createBlock("span", {
|
||
key: 4,
|
||
class: "text-sm text-gray"
|
||
}, toDisplayString(record.createTime?.substring(0, 10) || "-"), 1)) : createCommentVNode("", true),
|
||
column.key === "action" ? (openBlock(), createBlock(_component_a_space, { key: 5 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleView(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
onClick: ($event) => handleEdit(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_popconfirm, {
|
||
title: "确认删除此文章?",
|
||
onConfirm: ($event) => handleDelete(record)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, {
|
||
type: "link",
|
||
size: "small",
|
||
danger: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("删除")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["onConfirm"])
|
||
]),
|
||
_: 2
|
||
}, 1024)) : createCommentVNode("", true)
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(`</div>`);
|
||
_push(ssrRenderComponent(_component_a_modal, {
|
||
open: unref(showFormModal),
|
||
"onUpdate:open": ($event) => isRef(showFormModal) ? showFormModal.value = $event : null,
|
||
title: unref(editingArticle)?.articleId ? "编辑文章" : "新增文章",
|
||
width: "760px",
|
||
"confirm-loading": unref(saving),
|
||
onOk: handleSave,
|
||
onCancel: ($event) => showFormModal.value = false
|
||
}, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
_push2(ssrRenderComponent(_component_a_form, {
|
||
model: unref(formData),
|
||
layout: "vertical"
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(ssrRenderComponent(_component_a_form_item, {
|
||
label: "文章标题",
|
||
required: ""
|
||
}, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_input, {
|
||
value: unref(formData).title,
|
||
"onUpdate:value": ($event) => unref(formData).title = $event,
|
||
placeholder: "请输入文章标题",
|
||
maxlength: 200,
|
||
"show-count": ""
|
||
}, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).title,
|
||
"onUpdate:value": ($event) => unref(formData).title = $event,
|
||
placeholder: "请输入文章标题",
|
||
maxlength: 200,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_col, { span: 12 }, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_form_item, { label: "作者" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(ssrRenderComponent(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, _parent6, _scopeId5));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, { label: "作者" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(ssrRenderComponent(_component_a_col, { span: 12 }, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_form_item, { label: "来源" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(ssrRenderComponent(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, _parent6, _scopeId5));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, { label: "来源" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "作者" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "来源" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_col, { span: 12 }, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_form_item, { label: "文章分类" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(ssrRenderComponent(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, _parent6, _scopeId5));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, 8, ["value", "onUpdate:value", "options"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, { label: "文章分类" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, 8, ["value", "onUpdate:value", "options"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(ssrRenderComponent(_component_a_col, { span: 12 }, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_form_item, { label: "状态" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(ssrRenderComponent(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx((_6, _push7, _parent7, _scopeId6) => {
|
||
if (_push7) {
|
||
_push7(ssrRenderComponent(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx((_7, _push8, _parent8, _scopeId7) => {
|
||
if (_push8) {
|
||
_push8(`已发布`);
|
||
} else {
|
||
return [
|
||
createTextVNode("已发布")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent7, _scopeId6));
|
||
_push7(ssrRenderComponent(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx((_7, _push8, _parent8, _scopeId7) => {
|
||
if (_push8) {
|
||
_push8(`待审核`);
|
||
} else {
|
||
return [
|
||
createTextVNode("待审核")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent7, _scopeId6));
|
||
_push7(ssrRenderComponent(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx((_7, _push8, _parent8, _scopeId7) => {
|
||
if (_push8) {
|
||
_push8(`已驳回`);
|
||
} else {
|
||
return [
|
||
createTextVNode("已驳回")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent7, _scopeId6));
|
||
_push7(ssrRenderComponent(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx((_7, _push8, _parent8, _scopeId7) => {
|
||
if (_push8) {
|
||
_push8(`违规`);
|
||
} else {
|
||
return [
|
||
createTextVNode("违规")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent7, _scopeId6));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent6, _scopeId5));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, { label: "状态" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "文章分类" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, 8, ["value", "onUpdate:value", "options"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "状态" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, { label: "封面图" }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<div class="cover-upload-wrap" data-v-fea264b4${_scopeId3}>`);
|
||
if (unref(formData).image) {
|
||
_push4(`<div class="cover-preview-card" data-v-fea264b4${_scopeId3}><img${ssrRenderAttr("src", unref(formData).image)} class="cover-preview-image" data-v-fea264b4${_scopeId3}><div class="cover-preview-actions" data-v-fea264b4${_scopeId3}>`);
|
||
_push4(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => handlePreviewImage(unref(formData).image)
|
||
}, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(`预览`);
|
||
} else {
|
||
return [
|
||
createTextVNode("预览")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(ssrRenderComponent(_component_a_button, {
|
||
size: "small",
|
||
danger: "",
|
||
onClick: handleRemoveCover
|
||
}, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(`移除`);
|
||
} else {
|
||
return [
|
||
createTextVNode("移除")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(`</div></div>`);
|
||
} else {
|
||
_push4(`<!---->`);
|
||
}
|
||
_push4(ssrRenderComponent(_component_a_upload, {
|
||
accept: "image/*",
|
||
"show-upload-list": false,
|
||
"before-upload": beforeImageUpload,
|
||
"custom-request": handleCoverUpload
|
||
}, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_button, { loading: unref(imageUploading) }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(`上传封面`);
|
||
} else {
|
||
return [
|
||
createTextVNode("上传封面")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_button, { loading: unref(imageUploading) }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("上传封面")
|
||
]),
|
||
_: 1
|
||
}, 8, ["loading"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(`<div class="field-hint" data-v-fea264b4${_scopeId3}>支持 jpg/png/webp,建议横版封面,单张不超过 5MB</div></div>`);
|
||
} else {
|
||
return [
|
||
createVNode("div", { class: "cover-upload-wrap" }, [
|
||
unref(formData).image ? (openBlock(), createBlock("div", {
|
||
key: 0,
|
||
class: "cover-preview-card"
|
||
}, [
|
||
createVNode("img", {
|
||
src: unref(formData).image,
|
||
class: "cover-preview-image"
|
||
}, null, 8, ["src"]),
|
||
createVNode("div", { class: "cover-preview-actions" }, [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => handlePreviewImage(unref(formData).image)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
danger: "",
|
||
onClick: handleRemoveCover
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("移除")
|
||
]),
|
||
_: 1
|
||
})
|
||
])
|
||
])) : createCommentVNode("", true),
|
||
createVNode(_component_a_upload, {
|
||
accept: "image/*",
|
||
"show-upload-list": false,
|
||
"before-upload": beforeImageUpload,
|
||
"custom-request": handleCoverUpload
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, { loading: unref(imageUploading) }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("上传封面")
|
||
]),
|
||
_: 1
|
||
}, 8, ["loading"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode("div", { class: "field-hint" }, "支持 jpg/png/webp,建议横版封面,单张不超过 5MB")
|
||
])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, { label: "文章摘要" }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_textarea, {
|
||
value: unref(formData).overview,
|
||
"onUpdate:value": ($event) => unref(formData).overview = $event,
|
||
rows: 3,
|
||
placeholder: "文章简短描述",
|
||
maxlength: 500,
|
||
"show-count": ""
|
||
}, null, _parent4, _scopeId3));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_textarea, {
|
||
value: unref(formData).overview,
|
||
"onUpdate:value": ($event) => unref(formData).overview = $event,
|
||
rows: 3,
|
||
placeholder: "文章简短描述",
|
||
maxlength: 500,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, {
|
||
label: "文章内容",
|
||
required: ""
|
||
}, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(`<div class="content-editor-wrap" data-v-fea264b4${_scopeId3}><div class="editor-tabs" data-v-fea264b4${_scopeId3}>`);
|
||
_push4(ssrRenderComponent(_component_a_radio_group, {
|
||
value: unref(editorMode),
|
||
"onUpdate:value": ($event) => isRef(editorMode) ? editorMode.value = $event : null,
|
||
"button-style": "solid",
|
||
size: "small"
|
||
}, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(ssrRenderComponent(_component_a_radio_button, { value: "edit" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(`编辑`);
|
||
} else {
|
||
return [
|
||
createTextVNode("编辑")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
_push5(ssrRenderComponent(_component_a_radio_button, { value: "preview" }, {
|
||
default: withCtx((_5, _push6, _parent6, _scopeId5) => {
|
||
if (_push6) {
|
||
_push6(`预览`);
|
||
} else {
|
||
return [
|
||
createTextVNode("预览")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent5, _scopeId4));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_radio_button, { value: "edit" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_radio_button, { value: "preview" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(`</div><div style="${ssrRenderStyle(unref(editorMode) === "edit" ? null : { display: "none" })}" data-v-fea264b4${_scopeId3}>`);
|
||
_push4(ssrRenderComponent(MarkdownEditor, {
|
||
modelValue: unref(formData).content,
|
||
"onUpdate:modelValue": ($event) => unref(formData).content = $event,
|
||
placeholder: "请输入 Markdown 内容,支持 # 标题、**加粗**、*斜体*、[链接](url)、、代码块等语法",
|
||
"show-preview": false,
|
||
"min-height": "320px"
|
||
}, null, _parent4, _scopeId3));
|
||
_push4(`</div><div class="preview-only-mode" style="${ssrRenderStyle(unref(editorMode) === "preview" ? null : { display: "none" })}" data-v-fea264b4${_scopeId3}>`);
|
||
if (unref(formData).content) {
|
||
_push4(ssrRenderComponent(MarkdownRenderer, {
|
||
content: unref(formData).content
|
||
}, null, _parent4, _scopeId3));
|
||
} else {
|
||
_push4(`<div class="empty-preview" data-v-fea264b4${_scopeId3}>暂无内容</div>`);
|
||
}
|
||
_push4(`</div></div>`);
|
||
} else {
|
||
return [
|
||
createVNode("div", { class: "content-editor-wrap" }, [
|
||
createVNode("div", { class: "editor-tabs" }, [
|
||
createVNode(_component_a_radio_group, {
|
||
value: unref(editorMode),
|
||
"onUpdate:value": ($event) => isRef(editorMode) ? editorMode.value = $event : null,
|
||
"button-style": "solid",
|
||
size: "small"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_radio_button, { value: "edit" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_radio_button, { value: "preview" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
withDirectives(createVNode("div", null, [
|
||
createVNode(MarkdownEditor, {
|
||
modelValue: unref(formData).content,
|
||
"onUpdate:modelValue": ($event) => unref(formData).content = $event,
|
||
placeholder: "请输入 Markdown 内容,支持 # 标题、**加粗**、*斜体*、[链接](url)、、代码块等语法",
|
||
"show-preview": false,
|
||
"min-height": "320px"
|
||
}, null, 8, ["modelValue", "onUpdate:modelValue"])
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "edit"]
|
||
]),
|
||
withDirectives(createVNode("div", { class: "preview-only-mode" }, [
|
||
unref(formData).content ? (openBlock(), createBlock(MarkdownRenderer, {
|
||
key: 0,
|
||
content: unref(formData).content
|
||
}, null, 8, ["content"])) : (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
class: "empty-preview"
|
||
}, "暂无内容"))
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "preview"]
|
||
])
|
||
])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, { label: "内容格式" }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_tag, {
|
||
color: unref(isMarkdown) ? "blue" : "default"
|
||
}, {
|
||
default: withCtx((_4, _push5, _parent5, _scopeId4) => {
|
||
if (_push5) {
|
||
_push5(`${ssrInterpolate(unref(isMarkdown) ? "Markdown" : "纯文本/HTML")}`);
|
||
} else {
|
||
return [
|
||
createTextVNode(toDisplayString(unref(isMarkdown) ? "Markdown" : "纯文本/HTML"), 1)
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent4, _scopeId3));
|
||
_push4(`<span class="format-hint" data-v-fea264b4${_scopeId3}> 当前编辑器支持 Markdown 语法编写 </span>`);
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_tag, {
|
||
color: unref(isMarkdown) ? "blue" : "default"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(isMarkdown) ? "Markdown" : "纯文本/HTML"), 1)
|
||
]),
|
||
_: 1
|
||
}, 8, ["color"]),
|
||
createVNode("span", { class: "format-hint" }, " 当前编辑器支持 Markdown 语法编写 ")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
_push3(ssrRenderComponent(_component_a_form_item, { label: "是否推荐" }, {
|
||
default: withCtx((_3, _push4, _parent4, _scopeId3) => {
|
||
if (_push4) {
|
||
_push4(ssrRenderComponent(_component_a_switch, {
|
||
checked: unref(formRecommend),
|
||
"onUpdate:checked": ($event) => isRef(formRecommend) ? formRecommend.value = $event : null
|
||
}, null, _parent4, _scopeId3));
|
||
_push4(`<span class="switch-tip" data-v-fea264b4${_scopeId3}>推荐文章将优先出现在列表与前台推荐位</span>`);
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_switch, {
|
||
checked: unref(formRecommend),
|
||
"onUpdate:checked": ($event) => isRef(formRecommend) ? formRecommend.value = $event : null
|
||
}, null, 8, ["checked", "onUpdate:checked"]),
|
||
createVNode("span", { class: "switch-tip" }, "推荐文章将优先出现在列表与前台推荐位")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent3, _scopeId2));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form_item, {
|
||
label: "文章标题",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).title,
|
||
"onUpdate:value": ($event) => unref(formData).title = $event,
|
||
placeholder: "请输入文章标题",
|
||
maxlength: 200,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "作者" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "来源" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "文章分类" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, 8, ["value", "onUpdate:value", "options"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "状态" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "封面图" }, {
|
||
default: withCtx(() => [
|
||
createVNode("div", { class: "cover-upload-wrap" }, [
|
||
unref(formData).image ? (openBlock(), createBlock("div", {
|
||
key: 0,
|
||
class: "cover-preview-card"
|
||
}, [
|
||
createVNode("img", {
|
||
src: unref(formData).image,
|
||
class: "cover-preview-image"
|
||
}, null, 8, ["src"]),
|
||
createVNode("div", { class: "cover-preview-actions" }, [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => handlePreviewImage(unref(formData).image)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
danger: "",
|
||
onClick: handleRemoveCover
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("移除")
|
||
]),
|
||
_: 1
|
||
})
|
||
])
|
||
])) : createCommentVNode("", true),
|
||
createVNode(_component_a_upload, {
|
||
accept: "image/*",
|
||
"show-upload-list": false,
|
||
"before-upload": beforeImageUpload,
|
||
"custom-request": handleCoverUpload
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, { loading: unref(imageUploading) }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("上传封面")
|
||
]),
|
||
_: 1
|
||
}, 8, ["loading"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode("div", { class: "field-hint" }, "支持 jpg/png/webp,建议横版封面,单张不超过 5MB")
|
||
])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "文章摘要" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_textarea, {
|
||
value: unref(formData).overview,
|
||
"onUpdate:value": ($event) => unref(formData).overview = $event,
|
||
rows: 3,
|
||
placeholder: "文章简短描述",
|
||
maxlength: 500,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, {
|
||
label: "文章内容",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode("div", { class: "content-editor-wrap" }, [
|
||
createVNode("div", { class: "editor-tabs" }, [
|
||
createVNode(_component_a_radio_group, {
|
||
value: unref(editorMode),
|
||
"onUpdate:value": ($event) => isRef(editorMode) ? editorMode.value = $event : null,
|
||
"button-style": "solid",
|
||
size: "small"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_radio_button, { value: "edit" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_radio_button, { value: "preview" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
withDirectives(createVNode("div", null, [
|
||
createVNode(MarkdownEditor, {
|
||
modelValue: unref(formData).content,
|
||
"onUpdate:modelValue": ($event) => unref(formData).content = $event,
|
||
placeholder: "请输入 Markdown 内容,支持 # 标题、**加粗**、*斜体*、[链接](url)、、代码块等语法",
|
||
"show-preview": false,
|
||
"min-height": "320px"
|
||
}, null, 8, ["modelValue", "onUpdate:modelValue"])
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "edit"]
|
||
]),
|
||
withDirectives(createVNode("div", { class: "preview-only-mode" }, [
|
||
unref(formData).content ? (openBlock(), createBlock(MarkdownRenderer, {
|
||
key: 0,
|
||
content: unref(formData).content
|
||
}, null, 8, ["content"])) : (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
class: "empty-preview"
|
||
}, "暂无内容"))
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "preview"]
|
||
])
|
||
])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "内容格式" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_tag, {
|
||
color: unref(isMarkdown) ? "blue" : "default"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(isMarkdown) ? "Markdown" : "纯文本/HTML"), 1)
|
||
]),
|
||
_: 1
|
||
}, 8, ["color"]),
|
||
createVNode("span", { class: "format-hint" }, " 当前编辑器支持 Markdown 语法编写 ")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "是否推荐" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_switch, {
|
||
checked: unref(formRecommend),
|
||
"onUpdate:checked": ($event) => isRef(formRecommend) ? formRecommend.value = $event : null
|
||
}, null, 8, ["checked", "onUpdate:checked"]),
|
||
createVNode("span", { class: "switch-tip" }, "推荐文章将优先出现在列表与前台推荐位")
|
||
]),
|
||
_: 1
|
||
})
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
return [
|
||
createVNode(_component_a_form, {
|
||
model: unref(formData),
|
||
layout: "vertical"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, {
|
||
label: "文章标题",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).title,
|
||
"onUpdate:value": ($event) => unref(formData).title = $event,
|
||
placeholder: "请输入文章标题",
|
||
maxlength: 200,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "作者" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).author,
|
||
"onUpdate:value": ($event) => unref(formData).author = $event,
|
||
placeholder: "文章作者"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "来源" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_input, {
|
||
value: unref(formData).source,
|
||
"onUpdate:value": ($event) => unref(formData).source = $event,
|
||
placeholder: "文章来源"
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_row, { gutter: 16 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "文章分类" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).categoryId,
|
||
"onUpdate:value": ($event) => unref(formData).categoryId = $event,
|
||
"allow-clear": "",
|
||
"show-search": "",
|
||
"option-filter-prop": "label",
|
||
placeholder: "请选择文章分类",
|
||
options: unref(categorySelectOptions)
|
||
}, null, 8, ["value", "onUpdate:value", "options"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_col, { span: 12 }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_form_item, { label: "状态" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select, {
|
||
value: unref(formData).status,
|
||
"onUpdate:value": ($event) => unref(formData).status = $event
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_select_option, { value: 0 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已发布")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 1 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("待审核")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 2 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("已驳回")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_select_option, { value: 3 }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("违规")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "封面图" }, {
|
||
default: withCtx(() => [
|
||
createVNode("div", { class: "cover-upload-wrap" }, [
|
||
unref(formData).image ? (openBlock(), createBlock("div", {
|
||
key: 0,
|
||
class: "cover-preview-card"
|
||
}, [
|
||
createVNode("img", {
|
||
src: unref(formData).image,
|
||
class: "cover-preview-image"
|
||
}, null, 8, ["src"]),
|
||
createVNode("div", { class: "cover-preview-actions" }, [
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
onClick: ($event) => handlePreviewImage(unref(formData).image)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
}, 8, ["onClick"]),
|
||
createVNode(_component_a_button, {
|
||
size: "small",
|
||
danger: "",
|
||
onClick: handleRemoveCover
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("移除")
|
||
]),
|
||
_: 1
|
||
})
|
||
])
|
||
])) : createCommentVNode("", true),
|
||
createVNode(_component_a_upload, {
|
||
accept: "image/*",
|
||
"show-upload-list": false,
|
||
"before-upload": beforeImageUpload,
|
||
"custom-request": handleCoverUpload
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_button, { loading: unref(imageUploading) }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("上传封面")
|
||
]),
|
||
_: 1
|
||
}, 8, ["loading"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode("div", { class: "field-hint" }, "支持 jpg/png/webp,建议横版封面,单张不超过 5MB")
|
||
])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "文章摘要" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_textarea, {
|
||
value: unref(formData).overview,
|
||
"onUpdate:value": ($event) => unref(formData).overview = $event,
|
||
rows: 3,
|
||
placeholder: "文章简短描述",
|
||
maxlength: 500,
|
||
"show-count": ""
|
||
}, null, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, {
|
||
label: "文章内容",
|
||
required: ""
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode("div", { class: "content-editor-wrap" }, [
|
||
createVNode("div", { class: "editor-tabs" }, [
|
||
createVNode(_component_a_radio_group, {
|
||
value: unref(editorMode),
|
||
"onUpdate:value": ($event) => isRef(editorMode) ? editorMode.value = $event : null,
|
||
"button-style": "solid",
|
||
size: "small"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_radio_button, { value: "edit" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("编辑")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_radio_button, { value: "preview" }, {
|
||
default: withCtx(() => [
|
||
createTextVNode("预览")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["value", "onUpdate:value"])
|
||
]),
|
||
withDirectives(createVNode("div", null, [
|
||
createVNode(MarkdownEditor, {
|
||
modelValue: unref(formData).content,
|
||
"onUpdate:modelValue": ($event) => unref(formData).content = $event,
|
||
placeholder: "请输入 Markdown 内容,支持 # 标题、**加粗**、*斜体*、[链接](url)、、代码块等语法",
|
||
"show-preview": false,
|
||
"min-height": "320px"
|
||
}, null, 8, ["modelValue", "onUpdate:modelValue"])
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "edit"]
|
||
]),
|
||
withDirectives(createVNode("div", { class: "preview-only-mode" }, [
|
||
unref(formData).content ? (openBlock(), createBlock(MarkdownRenderer, {
|
||
key: 0,
|
||
content: unref(formData).content
|
||
}, null, 8, ["content"])) : (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
class: "empty-preview"
|
||
}, "暂无内容"))
|
||
], 512), [
|
||
[vShow, unref(editorMode) === "preview"]
|
||
])
|
||
])
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "内容格式" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_tag, {
|
||
color: unref(isMarkdown) ? "blue" : "default"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(isMarkdown) ? "Markdown" : "纯文本/HTML"), 1)
|
||
]),
|
||
_: 1
|
||
}, 8, ["color"]),
|
||
createVNode("span", { class: "format-hint" }, " 当前编辑器支持 Markdown 语法编写 ")
|
||
]),
|
||
_: 1
|
||
}),
|
||
createVNode(_component_a_form_item, { label: "是否推荐" }, {
|
||
default: withCtx(() => [
|
||
createVNode(_component_a_switch, {
|
||
checked: unref(formRecommend),
|
||
"onUpdate:checked": ($event) => isRef(formRecommend) ? formRecommend.value = $event : null
|
||
}, null, 8, ["checked", "onUpdate:checked"]),
|
||
createVNode("span", { class: "switch-tip" }, "推荐文章将优先出现在列表与前台推荐位")
|
||
]),
|
||
_: 1
|
||
})
|
||
]),
|
||
_: 1
|
||
}, 8, ["model"])
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(ssrRenderComponent(_component_a_modal, {
|
||
open: unref(showPreviewModal),
|
||
"onUpdate:open": ($event) => isRef(showPreviewModal) ? showPreviewModal.value = $event : null,
|
||
title: unref(previewData)?.title || "文章预览",
|
||
width: "760px",
|
||
footer: null
|
||
}, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
if (unref(previewData)) {
|
||
_push2(`<!--[--><div class="preview-meta" data-v-fea264b4${_scopeId}>`);
|
||
_push2(ssrRenderComponent(_component_a_tag, {
|
||
color: statusColor(unref(previewData).status)
|
||
}, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`${ssrInterpolate(statusText(unref(previewData).status))}`);
|
||
} else {
|
||
return [
|
||
createTextVNode(toDisplayString(statusText(unref(previewData).status)), 1)
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
if (unref(previewData).recommend) {
|
||
_push2(ssrRenderComponent(_component_a_tag, { color: "gold" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`推荐`);
|
||
} else {
|
||
return [
|
||
createTextVNode("推荐")
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (unref(previewData).categoryName) {
|
||
_push2(ssrRenderComponent(_component_a_tag, { color: "blue" }, {
|
||
default: withCtx((_2, _push3, _parent3, _scopeId2) => {
|
||
if (_push3) {
|
||
_push3(`${ssrInterpolate(unref(previewData).categoryName)}`);
|
||
} else {
|
||
return [
|
||
createTextVNode(toDisplayString(unref(previewData).categoryName), 1)
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
_push2(`<span class="preview-meta-text" data-v-fea264b4${_scopeId}>${ssrInterpolate(unref(previewData).createTime?.substring(0, 16) || "-")}</span></div>`);
|
||
if (unref(previewData).image) {
|
||
_push2(`<div class="preview-cover-wrap" data-v-fea264b4${_scopeId}><img${ssrRenderAttr("src", unref(previewData).image)} class="preview-cover" data-v-fea264b4${_scopeId}></div>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
if (unref(previewData).overview) {
|
||
_push2(`<div class="preview-summary" data-v-fea264b4${_scopeId}>${ssrInterpolate(unref(previewData).overview)}</div>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
_push2(ssrRenderComponent(_component_a_divider, null, null, _parent2, _scopeId));
|
||
_push2(`<div class="preview-content" data-v-fea264b4${_scopeId}>`);
|
||
if (unref(isPreviewMarkdown)) {
|
||
_push2(ssrRenderComponent(MarkdownRenderer, {
|
||
content: unref(previewData).content
|
||
}, null, _parent2, _scopeId));
|
||
} else {
|
||
_push2(`<div data-v-fea264b4${_scopeId}>${(unref(previewData).content || unref(previewData).overview || "暂无内容") ?? ""}</div>`);
|
||
}
|
||
_push2(`</div><!--]-->`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
} else {
|
||
return [
|
||
unref(previewData) ? (openBlock(), createBlock(Fragment, { key: 0 }, [
|
||
createVNode("div", { class: "preview-meta" }, [
|
||
createVNode(_component_a_tag, {
|
||
color: statusColor(unref(previewData).status)
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(statusText(unref(previewData).status)), 1)
|
||
]),
|
||
_: 1
|
||
}, 8, ["color"]),
|
||
unref(previewData).recommend ? (openBlock(), createBlock(_component_a_tag, {
|
||
key: 0,
|
||
color: "gold"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode("推荐")
|
||
]),
|
||
_: 1
|
||
})) : createCommentVNode("", true),
|
||
unref(previewData).categoryName ? (openBlock(), createBlock(_component_a_tag, {
|
||
key: 1,
|
||
color: "blue"
|
||
}, {
|
||
default: withCtx(() => [
|
||
createTextVNode(toDisplayString(unref(previewData).categoryName), 1)
|
||
]),
|
||
_: 1
|
||
})) : createCommentVNode("", true),
|
||
createVNode("span", { class: "preview-meta-text" }, toDisplayString(unref(previewData).createTime?.substring(0, 16) || "-"), 1)
|
||
]),
|
||
unref(previewData).image ? (openBlock(), createBlock("div", {
|
||
key: 0,
|
||
class: "preview-cover-wrap"
|
||
}, [
|
||
createVNode("img", {
|
||
src: unref(previewData).image,
|
||
class: "preview-cover"
|
||
}, null, 8, ["src"])
|
||
])) : createCommentVNode("", true),
|
||
unref(previewData).overview ? (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
class: "preview-summary"
|
||
}, toDisplayString(unref(previewData).overview), 1)) : createCommentVNode("", true),
|
||
createVNode(_component_a_divider),
|
||
createVNode("div", { class: "preview-content" }, [
|
||
unref(isPreviewMarkdown) ? (openBlock(), createBlock(MarkdownRenderer, {
|
||
key: 0,
|
||
content: unref(previewData).content
|
||
}, null, 8, ["content"])) : (openBlock(), createBlock("div", {
|
||
key: 1,
|
||
innerHTML: unref(previewData).content || unref(previewData).overview || "暂无内容"
|
||
}, null, 8, ["innerHTML"]))
|
||
])
|
||
], 64)) : createCommentVNode("", true)
|
||
];
|
||
}
|
||
}),
|
||
_: 1
|
||
}, _parent));
|
||
_push(ssrRenderComponent(_component_a_modal, {
|
||
open: unref(showImagePreview),
|
||
"onUpdate:open": ($event) => isRef(showImagePreview) ? showImagePreview.value = $event : null,
|
||
title: "封面预览",
|
||
footer: null,
|
||
width: "640px"
|
||
}, {
|
||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||
if (_push2) {
|
||
if (unref(previewImageUrl)) {
|
||
_push2(`<img${ssrRenderAttr("src", unref(previewImageUrl))} class="image-preview-modal" data-v-fea264b4${_scopeId}>`);
|
||
} else {
|
||
_push2(`<!---->`);
|
||
}
|
||
} else {
|
||
return [
|
||
unref(previewImageUrl) ? (openBlock(), createBlock("img", {
|
||
key: 0,
|
||
src: unref(previewImageUrl),
|
||
class: "image-preview-modal"
|
||
}, null, 8, ["src"])) : createCommentVNode("", true)
|
||
];
|
||
}
|
||
}),
|
||
_: 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/articles.vue");
|
||
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
|
||
};
|
||
const articles = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-fea264b4"]]);
|
||
|
||
export { articles as default };
|
||
//# sourceMappingURL=articles-DR9-Jw1_.mjs.map
|