feat(B2): 附件管理改"未使用"语义+用途列;banner/link 上传带 scene
- AttachmentManage: orphanCount→unusedCount(零残留),用途列(文章/轮播/友链/站点配置/未使用) - BannerManage/LinkManage 上传 action 传 scene;ArticleList 删除提示文案同步 - types AttachmentVo 增 refType;vitest 24/24+build 绿
This commit is contained in:
@@ -166,7 +166,7 @@ class ArticleApi {
|
|||||||
|
|
||||||
class AttachmentApi {
|
class AttachmentApi {
|
||||||
page(siteId: number, orphanOnly: boolean, page: number, pageSize: number) {
|
page(siteId: number, orphanOnly: boolean, page: number, pageSize: number) {
|
||||||
return get<PageResult<AttachmentVo> & { orphanCount: number }>(`${ATTACHMENT}/page`, {
|
return get<PageResult<AttachmentVo> & { unusedCount: number }>(`${ATTACHMENT}/page`, {
|
||||||
siteId,
|
siteId,
|
||||||
orphanOnly,
|
orphanOnly,
|
||||||
page,
|
page,
|
||||||
|
|||||||
@@ -173,11 +173,14 @@ export interface AttachmentVo {
|
|||||||
id: number;
|
id: number;
|
||||||
siteId: number;
|
siteId: number;
|
||||||
articleId?: number;
|
articleId?: number;
|
||||||
|
/** 场景引用类型(B2):banner/link/site;空=无场景引用 */
|
||||||
|
refType?: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
url: string;
|
url: string;
|
||||||
fileSize?: number;
|
fileSize?: number;
|
||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
|
/** 未使用(B2 语义:无文章引用且无场景引用) */
|
||||||
orphan: boolean;
|
orphan: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ function doDelete(row: ArticlePageItem) {
|
|||||||
MyConfirm({
|
MyConfirm({
|
||||||
title: "删除文章",
|
title: "删除文章",
|
||||||
msg: `确定删除「${row.title}」吗?`,
|
msg: `确定删除「${row.title}」吗?`,
|
||||||
info: "删除后正文图片将转为孤儿附件,可在附件管理中清理",
|
info: "删除后正文图片将转为未使用附件,可在附件管理中清理",
|
||||||
async onOk() {
|
async onOk() {
|
||||||
await articleApi.delete({ id: row.id, siteId: store.siteId! }).send();
|
await articleApi.delete({ id: row.id, siteId: store.siteId! }).send();
|
||||||
Message.success("操作成功!");
|
Message.success("操作成功!");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const store = useCmsStore();
|
|||||||
|
|
||||||
const rows = ref<AttachmentVo[]>([]);
|
const rows = ref<AttachmentVo[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const orphanCount = ref(0);
|
const unusedCount = ref(0);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const pageNum = ref(1);
|
const pageNum = ref(1);
|
||||||
const pageSize = ref(parseInt(localStorage.getItem("customPageCount") || "10"));
|
const pageSize = ref(parseInt(localStorage.getItem("customPageCount") || "10"));
|
||||||
@@ -32,16 +32,17 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{ title: "大小", key: "fileSize", width: 100, render: (h: any, p: any) => h("span", Utils.getFileSize(p.row.fileSize || 0)) },
|
{ title: "大小", key: "fileSize", width: 100, render: (h: any, p: any) => h("span", Utils.getFileSize(p.row.fileSize || 0)) },
|
||||||
{
|
{
|
||||||
title: "关联文章",
|
title: "用途",
|
||||||
key: "articleId",
|
key: "usage",
|
||||||
width: 100,
|
width: 110,
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (h: any, p: any) =>
|
render: (h: any, p: any) => {
|
||||||
h(
|
// B2 引用模型:文章(articleId)优先,其次场景引用(banner/link/site),均无=未使用
|
||||||
Tag,
|
const usage = p.row.articleId
|
||||||
{ color: p.row.orphan ? "warning" : "default" },
|
? "文章"
|
||||||
() => (p.row.orphan ? "孤儿" : p.row.articleId)
|
: { banner: "轮播", link: "友链", site: "站点配置" }[p.row.refType as string] || "未使用";
|
||||||
),
|
return h(Tag, { color: usage === "未使用" ? "warning" : "default" }, () => usage);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{ title: "上传时间", key: "createTime", width: 170 },
|
{ title: "上传时间", key: "createTime", width: 170 },
|
||||||
{
|
{
|
||||||
@@ -68,7 +69,7 @@ async function run() {
|
|||||||
.send();
|
.send();
|
||||||
rows.value = page?.list || [];
|
rows.value = page?.list || [];
|
||||||
total.value = page?.total || 0;
|
total.value = page?.total || 0;
|
||||||
orphanCount.value = (page as any)?.orphanCount || 0;
|
unusedCount.value = (page as any)?.unusedCount || 0;
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
@@ -95,9 +96,9 @@ function doDelete(row: AttachmentVo) {
|
|||||||
|
|
||||||
function cleanOrphans() {
|
function cleanOrphans() {
|
||||||
MyConfirm({
|
MyConfirm({
|
||||||
title: "清理孤儿附件",
|
title: "查看未使用附件",
|
||||||
msg: `当前共有 ${orphanCount.value} 条孤儿附件记录(关联文章已删除),仅清理列表页中勾选的记录。`,
|
msg: `当前共有 ${unusedCount.value} 条未使用附件记录(无文章引用且无场景引用),点击确定切换到未使用列表。`,
|
||||||
info: "为避免误删被封面/轮播引用的文件,MVP 不提供一键全清",
|
info: "为避免误删被引用的文件,MVP 不提供一键全清;旧数据在重新保存对应内容前显示为未使用属正常现象",
|
||||||
onOk() {
|
onOk() {
|
||||||
filter.orphanOnly = true;
|
filter.orphanOnly = true;
|
||||||
pageNum.value = 1;
|
pageNum.value = 1;
|
||||||
@@ -140,11 +141,11 @@ watch(() => store.siteId, () => {
|
|||||||
<Button type="primary" size="large" icon="ios-cloud-upload-outline">上传附件</Button>
|
<Button type="primary" size="large" icon="ios-cloud-upload-outline">上传附件</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
<Button class="fl" style="margin-left: 8px" size="large" @click="cleanOrphans">
|
<Button class="fl" style="margin-left: 8px" size="large" @click="cleanOrphans">
|
||||||
孤儿附件({{ orphanCount }})
|
未使用附件({{ unusedCount }})
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-wrap">
|
<div class="search-wrap">
|
||||||
<Checkbox v-model="filter.orphanOnly" @on-change="pageNum = 1; run()">仅看孤儿附件</Checkbox>
|
<Checkbox v-model="filter.orphanOnly" @on-change="pageNum = 1; run()">仅看未使用附件</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ watch(() => store.siteId, () => run());
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="轮播图片" required>
|
<FormItem label="轮播图片" required>
|
||||||
<Upload
|
<Upload
|
||||||
:action="uploadUrl() + '?siteId=' + store.siteId"
|
:action="uploadUrl() + '?siteId=' + store.siteId + '&scene=banner'"
|
||||||
with-credentials
|
with-credentials
|
||||||
:show-upload-list="false"
|
:show-upload-list="false"
|
||||||
:format="['jpg', 'jpeg', 'png', 'gif', 'webp']"
|
:format="['jpg', 'jpeg', 'png', 'gif', 'webp']"
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ watch(() => store.siteId, () => run());
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Logo(可选)">
|
<FormItem label="Logo(可选)">
|
||||||
<Upload
|
<Upload
|
||||||
:action="uploadUrl() + '?siteId=' + store.siteId"
|
:action="uploadUrl() + '?siteId=' + store.siteId + '&scene=link'"
|
||||||
with-credentials
|
with-credentials
|
||||||
:show-upload-list="false"
|
:show-upload-list="false"
|
||||||
:format="['jpg', 'jpeg', 'png', 'gif', 'webp']"
|
:format="['jpg', 'jpeg', 'png', 'gif', 'webp']"
|
||||||
|
|||||||
Reference in New Issue
Block a user