feat: 新媒体数据看板字段对接

This commit is contained in:
rd
2025-07-04 18:12:23 +08:00
parent 11bc19907c
commit 6404924e29
11 changed files with 627 additions and 100 deletions

View File

@ -44,7 +44,7 @@
.label { .label {
margin-right: 8px; margin-right: 8px;
color: #211f24; color: #211f24;
font-family: 'PuHuiTi-Medium'; font-family: 'PuHuiTi-Regular';
font-size: 14px; font-size: 14px;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;

View File

@ -2,13 +2,167 @@
* @Author: RenXiaoDong * @Author: RenXiaoDong
* @Date: 2025-06-28 10:33:06 * @Date: 2025-06-28 10:33:06
*/ */
export const getDefaultColumns = (type = 'week') => {
const isWeek = type === 'week';
const viewChain = isWeek ? 'week_view_chain' : 'month_view_chain';
const likeChain = isWeek ? 'week_like_chain' : 'month_like_chain';
const viewChainText = isWeek ? '近7天观看量环比' : '近30天观看量环比';
const likeChainText = isWeek ? '近7天点赞量环比' : '近30天点赞量环比';
export const CUSTOM_FIELDS = [
{
dataIndex: 'comment_number',
prop: 'comment_number',
title: '评论数',
width: 180,
tooltip: '账号所有内容的评论总数',
align: 'right',
},
{
dataIndex: 'share_number',
prop: 'share_number',
title: '分享数',
width: 180,
tooltip: '账号所有内容的分享总数',
align: 'right',
},
{
dataIndex: 'like_number',
prop: 'like_number',
title: '点赞数',
width: 180,
tooltip: '账号所有内容的点赞总数',
align: 'right',
},
{
dataIndex: 'rise_fans_number',
prop: 'rise_fans_number',
title: '粉丝增长数',
width: 180,
tooltip: '账号所有内容的粉丝增长总数',
align: 'right',
},
{
dataIndex: 'collect_number',
prop: 'collect_number',
title: '收藏数',
width: 180,
tooltip: '账号所有内容的收藏总数',
align: 'right',
},
{
dataIndex: 'view_number',
prop: 'view_number',
title: '浏览数',
width: 180,
tooltip: '账号所有内容的浏览总数',
align: 'right',
},
{
dataIndex: 'avg_view_time',
prop: 'avg_view_time',
title: '平均浏览数',
width: 180,
tooltip: '账号所有内容的平均浏览数',
align: 'right',
},
{
dataIndex: 'home_view_number',
prop: 'home_view_number',
title: '主页浏览数',
width: 180,
tooltip: '账号所有内容的主页浏览数',
align: 'right',
},
{
dataIndex: 'barrage_number',
prop: 'barrage_number',
title: '弹幕数',
width: 180,
tooltip: '账号所有内容的弹幕总数',
align: 'right',
},
{
dataIndex: 'rise_fans_rate',
prop: 'rise_fans_rate',
title: '粉丝增长率',
width: 180,
tooltip: '账号所有内容的粉丝增长率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
dataIndex: 'home_view_rate',
prop: 'home_view_rate',
title: '主页浏览率',
width: 180,
tooltip: '账号所有内容的主页浏览率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
dataIndex: 'share_rate',
prop: 'share_rate',
title: '分享率',
width: 180,
tooltip: '账号所有内容的分享率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
dataIndex: 'collect_rate',
prop: 'collect_rate',
title: '收藏率',
width: 180,
tooltip: '账号所有内容的收藏率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
dataIndex: 'comment_rate',
prop: 'comment_rate',
title: '评论率',
width: 180,
tooltip: '账号所有内容的评论率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
dataIndex: 'avg_view_time_rate',
prop: 'avg_view_time_rate',
title: '平均访问时长增长比率',
width: 180,
tooltip: '账号所有内容的平均访问时长增长比率',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
];
export function getPeriodColumns(type = 'week') {
const prefix = type === 'week' ? 'seven' : 'thirty';
const labelPrefix = type === 'week' ? '近7天' : '近30天';
return CUSTOM_FIELDS.map((item) => ({
...item,
dataIndex: `${prefix}_${item.dataIndex}`,
title: `${labelPrefix}${item.title}`,
prop: `${prefix}_${item.prop}`,
}));
}
export const getDefaultColumns = (type = 'week') => {
return [ return [
{ {
title: '账号名称', title: '账号名称',
@ -65,56 +219,12 @@ export const getDefaultColumns = (type = 'week') => {
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
}, },
}, },
{ ...getPeriodColumns(type),
title: '观看量',
dataIndex: 'view_number',
prop: 'view_number',
width: 180,
tooltip: '账号所有内容的总观看次数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: viewChainText,
dataIndex: viewChain,
prop: viewChain,
width: 180,
tooltip: '相比上一周期的观看量变化百分比',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: '点赞量',
dataIndex: 'like_number',
prop: 'like_number',
width: 180,
tooltip: '账号所有内容的总点赞数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: likeChainText,
dataIndex: likeChain,
prop: likeChain,
width: 180,
tooltip: '相比上一周期的点赞量变化百分比',
align: 'right',
suffix: '%',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{ {
title: '最新内容标题/日期', title: '最新内容标题/日期',
dataIndex: 'newest_work_title_and_publish_time', dataIndex: 'newest_work_title',
prop: 'newest_work_title_and_publish_time', prop: 'newest_work_title',
width: 240, width: 240,
tooltip: '最新发布内容的标题和发布日期', tooltip: '最新发布内容的标题和发布日期',
}, },
@ -130,20 +240,64 @@ export const getDefaultColumns = (type = 'week') => {
}, },
}, },
{ {
title: '最新作品日增长', title: '最新作品点赞数',
dataIndex: 'newest_work_view_grow_number', dataIndex: 'newest_work_like_number',
prop: 'newest_work_view_grow_number', prop: 'newest_work_like_number',
width: 180, width: 180,
tooltip: '最新作品每日观看量的增长情况', tooltip: '最新发布内容的点赞数',
align: 'right', align: 'right',
sortable: { sortable: {
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
}, },
}, },
{
title: '最新作品收藏数',
dataIndex: 'newest_work_collect_number',
prop: 'newest_work_collect_number',
width: 180,
tooltip: '最新发布内容的收藏数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: '最新作品评论数',
dataIndex: 'newest_work_comment_number',
prop: 'newest_work_comment_number',
width: 180,
tooltip: '最新发布内容的评论数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: '最新作品分享数',
dataIndex: 'newest_work_share_number',
prop: 'newest_work_share_number',
width: 180,
tooltip: '最新发布内容的分享数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
// {
// title: '最新作品日增长',
// dataIndex: 'newest_work_view_grow_number',
// prop: 'newest_work_view_grow_number',
// width: 180,
// tooltip: '最新作品每日观看量的增长情况',
// align: 'right',
// sortable: {
// sortDirections: ['ascend', 'descend'],
// },
// },
{ {
title: '次新内容标题/日期', title: '次新内容标题/日期',
dataIndex: 'second_new_work_title_and_publish_time', dataIndex: 'second_new_work_title',
prop: 'second_new_work_title_and_publish_time', prop: 'second_new_work_title',
width: 240, width: 240,
}, },
{ {
@ -158,16 +312,49 @@ export const getDefaultColumns = (type = 'week') => {
}, },
}, },
{ {
title: '次新作品日增长', title: '次新作品点赞数',
dataIndex: 'second_new_work_view_grow_number', dataIndex: 'second_new_work_like_number',
prop: 'second_new_work_view_grow_number', prop: 'second_new_work_like_number',
width: 180, width: 180,
tooltip: '倒数第二个作品每日观看量的增长情况', tooltip: '倒数第二个发布内容的点赞数',
align: 'right', align: 'right',
sortable: { sortable: {
sortDirections: ['ascend', 'descend'], sortDirections: ['ascend', 'descend'],
}, },
}, },
{
title: '次新作品评论数',
dataIndex: 'second_new_work_comment_number',
prop: 'second_new_work_comment_number',
width: 180,
tooltip: '倒数第二个发布内容的评论数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
{
title: '次新作品分享数',
dataIndex: 'second_new_work_share_number',
prop: 'second_new_work_share_number',
width: 180,
tooltip: '倒数第二个发布内容的分享数',
align: 'right',
sortable: {
sortDirections: ['ascend', 'descend'],
},
},
// {
// title: '次新作品日增长',
// dataIndex: 'second_new_work_view_grow_number',
// prop: 'second_new_work_view_grow_number',
// width: 180,
// tooltip: '倒数第二个作品每日观看量的增长情况',
// align: 'right',
// sortable: {
// sortDirections: ['ascend', 'descend'],
// },
// },
{ {
title: '操作', title: '操作',
dataIndex: 'operation', dataIndex: 'operation',

View File

@ -32,7 +32,11 @@
ref="tableRef" ref="tableRef"
:data="dataSource" :data="dataSource"
row-key="id" row-key="id"
:row-selection="rowSelection" :row-selection="{
type: 'checkbox',
showCheckedAll: true,
width: 48,
}"
:selected-keys="selectedItems" :selected-keys="selectedItems"
:pagination="false" :pagination="false"
:scroll="{ x: '100%' }" :scroll="{ x: '100%' }"
@ -113,14 +117,17 @@
{{ formatTableField(column, record) }} {{ formatTableField(column, record) }}
</div> </div>
</template> </template>
<template <template v-else-if="column.dataIndex === 'newest_work_title'" #cell="{ record }">
v-else-if=" <p class="cts cursor-pointer hover:!color-#6D4CFE">{{ record.newest_work_title }}</p>
['newest_work_title_and_publish_time', 'second_new_work_title_and_publish_time'].includes(column.dataIndex) <p class="cts text-12px lh-20px !color-#939499">
" {{ exactFormatTime(record.newest_work_published_at) }}
#cell="{ record }" </p>
> </template>
<p class="cts cursor-pointer hover:!color-#6D4CFE">打工人的环游世界旅行计划(国内版)</p> <template v-else-if="column.dataIndex === 'second_new_work_title'" #cell="{ record }">
<p class="cts text-12px lh-20px !color-#939499">2025-06-18</p> <p class="cts cursor-pointer hover:!color-#6D4CFE">{{ record.second_new_work_title }}</p>
<p class="cts text-12px lh-20px !color-#939499">
{{ exactFormatTime(record.second_new_work_published_at) }}
</p>
</template> </template>
<template v-else #cell="{ record }"> <template v-else #cell="{ record }">
@ -130,7 +137,12 @@
</template> </template>
</a-table> </a-table>
<CustomTableColumnModal ref="customTableColumnModalRef" :type="CUSTOM_COLUMN_TYPE" @success="onCustomColumnSuccess" /> <CustomTableColumnModal
ref="customTableColumnModalRef"
:type="CUSTOM_COLUMN_TYPE"
:dateType="dateType"
@success="onCustomColumnSuccess"
/>
</template> </template>
<script setup> <script setup>
@ -139,9 +151,9 @@ import { useRouter } from 'vue-router';
import { getCustomColumns } from '@/api/all/common'; import { getCustomColumns } from '@/api/all/common';
import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants'; import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants';
import { formatTableField, formatNumberShow } from '@/utils/tools'; import { formatTableField, formatNumberShow, exactFormatTime } from '@/utils/tools';
import { getDefaultColumns } from './constants'; import { getDefaultColumns } from './constants';
import CustomTableColumnModal from '@/components/custom-table-column-modal'; import CustomTableColumnModal from '../custom-column-modal';
import icon1 from '@/assets/img/media-account/icon-custom.png'; import icon1 from '@/assets/img/media-account/icon-custom.png';
import icon2 from '@/assets/img/media-account/icon-warn.png'; import icon2 from '@/assets/img/media-account/icon-warn.png';
@ -154,6 +166,10 @@ const props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
query: {
type: Object,
default: () => {},
},
}); });
const emit = defineEmits(['selectionChange', 'sorterChange', 'export']); const emit = defineEmits(['selectionChange', 'sorterChange', 'export']);
@ -173,15 +189,12 @@ const checkedAll = computed(
const indeterminate = computed( const indeterminate = computed(
() => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length, () => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length,
); );
const dateType = computed(() => (props.query.type === 7 ? 'week' : 'month'));
const rowSelection = computed(() => ({
type: 'checkbox',
showCheckedAll: true,
}));
const tableColumns = computed(() => { const tableColumns = computed(() => {
const _result = []; const _result = [];
const _columns = getDefaultColumns(); const _columns = getDefaultColumns(dateType.value);
selectedColumns.value.forEach((item) => { selectedColumns.value.forEach((item) => {
const _column = _columns.find((_item) => _item.prop === item); const _column = _columns.find((_item) => _item.prop === item);
if (_column) { if (_column) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

View File

@ -0,0 +1,218 @@
<!--
* @Author: RenXiaoDong
* @Date: 2025-06-30 10:54:49
-->
<template>
<a-modal
v-model:visible="visible"
title="自定义列"
width="960px"
unmountOnClose
titleAlign="start"
class="custom-table-column-modal-98"
@close="close"
>
<div class="modal-body">
<!-- 左侧分组 -->
<div class="left">
<div v-for="group in dataSource" :key="group.label" class="group-item">
<div class="title-row">
<span class="text">{{ group.label }}</span>
</div>
<div class="fields">
<a-checkbox
v-for="option in group.columns"
:key="option.value"
:model-value="isCheck(option)"
:value="option.value"
:disabled="option.is_require === ENUM_STATUS.NO"
@change="(checked) => onCheckChange(checked, option)"
>
{{ option.label }}
</a-checkbox>
</div>
</div>
</div>
<!-- 右侧已选 -->
<div class="right">
<span class="checked-title mb-16px">
已添加<span class="count">{{ checkColumns.length }}</span>
</span>
<div class="checked-list">
<div v-for="(groupName, index) in requiredGroupNames" :key="index" class="checked-item !cursor-default">
<div class="flex items-center">
<img :src="icon1" alt="icon" class="mr-8px" width="16" height="16" />
<span>{{ groupName }}</span>
</div>
</div>
<VueDraggable v-model="checkColumns">
<div
v-for="item in checkColumns"
:key="item"
class="checked-item justify-between"
:class="isRequiredColumn(item) ? '!display-none' : ''"
>
<div class="flex items-center">
<icon-menu size="16" class="mr-8px" />
<span>{{ getCheckColumnLabel(item) }}</span>
</div>
<icon-close size="16" class="color-#737478 cursor-pointer" @click="removeCheckedField(item)" />
</div>
</VueDraggable>
</div>
</div>
</div>
<template #footer>
<div style="text-align: right">
<a-button class="mr-8px cancel-btn" size="medium" @click="close">取消</a-button>
<a-button type="primary" size="medium" @click="onSubmit">确定</a-button>
</div>
</template>
</a-modal>
</template>
<script setup>
import { ref, defineExpose } from 'vue';
import { VueDraggable } from 'vue-draggable-plus';
import { getCustomColumns, updateCustomColumns } from '@/api/all/common';
import { CUSTOM_FIELDS } from '../account-table/constants';
import icon1 from './img/icon-lock.png';
const props = defineProps({
type: {
type: String,
default: '',
required: true,
},
dateType: {
type: String,
default: 'week',
},
});
const emit = defineEmits(['success']);
const ENUM_STATUS = {
YES: 0,
NO: 1,
};
const visible = ref(false);
const dataSource = ref([]);
const checkColumns = ref([]); // 选中字段
const allColumns = ref([]); // 所有字段
const requiredGroupNames = ref([]); // 必选分组名称
const open = () => {
initData();
visible.value = true;
};
const close = () => {
visible.value = false;
dataSource.value = [];
checkColumns.value = [];
allColumns.value = [];
requiredGroupNames.value = [];
};
const initData = async () => {
const { code, data } = await getCustomColumns({ type: props.type });
if (code === 200) {
const { selected_columns, groups } = data;
dataSource.value = groups;
formatDataSource();
setDefaultCheckColumns(groups, selected_columns);
allColumns.value = groups.flatMap((group) => group.columns);
}
};
// 过滤近7天/近30天字段
const formatDataSource = () => {
const prefix = props.dateType === 'week' ? 'seven_' : 'thirty_';
dataSource.value.forEach((group) => {
group.columns = group.columns.filter((item) => {
if (item.value.startsWith('seven_') || item.value.startsWith('thirty_')) {
return item.value.startsWith(prefix);
}
return true;
});
});
};
const isCheck = (option) => {
return checkColumns.value.includes(option.value);
};
const getCheckColumnLabel = (value) => {
const column = allColumns.value.find((column) => column.value === value);
return column?.label;
};
const isRequiredColumn = (value) => {
const column = allColumns.value.find((column) => column.value === value);
return column?.is_require === 1;
};
const removeCheckedField = (value) => {
checkColumns.value = checkColumns.value.filter((column) => column !== value);
};
// 勾选/取消
const onCheckChange = (checked, option) => {
if (checked) {
checkColumns.value.push(option.value);
} else {
checkColumns.value = checkColumns.value.filter((item) => item !== option.value);
}
};
// 提交
const onSubmit = async () => {
const result = checkColumns.value
.map((item) => {
if (item.startsWith('thirty_')) {
return [item, item.replace('thirty_', 'seven_')];
} else if (item.startsWith('seven_')) {
return [item, item.replace('seven_', 'thirty_')];
} else {
return item;
}
})
.flat();
const { code } = await updateCustomColumns({ type: props.type, selected_columns: result });
if (code === 200) {
emit('success', result);
close();
}
};
const setDefaultCheckColumns = (groups, selected_columns) => {
const prefix = props.dateType === 'week' ? 'seven_' : 'thirty_';
const requiredGroups = groups.filter((group) => group.is_require === 1);
const requiredValues = requiredGroups
.flatMap((group) => (group.columns || []).filter((col) => col.is_require === 1))
.map((col) => col.value);
const filteredSelected = selected_columns.filter(
(col) => (!col.startsWith('seven_') && !col.startsWith('thirty_')) || col.startsWith(prefix),
);
const merged = union(requiredValues, filteredSelected);
checkColumns.value = merged;
requiredGroupNames.value = requiredGroups.map((group) => group.label);
};
// 暴露方法
defineExpose({ open });
</script>
<style lang="scss">
@import './style.scss';
</style>

View File

@ -0,0 +1,99 @@
.custom-table-column-modal-98 {
.arco-modal-body {
.modal-body {
height: 504px;
border-radius: 8px;
border: 1px solid var(--BG-300, #e6e6e8);
display: flex;
flex-direction: row;
.left {
flex: 1;
padding: 20px;
border-right: 1px solid #eee;
overflow-y: auto;
.group-item {
.title-row {
border-radius: 4px;
background: var(--BG-100, #f7f8fa);
display: flex;
height: 44px;
padding: 0px 12px;
align-items: center;
margin-bottom: 16px;
.text {
color: var(--Text-1, #211f24);
font-family: 'PuHuiTi-Medium';
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px; /* 150% */
}
}
.fields {
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
&:not(:last-child) {
margin-bottom: 24px;
}
}
}
.right {
width: 280px;
padding: 16px 12px;
display: flex;
flex-direction: column;
.checked-title {
color: var(--Text-1, #211f24);
font-family: 'PuHuiTi-Medium';
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
.count {
font-weight: 500;
}
}
.checked-list {
flex: 1;
overflow-y: auto;
.checked-item {
cursor: move;
border-radius: 4px;
background: var(--BG-100, #f7f8fa);
display: flex;
height: 32px;
padding: 0px 12px;
align-items: center;
.text {
color: var(--Text-1, #211f24);
font-family: 'PuHuiTi-Medium';
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px; /* 157.143% */
}
&:not(:last-child) {
margin-bottom: 12px;
}
}
.draggable-list {
min-height: 40px;
}
}
}
}
}
.arco-modal-footer {
.cancel-btn {
border-radius: 4px;
border: 1px solid var(--BG-500, #b1b2b5);
background: var(--BG-white, #fff);
&:hover {
border: 1px solid var(--BG-500, #b1b2b5);
}
}
}
}

View File

@ -5,7 +5,7 @@
--> -->
<template> <template>
<div class="container"> <div class="container">
<div class="filter-row flex"> <div class="filter-row flex mb-20px">
<div class="filter-row-item flex items-center"> <div class="filter-row-item flex items-center">
<span class="label">账号名称</span> <span class="label">账号名称</span>
<a-space size="medium" class="w-240px"> <a-space size="medium" class="w-240px">
@ -34,7 +34,19 @@
<OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" /> <OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" />
</a-space> </a-space>
</div> </div>
</div>
<div class="filter-row flex">
<div class="filter-row-item flex items-center">
<span class="label">时间筛选</span>
<a-space class="w-240px">
<a-select v-model="query.type" size="medium" placeholder="全部" class="w-120px" @change="handleSearch">
<template #arrow-icon> <icon-calendar size="16" /> </template>
<a-option :value="7" label="近7天">近7天</a-option>
<!-- <a-option :value="14" label="近14天">近14天</a-option> -->
<a-option :value="30" label="近30天">近30天</a-option>
</a-select>
</a-space>
</div>
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch"> <a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
<template #icon> <template #icon>
<icon-search /> <icon-search />

View File

@ -1,8 +1,7 @@
/* /*
* @Author: RenXiaoDong * @Author: RenXiaoDong
* @Date: 2025-06-27 17:23:56 * @Date: 2025-07-04 15:50:37
*/ */
import icon1 from '@/assets/img/media-account/icon1.png'; import icon1 from '@/assets/img/media-account/icon1.png';
import icon2 from '@/assets/img/media-account/icon2.png'; import icon2 from '@/assets/img/media-account/icon2.png';
import icon3 from '@/assets/img/media-account/icon3.png'; import icon3 from '@/assets/img/media-account/icon3.png';
@ -39,7 +38,7 @@ export const INITIAL_QUERY = {
status: '', status: '',
operator_id: '', operator_id: '',
group_ids: [], group_ids: [],
// date_range: '', type: 7,
column: '', column: '',
order: '', order: '',
}; };

View File

@ -36,6 +36,7 @@
<AccountTable <AccountTable
ref="accountTableRef" ref="accountTableRef"
:dataSource="dataSource" :dataSource="dataSource"
:query="query"
@selectionChange="handleSelectionChange" @selectionChange="handleSelectionChange"
@export="handleExport" @export="handleExport"
@sorterChange="handleSorterChange" @sorterChange="handleSorterChange"

View File

@ -33,7 +33,11 @@
ref="tableRef" ref="tableRef"
:data="dataSource" :data="dataSource"
row-key="id" row-key="id"
:row-selection="rowSelection" :row-selection="{
type: 'checkbox',
showCheckedAll: true,
width: 48,
}"
:selected-keys="selectedItems" :selected-keys="selectedItems"
:pagination="false" :pagination="false"
:scroll="{ x: '100%' }" :scroll="{ x: '100%' }"
@ -173,11 +177,6 @@ const indeterminate = computed(
() => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length, () => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length,
); );
const rowSelection = computed(() => ({
type: 'checkbox',
showCheckedAll: true,
}));
const handleSelectAll = (checked) => { const handleSelectAll = (checked) => {
if (checked) { if (checked) {
selectedItems.value = props.dataSource.map((item) => item.id); selectedItems.value = props.dataSource.map((item) => item.id);

View File

@ -33,7 +33,11 @@
ref="tableRef" ref="tableRef"
:data="dataSource" :data="dataSource"
row-key="id" row-key="id"
:row-selection="rowSelection" :row-selection="{
type: 'checkbox',
showCheckedAll: true,
width: 48,
}"
:selected-keys="selectedItems" :selected-keys="selectedItems"
:pagination="false" :pagination="false"
:scroll="{ x: '100%' }" :scroll="{ x: '100%' }"
@ -173,11 +177,6 @@ const indeterminate = computed(
() => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length, () => selectedItems.value.length > 0 && selectedItems.value.length < props.dataSource.length,
); );
const rowSelection = computed(() => ({
type: 'checkbox',
showCheckedAll: true,
}));
const handleSelectAll = (checked) => { const handleSelectAll = (checked) => {
if (checked) { if (checked) {
selectedItems.value = props.dataSource.map((item) => item.id); selectedItems.value = props.dataSource.map((item) => item.id);