fixbug: 🐛 表格拖拽排序列,重置和点击不显示无反应
This commit is contained in:
parent
7ab9f084ed
commit
f097ab32b6
|
@ -12,7 +12,11 @@ export default {
|
|||
"subject-empty": [2, "never"],
|
||||
"type-empty": [2, "never"],
|
||||
"subject-case": [0],
|
||||
"type-enum": [2, "always", ["init", "optimize", "feat", "fix", "media", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert", "wip", "workflow", "types", "release"]]
|
||||
"type-enum": [
|
||||
2,
|
||||
"always",
|
||||
["init", "optimize", "feat", "fix", "fixbug", "media", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert", "wip", "workflow", "types", "release"]
|
||||
]
|
||||
},
|
||||
prompt: {
|
||||
messages: {
|
||||
|
@ -35,6 +39,7 @@ export default {
|
|||
{ value: "fix", name: "修复: 🧩 修复缺陷", emoji: "🧩" },
|
||||
{ value: "docs", name: "文档: 📚 文档变更", emoji: "📚" },
|
||||
{ value: "style", name: "格式: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: "🎨" },
|
||||
{ value: "fixbug", name: "bug: 🐛 修改bug", emoji: "🐛" },
|
||||
{ value: "refactor", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: "♻️" },
|
||||
{ value: "perf", name: "性能: ⚡️ 性能优化", emoji: "⚡️" },
|
||||
{ value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: "✅" },
|
||||
|
|
|
@ -19,6 +19,7 @@ buttons:
|
|||
pureBackTop: BackTop
|
||||
pureOpenText: Open
|
||||
pureCloseText: Close
|
||||
rest: Rest
|
||||
search:
|
||||
pureTotal: Total
|
||||
pureHistory: History
|
||||
|
@ -233,3 +234,7 @@ login:
|
|||
purePassWordUpdateReg: Password has been updated
|
||||
table:
|
||||
tableNumber: Table Number
|
||||
style:
|
||||
larger: Larger
|
||||
default: Default
|
||||
small: Small
|
||||
|
|
|
@ -19,6 +19,7 @@ buttons:
|
|||
pureBackTop: 回到顶部
|
||||
pureOpenText: 开
|
||||
pureCloseText: 关
|
||||
rest: 重置
|
||||
search:
|
||||
pureTotal: 共
|
||||
pureHistory: 搜索历史
|
||||
|
@ -233,3 +234,7 @@ login:
|
|||
purePassWordUpdateReg: 修改密码成功
|
||||
table:
|
||||
tableNumber: 序号
|
||||
style:
|
||||
larger: 宽松
|
||||
default: 默认
|
||||
small: 紧凑
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<template>
|
||||
<div class="main main-content">
|
||||
<div class="main">
|
||||
<!-- 表单设置,外加插槽 -->
|
||||
<el-form ref="formRef" :inline="true" :model="form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||
<slot name="tableForm" />
|
||||
</el-form>
|
||||
|
||||
<!-- 表格头部设置 -->
|
||||
<div class="w-[99/100] mt-2 px-2 pb-2 bg-bg_color">
|
||||
<div class="flex justify-between w-full h-[60px] p-4">
|
||||
|
@ -21,22 +20,28 @@
|
|||
<slot name="tableButtons" />
|
||||
</div>
|
||||
|
||||
<!-- 右边操作按钮 -->
|
||||
<!-- 表格刷新按钮 -->
|
||||
<RefreshIcon v-tippy="rendTipProps('刷新')" :class="`w-[16px] ${iconClass()}} ${loading ? 'animate-spin' : ''}`" @click="onReFresh" />
|
||||
<el-divider direction="vertical" />
|
||||
|
||||
<!-- 选择表格大小 -->
|
||||
<el-dropdown trigger="click">
|
||||
<CollapseIcon :class="`w-[16px] ${iconClass()}`" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'large')" @click="handleTableSizeClick('large')"> 宽松 </el-dropdown-item>
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'default')" @click="handleTableSizeClick('default')"> 默认 </el-dropdown-item>
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'small')" @click="handleTableSizeClick('small')"> 紧凑 </el-dropdown-item>
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'large')" @click="handleTableSizeClick('large')">
|
||||
{{ $t("style.larger") }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'default')" @click="handleTableSizeClick('default')"> {{ t("style.default") }} </el-dropdown-item>
|
||||
<el-dropdown-item :style="getDropdownItemStyle(size, 'small')" @click="handleTableSizeClick('small')">
|
||||
{{ t("style.small") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-divider direction="vertical" />
|
||||
|
||||
<!-- 表格列设置 -->
|
||||
<el-popover :popper-style="{ padding: 0 }" placement="bottom-start" trigger="click" width="200">
|
||||
<template #reference>
|
||||
<SettingIcon v-tippy="rendTipProps('列设置')" :class="`w-[16px] ${iconClass()}`" />
|
||||
|
@ -44,7 +49,7 @@
|
|||
|
||||
<div :class="topClass()">
|
||||
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" class="!-mr-1" label="列展示" @change="handleCheckAllChange" />
|
||||
<el-button link type="primary" @click="onReset"> 重置</el-button>
|
||||
<el-button link type="primary" @click="onReset"> {{ t("buttons.rest") }}</el-button>
|
||||
</div>
|
||||
|
||||
<div class="pt-[6px] pl-[11px]">
|
||||
|
@ -53,8 +58,8 @@
|
|||
<el-space :alignment="'flex-start'" :size="0" direction="vertical">
|
||||
<div v-for="(item, index) in checkColumnList" :key="index" class="flex items-center">
|
||||
<DragIcon :class="`drag-btn w-[16px] mr-2 ${isFixedColumn(item) ? '!cursor-no-drop' : '!cursor-grab'}`" @mouseenter="rowDrop" />
|
||||
<el-checkbox :key="index" :label="item" :value="item" @change="handleCheckColumnListChange(true, item)">
|
||||
<span class="inline-block w-[120px] truncate hover:text-text_color_primary" title="{transformI18n(item)}"> {{ transformI18n(item) }} </span>
|
||||
<el-checkbox :key="index" :label="item" :value="item" @change="handleCheckColumnListChange(item)">
|
||||
<span :title="transformI18n(item)" class="inline-block w-[120px] truncate hover:text-text_color_primary"> {{ transformI18n(item) }} </span>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</el-space>
|
||||
|
@ -80,7 +85,7 @@
|
|||
adaptive
|
||||
align-whole="center"
|
||||
border
|
||||
table-layout="auto"
|
||||
table-layout="fixed"
|
||||
v-bind="$attrs"
|
||||
@selection-change="handleSelectionChange"
|
||||
@page-size-change="handleSizeChange"
|
||||
|
@ -95,15 +100,14 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, getCurrentInstance, nextTick, onMounted, PropType, ref, unref, watch } from "vue";
|
||||
import { getCurrentInstance, nextTick, onMounted, PropType, ref, unref, watch } from "vue";
|
||||
import { rendTipProps } from "@/components/TableBar/utils/tableConfig";
|
||||
import { cellHeaderStyle, iconClass, topClass } from "@/components/TableBar/utils/tableStyle";
|
||||
import { cellHeaderStyle, getDropdownItemStyle, iconClass, topClass } from "@/components/TableBar/utils/tableStyle";
|
||||
import PureTable from "@pureadmin/table";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import RefreshIcon from "@/assets/table-bar/refresh.svg?component";
|
||||
import CollapseIcon from "@/assets/table-bar/collapse.svg?component";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
import SettingIcon from "@/assets/table-bar/settings.svg?component";
|
||||
import { cloneDeep, getKeyList, isBoolean, isFunction } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
|
@ -142,40 +146,37 @@ const props = defineProps({
|
|||
type: Object as PropType<any>,
|
||||
default: Object
|
||||
},
|
||||
// 刷新时
|
||||
onReFresh: {
|
||||
type: Function as PropType<Function>,
|
||||
default: () => {}
|
||||
},
|
||||
// 表格的key值
|
||||
tableKey: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
default: "0"
|
||||
},
|
||||
tableTitle: { type: String, default: "" },
|
||||
class: { type: String, default: "" }
|
||||
// 表格标题
|
||||
tableTitle: { type: String, default: "" }
|
||||
});
|
||||
|
||||
const emit = defineEmits(["changeColumn"]);
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
// 是否全选
|
||||
const checkAll = ref(true);
|
||||
// 表格样式大小
|
||||
const size = ref(props.size);
|
||||
const isIndeterminate = ref(false);
|
||||
// 动态行
|
||||
const dynamicColumns = ref(props.column);
|
||||
// 过滤是否选中的列
|
||||
const filterColumns = cloneDeep(props.column).filter(column => (isBoolean(column?.hide) ? !column.hide : !(isFunction(column?.hide) && column?.hide())));
|
||||
// 选择当前列
|
||||
const checkedColumns = ref(getKeyList(cloneDeep(filterColumns), "label"));
|
||||
let checkColumnList = getKeyList(cloneDeep(props.column), "label");
|
||||
const checkColumnList = ref(getKeyList(cloneDeep(dynamicColumns.value), "label"));
|
||||
const instance = getCurrentInstance()!;
|
||||
|
||||
const getDropdownItemStyle = computed(() => {
|
||||
return (size: string, s: string) => {
|
||||
return {
|
||||
background: s === size ? useEpThemeStoreHook().epThemeColor : "",
|
||||
color: s === size ? "#fff" : "var(--el-text-color-primary)"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* * 修改表格样式大小
|
||||
* @param value 修改样式大小 larger | default | small
|
||||
|
@ -189,32 +190,57 @@ const handleTableSizeClick = (value: string) => {
|
|||
* @param val 是否全部显示
|
||||
*/
|
||||
const handleCheckAllChange = (val: boolean) => {
|
||||
checkedColumns.value = val ? checkColumnList : [];
|
||||
checkedColumns.value = val ? checkColumnList.value : [];
|
||||
isIndeterminate.value = false;
|
||||
dynamicColumns.value.map(column => (val ? (column.hide = false) : (column.hide = true)));
|
||||
};
|
||||
|
||||
/**
|
||||
* * 选中的表格列---是否显示
|
||||
* @param value
|
||||
*/
|
||||
const handleCheckedColumnsChange = (value: string[]) => {
|
||||
checkedColumns.value = value;
|
||||
const checkedCount = value.length;
|
||||
checkAll.value = checkedCount === checkColumnList.length;
|
||||
isIndeterminate.value = checkedCount > 0 && checkedCount < checkColumnList.length;
|
||||
checkAll.value = checkedCount === checkColumnList.value.length;
|
||||
isIndeterminate.value = checkedCount > 0 && checkedCount < checkColumnList.value.length;
|
||||
};
|
||||
const handleCheckColumnListChange = (val: boolean, label: string) => {
|
||||
dynamicColumns.value.filter(item => transformI18n(item.label) === transformI18n(label))[0].hide = !val;
|
||||
|
||||
/**
|
||||
* * 点击是否显示列
|
||||
* @param label
|
||||
*/
|
||||
const handleCheckColumnListChange = (label: string) => {
|
||||
dynamicColumns.value.filter(item => transformI18n(item.label) === transformI18n(label))[0].hide = !(event.target as any).checked;
|
||||
};
|
||||
|
||||
/**
|
||||
* * 是否为固定列
|
||||
* @param label
|
||||
*/
|
||||
const isFixedColumn = (label: string) => {
|
||||
return dynamicColumns.value.filter(item => transformI18n(item.label) === transformI18n(label))[0].fixed;
|
||||
};
|
||||
const onReset = () => {
|
||||
|
||||
/**
|
||||
* * 重置自定义表格列字段
|
||||
*/
|
||||
const onReset = async () => {
|
||||
// 重置列表值
|
||||
const list = [];
|
||||
// 全选按钮设为true
|
||||
checkAll.value = true;
|
||||
isIndeterminate.value = false;
|
||||
// dynamicColumns.value = cloneDeep(props.column);
|
||||
// checkColumnList = [];
|
||||
// checkColumnList = getKeyList(cloneDeep(props?.column), "label");
|
||||
// 当前选中的列
|
||||
checkedColumns.value = getKeyList(cloneDeep(filterColumns), "label");
|
||||
// ? 重新赋值,拖拽排序不会改变原有值,响应式数据的特性 直接对 ref 或 reactive 创建的变量进行赋值可能不会触发视图的更新
|
||||
// ? Proxy 来追踪属性的访问和修改,使用异步方式确保正确更新视图
|
||||
checkColumnList.value = [];
|
||||
await nextTick(() => {
|
||||
checkColumnList.value = getKeyList(filterColumns, "label");
|
||||
});
|
||||
|
||||
const list = [];
|
||||
// checkedColumns 是原有顺序,根据这个顺序重新得到list
|
||||
checkedColumns.value.forEach(item => {
|
||||
dynamicColumns.value.forEach(column => {
|
||||
if (column.label == item) {
|
||||
|
@ -251,8 +277,7 @@ const rowDrop = (event: any) => {
|
|||
}
|
||||
const currentRow = dynamicColumns.value.splice(oldIndex, 1)[0];
|
||||
dynamicColumns.value.splice(newIndex, 0, currentRow);
|
||||
|
||||
emit("changeColumn", props.column);
|
||||
emit("changeColumn", dynamicColumns.value);
|
||||
}
|
||||
});
|
||||
}).then();
|
||||
|
@ -270,10 +295,6 @@ onMounted(() => {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin: 24px 24px 0 !important;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { computed } from "vue";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
|
||||
/**
|
||||
* * 表格头部样式
|
||||
*/
|
||||
|
@ -6,6 +9,20 @@ export const cellHeaderStyle = () => ({
|
|||
color: "var(--el-text-color-primary)"
|
||||
});
|
||||
|
||||
// * icon 样式
|
||||
export const iconClass = () => "text-black dark:text-white duration-100 hover:!text-primary cursor-pointer outline-none";
|
||||
|
||||
// * 顶部样式
|
||||
export const topClass = () => "flex justify-between pt-[3px] px-[11px] border-b-[1px] border-solid border-[#dcdfe6] dark:border-[#303030]";
|
||||
|
||||
/**
|
||||
* * 拖拽列样式
|
||||
*/
|
||||
export const getDropdownItemStyle = computed(() => {
|
||||
return (size: string, s: string) => {
|
||||
return {
|
||||
background: s === size ? useEpThemeStoreHook().epThemeColor : "",
|
||||
color: s === size ? "#fff" : "var(--el-text-color-primary)"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,59 @@
|
|||
<template>
|
||||
<TablePlusBar
|
||||
:column="columns"
|
||||
:data-list="dataList"
|
||||
:form="form"
|
||||
:handle-current-change="handleCurrentChange"
|
||||
:handle-selection-change="handleSelectionChange"
|
||||
:handle-size-change="handleSizeChange"
|
||||
:loading="loading"
|
||||
:onReFresh="onReFresh"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
tableTitle="系统测试(仅演示,操作后不生效)"
|
||||
@changeColumn="handleChangeColumn"
|
||||
@cell-dblclick="handleCellDblclick"
|
||||
>
|
||||
<template #tableForm>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="form.username" class="!w-[150px]" clearable placeholder="请输入用户名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录状态" prop="status">
|
||||
<el-select v-model="form.status" class="!w-[150px]" clearable placeholder="请选择">
|
||||
<el-option label="成功" value="1" />
|
||||
<el-option label="失败" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录时间" prop="loginTime">
|
||||
<el-date-picker v-model="form.loginTime" :shortcuts="getPickerShortcuts()" end-placeholder="结束日期时间" range-separator="至" start-placeholder="开始日期时间" type="datetimerange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="loading" type="primary" @click="onSearch"> 搜索 </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> 重置</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template #tableButtons>
|
||||
<el-button type="danger">按钮</el-button>
|
||||
</template>
|
||||
|
||||
<template #tableSelect>
|
||||
<div v-if="selectedNum > 0" v-motion-fade class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center">
|
||||
<div class="flex-auto">
|
||||
<span class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]" style="font-size: var(--el-font-size-base)"> 已选 {{ selectedNum }} 项 </span>
|
||||
<el-button text type="primary" @click="onSelectionCancel"> 取消选择</el-button>
|
||||
</div>
|
||||
<el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
|
||||
<template #reference>
|
||||
<el-button class="mr-1" text type="danger"> 批量删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #operation> 111</template>
|
||||
</TablePlusBar>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { PaginationProps } from "@pureadmin/table";
|
||||
|
@ -92,60 +148,3 @@ onMounted(() => {
|
|||
setTimeout(() => (loading.value = false), 1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TablePlusBar
|
||||
:column="columns"
|
||||
:data-list="dataList"
|
||||
:form="form"
|
||||
:handle-current-change="handleCurrentChange"
|
||||
:handle-selection-change="handleSelectionChange"
|
||||
:handle-size-change="handleSizeChange"
|
||||
:loading="loading"
|
||||
:onReFresh="onReFresh"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
tableTitle="系统测试(仅演示,操作后不生效)"
|
||||
@changeColumn="handleChangeColumn"
|
||||
@cell-dblclick="handleCellDblclick"
|
||||
>
|
||||
<template #tableForm>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="form.username" class="!w-[150px]" clearable placeholder="请输入用户名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录状态" prop="status">
|
||||
<el-select v-model="form.status" class="!w-[150px]" clearable placeholder="请选择">
|
||||
<el-option label="成功" value="1" />
|
||||
<el-option label="失败" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录时间" prop="loginTime">
|
||||
<el-date-picker v-model="form.loginTime" :shortcuts="getPickerShortcuts()" end-placeholder="结束日期时间" range-separator="至" start-placeholder="开始日期时间" type="datetimerange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="loading" type="primary" @click="onSearch"> 搜索 </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> 重置</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template #tableButtons>
|
||||
<el-button type="danger">按钮</el-button>
|
||||
</template>
|
||||
|
||||
<template #tableSelect>
|
||||
<div v-if="selectedNum > 0" v-motion-fade class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center">
|
||||
<div class="flex-auto">
|
||||
<span class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]" style="font-size: var(--el-font-size-base)"> 已选 {{ selectedNum }} 项 </span>
|
||||
<el-button text type="primary" @click="onSelectionCancel"> 取消选择</el-button>
|
||||
</div>
|
||||
<el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
|
||||
<template #reference>
|
||||
<el-button class="mr-1" text type="danger"> 批量删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #operation> 111</template>
|
||||
</TablePlusBar>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue