Files
cashier_app/components/goods-table.vue
2026-03-28 18:07:30 +08:00

147 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="table u-font-28">
<!-- 表头根据 columns 渲染 + 全选框 -->
<view class="u-flex u-row-between no-wrap title">
<!-- 全选框 -->
<view class="table-th">
<up-checkbox @change="handleSelectAll" usedAlone v-model:checked="internalAllChecked" shape="square" :size="20" />
</view>
<!-- 动态列标题 -->
<view class="table-th" v-for="col in columns" :key="col.key" :style="col.style || {}">
{{ col.title }}
</view>
</view>
<!-- 表格行 -->
<view @click="handleRowCheck(item)" class="u-m-t-12 u-flex u-p-24 u-row-between row"
v-for="(item, index) in internalData" :key="item.id || index" row-key="id">
<!-- 单选框 -->
<view class="table-td">
<up-checkbox
usedAlone
v-model:checked="item._checked" shape="square" :size="20" @change="handleRowCheck(item)"></up-checkbox>
</view>
<!-- 动态列内容 -->
<view class="table-td" v-for="col in columns" :key="col.key" :style="col.style || {}">
<!-- 支持自定义渲染 / 直接取值 -->
<slot v-if="col.slot" :name="col.slot" :row="item" />
<template v-else>
{{ item[col.key] }}
</template>
</view>
</view>
</view>
</template>
<script setup>
import {
ref,
computed,
watch
} from 'vue';
// 完全对齐 u-table2 的 props
const props = defineProps({
data: {
type: Array,
default: () => []
},
columns: {
type: Array,
default: () => []
},
rowKey: {
type: String,
default: 'id'
}
});
// 抛出和 u-table2 一样的 selection-change 事件
const emits = defineEmits(['selection-change']);
// 内部数据(增加选中状态 _checked
const internalData = ref([]);
// 全选状态
const internalAllChecked = ref(false);
// 监听外部 data 变化,自动注入选中状态
watch(
() => props.data,
(val) => {
internalData.value = val.map(item => ({
...item,
_checked: item._checked || false
}));
}, {
immediate: true,
deep: true
}
);
// 全选切换
function handleSelectAll() {
const checked = internalAllChecked.value;
internalData.value=internalData.value.map(item=>{
item._checked = checked;
return item;
})
console.log('internalData.value',internalData.value);
emitChange();
}
// 行选中切换
function handleRowCheck(row) {
row._checked = !row._checked;
emitChange();
}
// 抛出选中结果(和 u-table2 行为一致)
function emitChange() {
const selectedRows = internalData.value.filter(item => item._checked);
emits('selection-change', selectedRows);
}
// 监听所有行选中状态,自动更新全选框
watch(
() => internalData.value,
() => {
const total = internalData.value.length;
const checkedCount = internalData.value.filter(i => i._checked).length;
internalAllChecked.value = total > 0 && checkedCount === total;
}, {
deep: true
}
);
</script>
<style lang="scss">
.table {
background: #f9f9f9;
border-radius: 8rpx;
overflow: hidden;
.title {
padding: 12rpx 24rpx;
background: #aebad2;
border-radius: 8rpx 8rpx 0 0;
color: #fff;
}
.table-th,
.table-td {
flex: 1;
text-align: center;
}
.row {
cursor: pointer;
}
.row:nth-of-type(2n + 1) {
background: #f0f0f0;
}
}
</style>