fix: todo修复

This commit is contained in:
hw
2025-11-21 18:19:42 +08:00
parent 0251dc2f3b
commit 8d7d3d5fe1
86 changed files with 963 additions and 1195 deletions

View File

@@ -1,7 +1,6 @@
<script lang="ts" setup>
import type { Article } from './modules/types';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MpDraftApi } from '#/api/mp/draft';
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
@@ -9,7 +8,7 @@ import { ElLoading, ElMessage, ElMessageBox } from 'element-plus';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteDraft, getDraftPage } from '#/api/mp/draft';
import * as MpFreePublishApi from '#/api/mp/freePublish';
import { submitFreePublish } from '#/api/mp/freePublish';
import { WxAccountSelect } from '#/views/mp/components';
import { createEmptyNewsItem } from '#/views/mp/draft/modules/types';
@@ -19,11 +18,6 @@ import Form from './modules/form.vue';
defineOptions({ name: 'MpDraft' });
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
destroyOnClose: true,
});
/** 刷新表格 */
function handleRefresh() {
gridApi.query();
@@ -35,7 +29,91 @@ function handleAccountChange(accountId: number) {
gridApi.formApi.submitForm();
}
// TODO @hw代码风格要和对应的 antd index.vue 一致,类似方法的顺序,注释等。原因是,这样后续两端迭代,会方便很多。
/** 新增草稿 */
async function handleCreate() {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId) {
ElMessage.warning('请先选择公众号');
return;
}
formModalApi
.setData({
isCreating: true,
accountId,
newsList: [createEmptyNewsItem()],
})
.open();
}
/** 修改草稿 */
async function handleEdit(row: MpDraftApi.DraftArticle) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId) {
ElMessage.warning('请先选择公众号');
return;
}
formModalApi
.setData({
isCreating: false,
accountId,
mediaId: row.mediaId,
newsList: row.content.newsItem,
})
.open();
}
/** 删除草稿 */
async function handleDelete(row: MpDraftApi.DraftArticle) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId) {
ElMessage.warning('请先选择公众号');
return;
}
await ElMessageBox.confirm('此操作将永久删除该草稿, 是否继续?');
const hideLoading = ElLoading.service({
text: '删除中...',
});
try {
await deleteDraft(accountId, row.mediaId);
ElMessage.success('删除成功');
handleRefresh();
} finally {
hideLoading.close();
}
}
/** 发布草稿 */
async function handlePublish(row: MpDraftApi.DraftArticle) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId) {
ElMessage.warning('请先选择公众号');
return;
}
await ElMessageBox.confirm(
'你正在通过发布的方式发表内容。 发布不占用群发次数,一天可多次发布。' +
'已发布内容不会推送给用户,也不会展示在公众号主页中。 ' +
'发布后,你可以前往发表记录获取链接,也可以将发布内容添加到自定义菜单、自动回复、话题和页面模板中。',
);
const hideLoading = ElLoading.service({
text: '发布中...',
});
try {
await submitFreePublish(accountId, row.mediaId);
ElMessage.success('发布成功');
handleRefresh();
} finally {
hideLoading.close();
}
}
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
destroyOnClose: true,
});
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
@@ -48,6 +126,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
// 调试用:跳过请求,直接返回模拟数据
const drafts = await getDraftPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
@@ -62,9 +141,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
});
}
});
// 模拟数据
// const mockList = [
return {
list: drafts.list as unknown as Article[],
total: drafts.total,
list: drafts.list,
total: drafts.total, // 模拟总数
};
},
},
@@ -78,101 +161,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
refresh: true,
search: true,
},
} as VxeTableGridOptions<Article>,
} as VxeTableGridOptions<MpDraftApi.DraftArticle>,
});
/** 新增按钮操作 */
async function handleCreate() {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId || accountId === -1) {
ElMessage.warning('请先选择公众号');
return;
}
formModalApi
.setData({
isCreating: true,
accountId,
newsList: [createEmptyNewsItem()],
})
.open();
}
/** 修改按钮操作 */
async function handleEdit(row: Article) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId || accountId === -1) {
ElMessage.warning('请先选择公众号');
return;
}
formModalApi
.setData({
isCreating: false,
accountId,
mediaId: row.mediaId,
newsList: row.content.newsItem,
})
.open();
}
/** 发布按钮操作 */
async function handlePublish(row: Article) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId || accountId === -1) {
ElMessage.warning('请先选择公众号');
return;
}
const content =
'你正在通过发布的方式发表内容。 发布不占用群发次数,一天可多次发布。' +
'已发布内容不会推送给用户,也不会展示在公众号主页中。 ' +
'发布后,你可以前往发表记录获取链接,也可以将发布内容添加到自定义菜单、自动回复、话题和页面模板中。';
try {
await ElMessageBox.confirm(content);
const loadingInstance = ElLoading.service({
text: '发布中...',
});
try {
await MpFreePublishApi.submitFreePublish(accountId, row.mediaId);
ElMessage.success('发布成功');
await gridApi.query();
} finally {
loadingInstance.close();
}
} catch {
//
}
}
/** 删除按钮操作 */
async function handleDelete(row: Article) {
const formValues = await gridApi.formApi.getValues();
const accountId = formValues.accountId;
if (!accountId) {
ElMessage.warning('请先选择公众号');
return;
}
try {
await ElMessageBox.confirm('此操作将永久删除该草稿, 是否继续?');
const loadingInstance = ElLoading.service({
text: '删除中...',
});
try {
await deleteDraft(accountId, row.mediaId);
ElMessage.success('删除成功');
handleRefresh();
} finally {
loadingInstance.close();
}
} catch {
//
}
}
</script>
<template>

View File

@@ -1,165 +0,0 @@
// TODO @hw要不要删除
export default {
list: [
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-q-G9pdsmZw0OYG4FzHQkKfpLfEwIH51wy2bxisx8PvW',
content: {
newsItem: [
{
title: '我是标题OOO',
author: '我是作者',
digest: '我是摘要',
content: '我是内容',
contentSourceUrl: 'https://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9XaFphcmtJVFh3VEc4Q1MxQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuN2QxTE56SFBCYXc2RE9NcUxIeS1CQjJuUHhTWjBlN2VOeGRpRi1fZUhwN1FNQjdrQV9yRU9EU0hibHREZmZoVW5acnZrN3ZjaWsxejR3RGpKczBzTHFIM0dFNFZWVkpBc0dWWlAzUEhlVmpnfn4%3D&chksm=1f6354802814dd969ef83c0f3babe555c614270b30bc383beaf7ffd13b0257f0fe5ced9af694#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn.png',
},
{
title: '我是标题XXX',
author: '我是作者',
digest: '我是摘要',
content: '我是内容',
contentSourceUrl: 'https://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9yTlYwOEs1clpwcE5OUEhCQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuN0NSMjFqN3N1aUZMbFNVLTZHN2ZDME9qOGp2THk2RFNlSTlKZ3Y1czFVZDdQQm5IeUg3dEppSUtpQUh5SExOOTRkT3dHNUdBdHdWSWlOendlREV3dS1jUEVQbFpiVTZmVW5iRWhZcGdkNTFRfn4%3D&chksm=1f6354802814dd96a403151cd44c7da4eecf0e475d25423e46ecd795b513bafd829a75daef9b#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn.png',
},
],
},
updateTime: 1_673_655_730,
},
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-jGpXnO73ihN0lsNXknCRQHapp2xgHMRxHKG50LituFe',
content: {
newsItem: [
{
title: '我是标题(修改)',
author: '我是作者',
digest: '我是摘要',
content: '我是内容',
contentSourceUrl: 'https://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl95WVFXYndIZnZJd0t5cjgvQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuN1dlNURPbWswbEF4RDd5dVJTdjQ4cm9Cc0Q1TWhpMUh6SE1hVEE3ZHljaHhlZjZYSGF5N2JNSHpDTlh6ajNZbkpGTGpTcUQ4M3NMdW41ZUpXNFZZQ1VKbVlaMVp5ekxEV1czREdsY1dOYTZnfn4%3D&chksm=1f6354be2814dda8e6238037c2ebd52b1c8e80e93249a861ad80e4d40e5ca7207233475ca689#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn.png',
},
],
},
updateTime: 1_673_655_584,
},
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-v5SrbNCPpD6M_p3TmSrYwTjKogs-0DMJgmjMyNZPeMO',
content: {
newsItem: [
{
title: '1321',
author: '3232',
digest: '1333',
content: '<p>444</p>',
contentSourceUrl: 'http://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-tlQmcl3RdC-Jcgns6IQtf7zenGy3b86WLT7GzUcrb1T',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9jelJiaDAzbmdpSkJOZ2M2QWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuNDNXVVc2ZDRYeTY0Zm1weXR6dE9vQWh1TzEwbEpUVnRfVzJyaGFDNXBkZ0ZXM2JFOTNaRHNhOHRUeFdEanhMeS01X01kMUNWQ1BpRER3cjYwTl9pMnpFLUJhZXFucVVfM1pDUXlTUEl1S25nfn4%3D&chksm=1f6354bc2814ddaa56a90ad5bc3d078601c8d1589ba01827a8170587bc830ff9747b5f59c3a0#rd',
thumbUrl:
'http://mmbiz.qpic.cn/mmbiz_png/btUmCVHwbJUoicwBiacjVeQbu6QxgBVrukfSJXz509boa21SpH8OVHAqXCJiaiaAaHQJNxwwsa0gHRXVr0G5EZYamw/0?wx_fmt=png',
},
],
},
updateTime: 1_673_628_969,
},
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-vdWrisK5EZbk4Y3tzh8P0PG0eEUbnQrh0BcsEb3WNP0',
content: {
newsItem: [
{
title: 'tudou',
author: 'haha',
digest: '312',
content: '<p>132312</p>',
contentSourceUrl: 'http://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-pgFtUNLu1foMSAMkoOsrQrTZ8EtTMssBLfTtzP0dfjG',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9qdkJ1ZjBoUmg2Uk9TS3RlQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuNVg2aTJsaC1fMkU2eXNacUplN3VDTTZFZkhtMjhuTUZvWkxsNDBRSXExY2tiVXRHb09TaHgtREhzY3doZ0JYeC1TSTZ5eWZldXJsOWtfbV8yMi1aYkcyZ2pOY0haM0Ntb3VSWEtxUGVFRlNBfn4%3D&chksm=1f6354ba2814ddacf0184b24d310483641ef190b1faac098c285eb416c70017e2f54decfa1af#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-pgFtUNLu1foMSAMkoOsrQrTZ8EtTMssBLfTtzP0dfjG.png',
},
],
},
updateTime: 1_673_628_760,
},
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-u9kTIm1DhWZDdXyxsxUVv2Z5DAB99IPxkIRTUUD206k',
content: {
newsItem: [
{
title: '12',
author: '333',
digest: '123',
content: '123',
contentSourceUrl: 'https://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-jVixJGgnBnkBPRbuVptOW0CHYuQFyiOVNtamctS8xU8',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9qVVhpSDZUaFJWTzBBWWRVQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuNWRnTDJWYmF2NER0clV1bThmQ0xUR3hqQnJkZ3BJSUNmNDJmc0lCZ1dadkVnZ3Z5bkN4YWtVUjhoaWZWYzZURUR4NnpMd0Y4Z3U5aUdib0lkMzI4Rjg3SG9JX2FycTMxbUctOHplaTlQVVhnfn4%3D&chksm=1f6354b62814dda076c778af33f06580165d8aa81f7798d55cfabb1886b5c74d9b2124a3535c#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-jVixJGgnBnkBPRbuVptOW0CHYuQFyiOVNtamctS8xU8.jpg',
},
],
},
updateTime: 1_673_626_494,
},
{
mediaId:
'r6ryvl6LrxBU0miaST4Y-sO24upobaENDmeByfBTfaozB3aOqSMAV0lGy-UkHXE7',
content: {
newsItem: [
{
title: '我是标题',
author: '我是作者',
digest: '我是摘要',
content: '我是内容',
contentSourceUrl: 'https://www.iocoder.cn',
thumbMediaId:
'r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn',
showCoverPic: 0,
needOpenComment: 0,
onlyFansCanComment: 0,
url: 'http://mp.weixin.qq.com/s?__biz=MzA3NjM4MzQzOQ==&tempkey=MTIxMl9LT2dqRnpMNUpsR0hjYWtBQWwxQ3R5R0JGTXBDM1Q0N2ZFQm8zeUphOFlwNEpXSWxTYm9RQnJ6cHVuNGNmazZTdlE5WkxvU0tfX2V5cjV2WjJiR0xjQUhyREFSZWo2eWNrUW9EYVh6ZkpWRXBLR3FmTEV6YldBMno3Q2ZvVXBSdzlaVDc3aFhndEpQWUwzWmFMUWt0YVVURE1VZ1FsQTdPMlRtc3JBfn4%3D&chksm=1f6354aa2814ddbcc2637382f963a8742993ac38ebcebe6e3411df5ac82ac7bbdb391be6494a#rd',
thumbUrl:
'http://test.yudao.iocoder.cn/r6ryvl6LrxBU0miaST4Y-pIcmK-zAAId-9TGgy-DrSLhjVuWbuT3ZBjk9K1yQ0Dn.png',
},
],
},
updateTime: 1_673_534_279,
},
],
total: 6,
};

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { UploadFiles, UploadProps, UploadRawFile } from 'element-plus';
import type { NewsItem } from './types';
import type { MpDraftApi } from '#/api/mp/draft';
import { computed, inject, reactive, ref } from 'vue';
@@ -13,20 +13,18 @@ import { ElButton, ElDialog, ElImage, ElMessage, ElUpload } from 'element-plus';
import { UploadType, useBeforeUpload } from '#/utils/useUpload';
import MaterialSelect from '#/views/mp/components/wx-material-select/wx-material-select.vue';
// TODO @hw代码风格要和对应的 antd index.vue 一致,类似方法的顺序,注释等。原因是,这样后续两端迭代,会方便很多。
const props = defineProps<{
isFirst: boolean;
modelValue: NewsItem;
modelValue: MpDraftApi.NewsItem;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', v: NewsItem): void;
(e: 'update:modelValue', v: MpDraftApi.NewsItem): void;
}>();
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-permanent`; // 上传永久素材的地址
const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` };
const newsItem = computed<NewsItem>({
const newsItem = computed<MpDraftApi.NewsItem>({
get() {
return props.modelValue;
},
@@ -36,7 +34,7 @@ const newsItem = computed<NewsItem>({
});
const accountId = inject<number>('accountId');
const showImageDialog = ref(false);
const dialogVisible = ref(false);
const fileList = ref<UploadFiles>([]);
interface UploadData {
@@ -48,15 +46,19 @@ const uploadData: UploadData = reactive({
accountId: accountId!,
});
function handleOpenDialog() {
dialogVisible.value = true;
}
/** 素材选择完成事件*/
function onMaterialSelected(item: any) {
showImageDialog.value = false;
dialogVisible.value = false;
newsItem.value.thumbMediaId = item.mediaId;
newsItem.value.thumbUrl = item.url;
}
const onBeforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) =>
useBeforeUpload(UploadType.Image, 2)(rawFile);
const onBeforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) =>
useBeforeUpload(UploadType.Image, 2)(file as any);
function onUploadSuccess(res: any) {
if (res.code !== 0) {
@@ -113,7 +115,7 @@ function onUploadError(err: Error) {
<ElButton
size="small"
type="primary"
@click="showImageDialog = true"
@click="handleOpenDialog"
class="ml-1.5"
>
素材库选择
@@ -127,7 +129,7 @@ function onUploadError(err: Error) {
</div>
<ElDialog
title="选择图片"
v-model="showImageDialog"
v-model="dialogVisible"
width="80%"
append-to-body
destroy-on-close

View File

@@ -93,27 +93,29 @@ function plusNews() {
<template>
<ElContainer>
<ElAside width="40%">
<div class="mx-auto mb-2.5 w-3/5 border border-gray-200 p-2.5">
<div class="mx-auto mb-[10px] w-[60%] border border-[#eaeaea] p-[10px]">
<div v-for="(news, index) in newsList" :key="index">
<div
class="group mx-auto h-[120px] w-full cursor-pointer bg-white"
class="group relative mx-auto mb-[10px] w-full cursor-pointer border-[2px] bg-white"
v-if="index === 0"
:class="{
'border-[5px] border-[#2bb673]': activeNewsIndex === index,
}"
:class="
activeNewsIndex === index
? 'border-green-500'
: 'border-transparent'
"
@click="activeNewsIndex = index"
>
<div class="relative h-[120px] w-full bg-[#acadae]">
<div class="relative w-full bg-[#acadae]">
<img class="h-full w-full" :src="news.thumbUrl" />
<div
class="absolute bottom-0 left-0 inline-block h-[25px] w-[98%] overflow-hidden text-ellipsis whitespace-nowrap bg-black p-[1%] text-[15px] text-white opacity-65"
class="absolute bottom-0 left-0 inline-block h-[25px] w-[100%] overflow-hidden text-ellipsis whitespace-nowrap bg-black p-[1%] text-center text-[15px] text-white opacity-65"
>
{{ news.title }}
</div>
</div>
<div
class="relative flex justify-center gap-[10px] py-[5px] text-center"
v-if="newsList.length > 1"
class="relative -bottom-6 hidden text-center group-hover:block"
>
<ElButton
type="info"
@@ -134,25 +136,29 @@ function plusNews() {
</ElButton>
</div>
</div>
<!-- TODO @hw1每个文章的选中框太粗了2没完全覆盖住文章最好首个文章和第个文章的情况都看看 -->
<div
class="group mx-auto w-full cursor-pointer border-t border-gray-200 bg-white py-1.5"
class="group relative mx-auto mb-[10px] cursor-pointer border-[2px] bg-white"
v-if="index > 0"
:class="{
'border-[5px] border-[#2bb673]': activeNewsIndex === index,
}"
:class="
activeNewsIndex === index
? 'border-green-500'
: 'border-transparent'
"
@click="activeNewsIndex = index"
>
<div class="relative -ml-0.5">
<div class="inline-block w-[70%] text-xs">{{ news.title }}</div>
<div class="inline-block w-1/4 bg-[#acadae]">
<img class="h-full w-full" :src="news.thumbUrl" width="100%" />
<div class="relative">
<div class="bg-[#acadae]">
<img class="block h-full w-full" :src="news.thumbUrl" />
<div
class="absolute bottom-0 left-0 inline-block h-[25px] w-[100%] overflow-hidden text-ellipsis whitespace-nowrap bg-black p-[1%] text-center text-[15px] text-white opacity-65"
>
{{ news.title }}
</div>
</div>
</div>
<!-- TODO @hw这里的按钮交互不太对应该在每个卡片的里面或者类似公众号现在的交互放到右侧复现本周如果有 2 个文章的时候 -->
<!-- TODO @hw当有 2 个文章的时候挪到第二个文章的时候卡片会变大期望不变大 -->
<div
class="relative -bottom-6 hidden text-center group-hover:block"
class="relative flex justify-center gap-[10px] py-[5px] text-center"
>
<ElButton
v-if="newsList.length > index + 1"