| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- <template>
- <div>
- <el-button type="primary" @click="dialogVisible = true">选择轮播组</el-button>
- <div v-if="showSelected && selectedGroup" class="selected-group">
- <el-tag closable @close="removeGroup" style="margin: 2px">
- {{ selectedGroup.name }}
- </el-tag>
- </div>
- <el-dialog title="选择轮播组" v-model="dialogVisible" width="900px" append-to-body>
- <el-form :inline="true" :model="queryParams" class="mb-2">
- <el-form-item label="名称">
- <el-input v-model="queryParams.itemName" placeholder="轮播组名称" clearable style="width: 180px"
- @keyup.enter="getCarouselList" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getCarouselList">搜索</el-button>
- </el-form-item>
- </el-form>
- <el-table v-loading="dialogLoading" :data="carouselList" @row-click="handleRowClick" highlight-current-row>
- <el-table-column width="50">
- <template #default="{ row }">
- <el-checkbox v-model="row.selected" @click.stop @change="handleSelectChange(row)" />
- </template>
- </el-table-column>
- <el-table-column prop="name" label="轮播组名称" min-width="150" />
- <el-table-column prop="itemCount" label="轮播项数量" width="100" />
- <el-table-column prop="duration" label="轮播间隔(秒)" width="120" />
- <el-table-column prop="createTime" label="创建时间" width="180" />
- </el-table>
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize" @pagination="getCarouselList" />
- <template #footer>
- <el-button @click="dialogVisible = false">取消</el-button>
- <el-button type="primary" @click="confirmSelect">确定</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, watch, defineProps, defineEmits, nextTick } from 'vue';
- import { listItem } from '@/api/smsb/source/item';
- import type { ItemVO, ItemQuery } from '@/api/smsb/source/item_type';
- export interface CarouselGroup {
- id: string | number;
- name: string;
- itemCount: number;
- duration: number;
- createTime: string;
- items: any[];
- selected?: boolean;
- [key: string]: any; // Allow additional properties
- }
- const props = defineProps<{
- modelValue: string;
- showSelected?: boolean;
- }>();
- const emit = defineEmits(['update:modelValue']);
- const dialogVisible = ref(false);
- const dialogLoading = ref(false);
- const carouselList = ref<CarouselGroup[]>([]);
- const total = ref(0);
- const currentRow = ref<CarouselGroup | null>(null);
- const selectedGroup = ref<CarouselGroup | null>(null);
- // 定义查询参数类型
- interface CarouselQuery extends ItemQuery {
- pageNum: number;
- pageSize: number;
- itemName: string;
- itemType: number;
- }
- const queryParams = ref<CarouselQuery>({
- pageNum: 1,
- pageSize: 10,
- itemName: '',
- itemType: 1 // 1表示轮播组类型
- });
- // 初始化时,如果有值,反序列化
- watch(
- () => props.modelValue,
- (val) => {
- if (val) {
- try {
- // 使用 JSON.parse 的 reviver 函数确保大数 ID 保持为字符串
- const parsedValue = JSON.parse(val, (key, value) => {
- // 如果键是 id,确保它作为字符串返回
- if (key === 'id' && value !== null && value !== undefined) {
- return String(value);
- }
- return value;
- });
- // 确保 id 是字符串
- const id = parsedValue.id ? String(parsedValue.id) : '';
- selectedGroup.value = {
- id: id,
- name: String(parsedValue.name || ''),
- itemCount: Number(parsedValue.itemCount) || 0,
- duration: Number(parsedValue.duration) || 5,
- createTime: String(parsedValue.createTime || ''),
- items: Array.isArray(parsedValue.items) ? parsedValue.items : []
- };
- } catch (error) {
- console.error('Error parsing modelValue:', error);
- selectedGroup.value = null;
- }
- } else {
- selectedGroup.value = null;
- }
- },
- { immediate: true, deep: true }
- );
- // 查询轮播组列表
- const getCarouselList = async () => {
- dialogLoading.value = true;
- try {
- // 构建查询参数,确保类型安全
- const query: ItemQuery = {
- itemName: queryParams.value.itemName,
- itemType: 1, // 1表示轮播组类型
- pageNum: queryParams.value.pageNum,
- pageSize: queryParams.value.pageSize
- };
- const res = await listItem(query);
- // 转换数据格式,并标记已选中的项,确保 ID 是字符串
- carouselList.value = (res.rows || []).map((item: ItemVO) => {
- // 确保 ID 是字符串,避免大数精度问题
- const itemId = item.id ? String(item.id) : '';
- const isSelected = selectedGroup.value?.id === itemId;
- return {
- id: itemId,
- name: item.itemName || '',
- itemName: item.itemName || '', // 保持与API返回的字段名一致
- itemCount: item.sourceNum || 0,
- duration: 5, // 默认5秒,可以根据实际需求调整
- createTime: item.createTime || '',
- selected: isSelected,
- items: [] // 不需要在UI中显示,仅用于内部处理
- };
- });
- // 如果当前有选中的组,确保它在列表中也被选中
- if (selectedGroup.value?.id) {
- const selectedItem = carouselList.value.find((item) => item.id === selectedGroup.value?.id);
- if (selectedItem) {
- selectedItem.selected = true;
- currentRow.value = selectedItem;
- }
- }
- total.value = res.total || 0;
- } finally {
- dialogLoading.value = false;
- }
- };
- // 行点击
- const handleRowClick = (row: CarouselGroup) => {
- currentRow.value = row;
- };
- // 处理选择变化
- const handleSelectChange = (row: CarouselGroup) => {
- if (row.selected) {
- // 只允许单选,取消其他项
- carouselList.value.forEach((item) => {
- if (item !== row) item.selected = false;
- });
- currentRow.value = row;
- } else {
- // 当前项取消选中
- currentRow.value = null;
- }
- };
- // 选择轮播组
- const selectGroup = (row: CarouselGroup) => {
- row.selected = true;
- handleSelectChange(row);
- confirmSelect();
- };
- // 移除已选轮播组
- const removeGroup = () => {
- selectedGroup.value = null;
- emit('update:modelValue', '');
- };
- // 确认选择
- const confirmSelect = () => {
- console.log('confirmSelect called, currentRow:', currentRow.value);
- if (!currentRow.value) {
- // 无选中项,清除选中
- console.log('No row selected, clearing selection');
- selectedGroup.value = null;
- emit('update:modelValue', '');
- dialogVisible.value = false;
- return;
- }
- // 保持ID为字符串,避免精度丢失
- const id = String(currentRow.value.id);
- console.log('Selected group ID (as string):', id, 'Type:', typeof id);
- if (!id) {
- console.error('Invalid group ID:', currentRow.value.id);
- return;
- }
- // 只存储 id 和 name 字段,确保id是字符串
- const selectedData = {
- id: id, // 已经是字符串
- name: String(currentRow.value.name || '') // 确保name是字符串
- };
- console.log('Emitting selected data:', selectedData);
- selectedGroup.value = selectedData;
- // 更新所有行的选中状态
- carouselList.value.forEach((item) => {
- item.selected = String(item.id) === id; // 确保比较时类型一致
- });
- emit('update:modelValue', JSON.stringify(selectedData));
- dialogVisible.value = false;
- };
- // 弹窗首次打开时自动加载
- watch(dialogVisible, (val) => {
- if (val) getCarouselList();
- });
- </script>
- <style scoped>
- .selected-group {
- margin-top: 8px;
- }
- </style>
|