# TableColumnControl 快速开始指南

## 简介

`TableColumnControl` 是一个通用的表格列控制组件，支持：

- ✅ 列的显示/隐藏控制
- ✅ 列的拖拽排序
- ✅ 配置的自动保存和恢复（基于路由）
- ✅ 两种使用方式：自动提取或手动配置

## 快速集成（3 步）

### 步骤 1: 在页面中引入组件

```vue
<script setup lang="ts">
import { ref } from 'vue';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
import type { TableInstance } from 'element-plus';

const tableRef = ref<TableInstance>();
</script>
```

### 步骤 2: 添加列设置按钮

```vue
<template>
	<div>
		<!-- 列设置按钮（放在表格上方） -->
		<right-toolbar>
			<TableColumnControl :table-ref="tableRef" trigger-circle>
				<template #trigger>
					<el-tooltip content="列设置" placement="top">
						<el-button circle style="margin-left: 0;">
							<el-icon><Menu /></el-icon>
						</el-button>
					</el-tooltip>
				</template>
			</TableColumnControl>
		</right-toolbar>

		<!-- 表格 -->
		<el-table ref="tableRef" :data="tableData">
			<el-table-column prop="name" label="姓名" />
			<el-table-column prop="age" label="年龄" />
			<el-table-column prop="email" label="邮箱" />
			<el-table-column label="操作" fixed="right">
				<template #default="scope">
					<el-button @click="handleEdit(scope.row)">编辑</el-button>
				</template>
			</el-table-column>
		</el-table>
	</div>
</template>
```

### 步骤 3: 完成！

就这么简单！组件会自动：

- 从表格中提取列配置
- 根据当前路由自动生成存储 key
- 保存和恢复用户的列设置

## 手动配置方式（可选）

如果你的表格列是动态生成的，或者需要自定义列配置，可以使用手动配置：

```vue
<template>
	<div>
		<right-toolbar>
			<TableColumnControl :columns="tableColumns" v-model="visibleColumns" trigger-circle>
				<template #trigger>
					<el-tooltip content="列设置" placement="top">
						<el-button circle>
							<el-icon><Menu /></el-icon>
						</el-button>
					</el-tooltip>
				</template>
			</TableColumnControl>
		</right-toolbar>

		<el-table :data="tableData">
			<el-table-column
				v-for="col in sortedTableColumns"
				v-if="checkColumnVisible(col.prop || '')"
				:key="col.prop"
				:prop="col.prop"
				:label="col.label"
			/>
		</el-table>
	</div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';

const route = useRoute();
const visibleColumns = ref<string[]>([]);
const columnOrder = ref<string[]>([]);

const tableColumns = [
	{ prop: 'name', label: '姓名' },
	{ prop: 'age', label: '年龄' },
	{ prop: 'email', label: '邮箱' },
	{ prop: 'action', label: '操作', fixed: true, alwaysShow: true },
];

// 检查列是否可见
const checkColumnVisible = (prop: string): boolean => {
	if (visibleColumns.value.length === 0) return true;
	return visibleColumns.value.includes(prop);
};

// 排序后的列
const sortedTableColumns = computed(() => {
	if (columnOrder.value.length === 0) return tableColumns;

	const ordered: typeof tableColumns = [];
	const unordered: typeof tableColumns = [];

	columnOrder.value.forEach((key) => {
		const col = tableColumns.find((c) => (c.prop || c.label) === key);
		if (col) ordered.push(col);
	});

	tableColumns.forEach((col) => {
		const key = col.prop || col.label;
		if (!columnOrder.value.includes(key)) {
			unordered.push(col);
		}
	});

	return [...ordered, ...unordered];
});

// 加载保存的配置
const loadSavedConfig = () => {
	const routePath = route.path.replace(/^\//, '').replace(/\//g, '-');
	const storageKey = `table-columns-${routePath}`;
	const saved = localStorage.getItem(storageKey);

	if (saved) {
		try {
			const savedColumns = JSON.parse(saved);
			const validColumns = tableColumns.filter((col) => !col.alwaysShow && !col.fixed).map((col) => col.prop || col.label);
			const filteredSaved = savedColumns.filter((col: string) => validColumns.includes(col));

			if (filteredSaved.length > 0) {
				visibleColumns.value = filteredSaved;
			} else {
				visibleColumns.value = validColumns;
			}
		} catch (e) {
			visibleColumns.value = tableColumns.filter((col) => !col.alwaysShow && !col.fixed).map((col) => col.prop || col.label);
		}
	} else {
		visibleColumns.value = tableColumns.filter((col) => !col.alwaysShow && !col.fixed).map((col) => col.prop || col.label);
	}

	// 加载排序
	const orderKey = `${storageKey}-order`;
	const savedOrder = localStorage.getItem(orderKey);
	if (savedOrder) {
		try {
			columnOrder.value = JSON.parse(savedOrder);
		} catch (e) {
			columnOrder.value = tableColumns.filter((col) => !col.alwaysShow && !col.fixed).map((col) => col.prop || col.label);
		}
	} else {
		columnOrder.value = tableColumns.filter((col) => !col.alwaysShow && !col.fixed).map((col) => col.prop || col.label);
	}
};

// 监听列变化
const handleColumnChange = (columns: string[]) => {
	visibleColumns.value = columns;
	const routePath = route.path.replace(/^\//, '').replace(/\//g, '-');
	const storageKey = `table-columns-${routePath}`;
	const selectableColumns = columns.filter((col) => {
		const column = tableColumns.find((c) => (c.prop || c.label) === col);
		return column && !column.alwaysShow && !column.fixed;
	});
	localStorage.setItem(storageKey, JSON.stringify(selectableColumns));
};

// 监听列排序变化
const handleColumnOrderChange = (order: string[]) => {
	columnOrder.value = order;
	const routePath = route.path.replace(/^\//, '').replace(/\//g, '-');
	const storageKey = `table-columns-${routePath}-order`;
	localStorage.setItem(storageKey, JSON.stringify(order));
};

// 立即加载配置
loadSavedConfig();
</script>
```

## 使用 Composable（推荐）

为了简化手动配置方式，可以使用 `useTableColumnControl` composable：

```vue
<script setup lang="ts">
import { computed } from 'vue';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
import { useTableColumnControl } from '/@/composables/useTableColumnControl';

const tableColumns = [
	{ prop: 'name', label: '姓名' },
	{ prop: 'age', label: '年龄' },
	{ prop: 'email', label: '邮箱' },
	{ prop: 'action', label: '操作', fixed: true, alwaysShow: true },
];

const { visibleColumns, columnOrder, checkColumnVisible, saveColumnConfig, saveColumnOrder } = useTableColumnControl({
	columns: tableColumns,
});

const sortedTableColumns = computed(() => {
	// ... 排序逻辑
});
</script>
```

## 常见问题

### Q: 如何自定义存储 key？

```vue
<TableColumnControl :table-ref="tableRef" storage-key="my-custom-key" />
```

### Q: 如何设置始终显示的列？

```vue
<TableColumnControl
	:table-ref="tableRef"
	:auto-extract-options="{
		alwaysShow: ['name', 'action'],
	}"
/>
```

### Q: 如何设置默认隐藏的列？

```vue
<TableColumnControl
	:table-ref="tableRef"
	:auto-extract-options="{
		defaultHidden: ['remark', 'description'],
	}"
/>
```

### Q: 固定列会自动隐藏吗？

不会。使用 `fixed="left"` 或 `fixed="right"` 的列会自动标记为不可隐藏。

## 完整示例

查看 `src/views/stuwork/classroomhygienemonthly/index.vue` 了解完整的使用示例。
