(
+ {
+ url: "/Article/Delete?key="+data,
+ method: "post",
+ data,
+ }
+ )
+ };
+
+}
+
+const articleService= new ArticleService();
+export default articleService;
\ No newline at end of file
diff --git a/uniapp/youjiala/src/utils/fileUrl.ts b/uniapp/youjiala/src/utils/fileUrl.ts
index b977b13..acb28f5 100644
--- a/uniapp/youjiala/src/utils/fileUrl.ts
+++ b/uniapp/youjiala/src/utils/fileUrl.ts
@@ -146,6 +146,67 @@ export function wanFileUrl(path?: string | null): string {
* 提交用的相对路径 /FileServer/... 与裸物理名(无主机)、blob:/data:/本地路径均不含“主机+/FileServer”,天然被排除 */
const FILE_URL_PATH_MARKER = "/FileServer/";
+/**
+ * 上传即落盘的备份文件直链:/FileServer/Backup/{folder}/{ext}/{物理名}。
+ *
+ * 为什么需要:DmsFile/UploadFile 上传成功后文件立刻落盘(与是否保存业务数据无关),
+ * 后端读取态才用 PackAvatarUrl 把物理名打成这个结构;前端「保存前预览 / 富文本内联插图」
+ * 拿不到后端打包地址,直接 absoluteFileUrl(裸物理名) 会拼出 {base}/uni-xxx.jpg 的坏地址。
+ * 这里按后端同口径自行拼相对路径再过 absoluteFileUrl(H5 锁 origin、App 跟线路),
+ * 保存前后同一个地址都能取到图。folder 须与后端 UploadFolderPolicy 一致(如 ArticleCover / ArticleImage)。
+ */
+export function backupFileUrl(
+ folder: string,
+ fileName?: string | null,
+): string {
+ const name = String(fileName ?? "").trim();
+ if (!name) {
+ return "";
+ }
+ // 已是绝对/相对直链或本地资源:交给 absoluteFileUrl 归一,不再重复打包
+ if (
+ name.includes(FILE_URL_PATH_MARKER) ||
+ /^(?:https?:|blob:|data:|\/)/i.test(name)
+ ) {
+ return absoluteFileUrl(name);
+ }
+ const dot = name.lastIndexOf(".");
+ const ext = dot > 0 ? name.slice(dot + 1).toLowerCase() : "ext";
+ return absoluteFileUrl(`/FileServer/Backup/${folder}/${ext}/${name}`);
+}
+
+/**
+ * 改写富文本(文章正文 Brief)HTML 里每个
的 src。
+ *
+ * 为什么单独处理:响应层 normalizePayloadFileUrls 只改「整个字段值就是绝对 FileServer URL」的串,
+ * 而 Brief 是 HTML(以 开头),absoluteHost 判非绝对 → 漏改。后端 Debug 会把 localhost:5235
+ * 打进正文内联
,App 上 localhost 指向手机自己,插图必挂;封面/配图走 absoluteFileUrl 才没事。
+ * - display:把 src 归一到当前端可达的绝对地址(absoluteFileUrl,App 跟线路、H5 锁 origin);
+ * - store:把 src 剥成 host 无关的相对路径 /FileServer/...(toPathAndQuery),存库后跨环境可移植。
+ * 判据极窄:只碰含 /FileServer/ 的地址;blob:/data:/file:/设备路径等本地资源、外部图 URL 一律原样放行。
+ */
+export function mapBriefImageSrc(
+ html: string,
+ mode: "display" | "store",
+): string {
+ return String(html ?? "").replace(
+ /(
]*?\ssrc=)(["'])([^"']*)\2/gi,
+ (whole, prefix: string, quote: string, src: string) => {
+ const trimmed = String(src).trim();
+ if (
+ !trimmed ||
+ isLocalResource(trimmed) ||
+ !trimmed.includes(FILE_URL_PATH_MARKER)
+ ) {
+ return whole;
+ }
+ const next =
+ mode === "display" ? absoluteFileUrl(trimmed) : toPathAndQuery(trimmed);
+ return next ? `${prefix}${quote}${next}${quote}` : whole;
+ },
+ );
+}
+
/** 取绝对 http(s) 地址的主机(小写、含端口);非绝对地址返回 null */
function absoluteHost(url: string): string | null {
const matched = /^https?:\/\/([^/]+)/i.exec(url);