Files
iot-device-management-frontend/apps/web-ele/src/views/mp/material/index.vue

260 lines
6.9 KiB
Vue
Raw Normal View History

2025-11-28 15:42:19 +08:00
<script lang="ts" setup>
2025-12-15 10:13:13 +08:00
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MpMaterialApi } from '#/api/mp/material';
import { provide, ref } from 'vue';
2025-11-28 15:42:19 +08:00
import { useAccess } from '@vben/access';
import { confirm, DocAlert, Page } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import {
ElButton,
ElLoading,
ElMessage,
ElTabPane,
ElTabs,
} from 'element-plus';
2025-12-15 10:13:13 +08:00
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
2025-11-28 15:42:19 +08:00
import { deletePermanentMaterial, getMaterialPage } from '#/api/mp/material';
import { WxAccountSelect } from '#/views/mp/components';
2025-12-15 10:13:13 +08:00
import {
useGridFormSchema,
useImageGridColumns,
useVideoGridColumns,
useVoiceGridColumns,
} from './modules/data';
2025-11-28 15:42:19 +08:00
import { UploadType } from './modules/upload';
import UploadFile from './modules/UploadFile.vue';
import UploadVideo from './modules/UploadVideo.vue';
defineOptions({ name: 'MpMaterial' });
const { hasAccessByCodes } = useAccess();
const type = ref<UploadType>(UploadType.Image); // 素材类型
2025-12-15 10:13:13 +08:00
const showCreateVideo = ref(false); // 是否新建视频的弹窗
2025-11-28 15:42:19 +08:00
const accountId = ref(-1);
provide('accountId', accountId);
2025-12-15 10:13:13 +08:00
// 根据类型获取对应的列配置
const getColumnsByType = () => {
switch (type.value) {
case UploadType.Image: {
return useImageGridColumns();
}
case UploadType.Video: {
return useVideoGridColumns();
}
case UploadType.Voice: {
return useVoiceGridColumns();
}
default: {
return [];
}
}
};
2025-11-28 15:42:19 +08:00
2025-12-15 10:13:13 +08:00
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: useGridFormSchema(),
},
gridOptions: {
columns: getColumnsByType(),
height: 'auto',
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
const finalAccountId = formValues?.accountId ?? accountId.value;
if (!finalAccountId || finalAccountId === -1) {
return { list: [], total: 0 };
}
return await getMaterialPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
type: type.value,
permanent: true,
accountId: finalAccountId,
...formValues,
});
},
},
autoLoad: false,
},
rowConfig: {
keyField: 'id',
isHover: true,
height: type.value === UploadType.Image ? 220 : 'auto',
},
toolbarConfig: {
refresh: true,
search: true,
},
} as VxeTableGridOptions<MpMaterialApi.Material>,
});
2025-11-28 15:42:19 +08:00
2025-12-15 10:13:13 +08:00
// 当 tab 切换时,更新 Grid 的 columns 和 rowConfig
async function onTabChange() {
const columns = getColumnsByType();
gridApi.setGridOptions({
2025-12-15 10:13:13 +08:00
columns,
rowConfig: {
keyField: 'id',
isHover: true,
height: type.value === UploadType.Image ? 220 : 'auto',
},
});
await gridApi.reload();
2025-11-28 15:42:19 +08:00
}
2025-12-15 10:13:13 +08:00
async function handleAccountChange(id: number) {
accountId.value = id;
// 同步设置表单值
await gridApi.formApi.setValues({ accountId: id });
2025-12-15 10:13:13 +08:00
await gridApi.formApi.submitForm();
2025-11-28 15:42:19 +08:00
}
2025-12-15 10:13:13 +08:00
async function handleRefresh() {
await gridApi.query();
2025-11-28 15:42:19 +08:00
}
/** 处理删除操作 */
async function handleDelete(id: number) {
await confirm('此操作将永久删除该文件, 是否继续?');
const loadingInstance = ElLoading.service({
text: '正在删除...',
lock: true,
});
try {
await deletePermanentMaterial(id);
ElMessage.success('删除成功');
await handleRefresh();
2025-11-28 15:42:19 +08:00
} finally {
loadingInstance.close();
}
}
</script>
<template>
<Page auto-content-height>
<template #doc>
<DocAlert title="公众号素材" url="https://doc.iocoder.cn/mp/material/" />
</template>
2025-12-15 10:13:13 +08:00
<Grid class="material-grid">
<template #form-accountId>
<WxAccountSelect @change="handleAccountChange" />
</template>
<template #toolbar-actions>
<ElTabs v-model="type" class="w-full" @tab-change="onTabChange">
2025-11-28 15:42:19 +08:00
<!-- tab 1图片 -->
<ElTabPane :name="UploadType.Image">
<template #label>
<span class="flex items-center">
<IconifyIcon icon="lucide:image" class="mr-1" />
图片
</span>
</template>
</ElTabPane>
<!-- tab 2语音 -->
<ElTabPane :name="UploadType.Voice">
<template #label>
<span class="flex items-center">
<IconifyIcon icon="lucide:mic" class="mr-1" />
语音
</span>
</template>
</ElTabPane>
<!-- tab 3视频 -->
<ElTabPane :name="UploadType.Video">
<template #label>
<span class="flex items-center">
<IconifyIcon icon="lucide:video" class="mr-1" />
视频
</span>
</template>
</ElTabPane>
</ElTabs>
2025-12-15 10:13:13 +08:00
</template>
<template #toolbar-tools>
<UploadFile
v-if="
hasAccessByCodes(['mp:material:upload-permanent']) &&
type === UploadType.Image
"
:type="UploadType.Image"
@uploaded="handleRefresh"
/>
<UploadFile
v-if="
hasAccessByCodes(['mp:material:upload-permanent']) &&
type === UploadType.Voice
"
:type="UploadType.Voice"
@uploaded="handleRefresh"
/>
<ElButton
v-if="
hasAccessByCodes(['mp:material:upload-permanent']) &&
type === UploadType.Video
"
type="primary"
@click="showCreateVideo = true"
>
新建视频
</ElButton>
</template>
<!-- 图片列的 slot -->
2025-12-15 10:13:13 +08:00
<template #image="{ row }">
<div class="flex items-center justify-center" style="height: 192px">
<img
:src="row.url"
class="object-contain"
style="display: block; max-width: 100%; max-height: 192px"
/>
</div>
</template>
<!-- 语音列的 slot -->
2025-12-15 10:13:13 +08:00
<template #voice="{ row }">
<audio :src="row.url" controls style="width: 160px"></audio>
</template>
<!-- 视频列的 slot -->
2025-12-15 10:13:13 +08:00
<template #video="{ row }">
<video
:src="row.url"
controls
style="width: 200px; height: 150px"
></video>
</template>
<!-- 操作列的 slot -->
2025-12-15 10:13:13 +08:00
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.delete'),
type: 'danger',
link: true,
icon: ACTION_ICON.DELETE,
2025-12-15 10:13:13 +08:00
auth: ['mp:material:delete'],
onClick: () => handleDelete(row.id!),
2025-12-15 10:13:13 +08:00
},
]"
/>
</template>
</Grid>
<!-- 新建视频的弹窗 -->
<UploadVideo v-model:open="showCreateVideo" @uploaded="handleRefresh" />
2025-11-28 15:42:19 +08:00
</Page>
</template>