2025-11-04 17:32:12 +08:00
|
|
|
|
<script lang="ts" setup>
|
2025-11-07 13:21:42 +08:00
|
|
|
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
|
|
|
|
|
|
|
|
|
|
|
import { watch } from 'vue';
|
|
|
|
|
|
|
2025-11-04 17:32:12 +08:00
|
|
|
|
import { useAccess } from '@vben/access';
|
|
|
|
|
|
import { IconifyIcon } from '@vben/icons';
|
|
|
|
|
|
import { formatDate2 } from '@vben/utils';
|
|
|
|
|
|
|
2025-11-07 13:21:42 +08:00
|
|
|
|
import { Button } from 'ant-design-vue';
|
2025-11-06 15:25:11 +08:00
|
|
|
|
|
2025-11-07 13:21:42 +08:00
|
|
|
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
2025-11-06 15:36:08 +08:00
|
|
|
|
import { WxVoicePlayer } from '#/views/mp/components/wx-voice-play';
|
2025-11-04 17:32:12 +08:00
|
|
|
|
|
2025-11-13 13:57:17 +08:00
|
|
|
|
// TODO @dylan:vue 组件名小写 + 中划线
|
|
|
|
|
|
|
2025-11-13 20:31:46 +08:00
|
|
|
|
// TODO @dylan:组件内,尽量用 modules 哈。只有对外共享,才用 components
|
|
|
|
|
|
|
2025-11-04 17:32:12 +08:00
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
list: any[];
|
|
|
|
|
|
loading: boolean;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
delete: [v: number];
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
|
|
const { hasAccessByCodes } = useAccess();
|
|
|
|
|
|
|
2025-11-13 20:31:46 +08:00
|
|
|
|
// TODO @dylan:这里有个告警哈;
|
|
|
|
|
|
// TODO @dylan:放到 data.ts 里;
|
2025-11-07 13:21:42 +08:00
|
|
|
|
const columns: VxeTableGridOptions<any>['columns'] = [
|
2025-11-06 15:25:11 +08:00
|
|
|
|
{
|
2025-11-07 13:21:42 +08:00
|
|
|
|
field: 'mediaId',
|
2025-11-06 15:25:11 +08:00
|
|
|
|
title: '编号',
|
2025-11-07 13:21:42 +08:00
|
|
|
|
align: 'center',
|
|
|
|
|
|
width: 160,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'name',
|
|
|
|
|
|
title: '文件名',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
minWidth: 200,
|
2025-11-06 15:25:11 +08:00
|
|
|
|
},
|
2025-11-13 20:31:46 +08:00
|
|
|
|
// TODO @dylan:语音的样式,有点奇怪。
|
2025-11-06 15:25:11 +08:00
|
|
|
|
{
|
2025-11-07 13:21:42 +08:00
|
|
|
|
field: 'voice',
|
|
|
|
|
|
title: '语音',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
width: 220,
|
|
|
|
|
|
slots: { default: 'voice' },
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'createTime',
|
2025-11-06 15:25:11 +08:00
|
|
|
|
title: '上传时间',
|
2025-11-07 13:21:42 +08:00
|
|
|
|
align: 'center',
|
2025-11-06 15:25:11 +08:00
|
|
|
|
width: 180,
|
2025-11-07 13:21:42 +08:00
|
|
|
|
slots: { default: 'createTime' },
|
2025-11-06 15:25:11 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-11-07 13:21:42 +08:00
|
|
|
|
field: 'actions',
|
2025-11-06 15:25:11 +08:00
|
|
|
|
title: '操作',
|
2025-11-07 13:21:42 +08:00
|
|
|
|
align: 'center',
|
|
|
|
|
|
fixed: 'right',
|
|
|
|
|
|
width: 160,
|
|
|
|
|
|
slots: { default: 'actions' },
|
2025-11-06 15:25:11 +08:00
|
|
|
|
},
|
2025-11-04 17:32:12 +08:00
|
|
|
|
];
|
|
|
|
|
|
|
2025-11-07 13:21:42 +08:00
|
|
|
|
const [Grid, gridApi] = useVbenVxeGrid({
|
|
|
|
|
|
gridOptions: {
|
|
|
|
|
|
border: true,
|
|
|
|
|
|
columns,
|
|
|
|
|
|
keepSource: true,
|
|
|
|
|
|
pagerConfig: {
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
rowConfig: {
|
|
|
|
|
|
keyField: 'id',
|
|
|
|
|
|
isHover: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
showOverflow: 'tooltip',
|
2025-11-13 13:57:17 +08:00
|
|
|
|
} as VxeTableGridOptions<any>, // TODO @dylan:这里有个告警哈;
|
2025-11-07 13:21:42 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-06 23:23:25 +08:00
|
|
|
|
function handleDownload(url: string) {
|
2025-11-04 17:32:12 +08:00
|
|
|
|
window.open(url, '_blank');
|
2025-11-06 23:23:25 +08:00
|
|
|
|
}
|
2025-11-07 13:21:42 +08:00
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
() => props.list,
|
|
|
|
|
|
(list: any[]) => {
|
|
|
|
|
|
const data = Array.isArray(list) ? list : [];
|
|
|
|
|
|
if (gridApi.grid?.loadData) {
|
|
|
|
|
|
gridApi.grid.loadData(data);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
gridApi.setGridOptions({ data });
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{ immediate: true },
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
() => props.loading,
|
|
|
|
|
|
(loading: boolean) => {
|
2025-11-13 13:57:17 +08:00
|
|
|
|
gridApi.setLoading(loading);
|
2025-11-07 13:21:42 +08:00
|
|
|
|
},
|
|
|
|
|
|
{ immediate: true },
|
|
|
|
|
|
);
|
2025-11-04 17:32:12 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
2025-11-07 13:21:42 +08:00
|
|
|
|
<Grid class="mt-4">
|
|
|
|
|
|
<template #voice="{ row }">
|
|
|
|
|
|
<WxVoicePlayer v-if="row.url" :url="row.url" />
|
|
|
|
|
|
</template>
|
2025-11-13 20:31:46 +08:00
|
|
|
|
<!-- TODO @dylan:应该 data.ts 里 formatDate 就好了。别的模块有的哈。 -->
|
2025-11-07 13:21:42 +08:00
|
|
|
|
<template #createTime="{ row }">
|
|
|
|
|
|
{{ formatDate2(row.createTime) }}
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template #actions="{ row }">
|
2025-11-13 20:31:46 +08:00
|
|
|
|
<!-- TODO @dylan:用 tableaction 哈:yudao-ui-admin-vben-v5/apps/web-antd/src/views/system/user/index.vue -->
|
2025-11-07 13:21:42 +08:00
|
|
|
|
<Button type="link" @click="handleDownload(row.url)">
|
|
|
|
|
|
<IconifyIcon icon="mdi:download" />
|
|
|
|
|
|
下载
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
v-if="hasAccessByCodes(['mp:material:delete'])"
|
|
|
|
|
|
danger
|
|
|
|
|
|
type="link"
|
|
|
|
|
|
@click="emit('delete', row.id)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<IconifyIcon icon="mdi:delete" />
|
|
|
|
|
|
删除
|
|
|
|
|
|
</Button>
|
2025-11-04 17:32:12 +08:00
|
|
|
|
</template>
|
2025-11-07 13:21:42 +08:00
|
|
|
|
</Grid>
|
2025-11-04 17:32:12 +08:00
|
|
|
|
</template>
|