feat: 新增 @pureadmin/table 行、列拖拽示例

This commit is contained in:
xiaoxian521
2022-11-23 12:03:17 +08:00
parent 27d9339a4c
commit 7472c25c0a
44 changed files with 406 additions and 90 deletions

View File

@@ -1,13 +1,16 @@
<script setup lang="ts">
import Sortable from "sortablejs";
import { ref, onMounted } from "vue";
import Sortable, { Swap } from "sortablejs";
import draggable from "vuedraggable/src/vuedraggable";
import { useAppStoreHook } from "@/store/modules/app";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
defineOptions({
name: "Draggable"
});
const { setSortSwap } = useAppStoreHook();
const gridLists = ref<Array<Object>>([
{ grid: "cn", num: 1 },
{ grid: "cn", num: 2 },
@@ -39,7 +42,8 @@ const change = (evt): void => {
};
onMounted(() => {
// 使用原生sortable实现元素位置切换
if (!useAppStoreHook().sortSwap) Sortable.mount(new Swap());
setSortSwap(true);
new Sortable(document.querySelector(".cut-container"), {
swap: true,
forceFallback: true,
@@ -121,7 +125,7 @@ onMounted(() => {
<el-card>
<template #header>
<div class="card-header">
<span>拖拽实现元素位置</span>
<span>拖拽实现元素位置</span>
</div>
</template>
<!-- 拖拽实现元素位置切换 -->

View File

@@ -1,30 +1,28 @@
import {
Base,
Stripe,
Border,
Status,
FixHeader,
FixColumn,
FluidHeight,
GroupHeader,
Radio,
MultipleChoice,
Sortable,
Filters,
ColumnTemplate,
HeaderRenderer,
Expand,
TreeTable,
TotalRow,
Merge,
CustomIndex,
Layout,
NestProp,
ImgPreview
} from "./components";
import Base from "./base.vue";
import Stripe from "./stripe.vue";
import Border from "./border.vue";
import Status from "./status.vue";
import FixHeader from "./fixHeader.vue";
import FixColumn from "./fixColumn.vue";
import FluidHeight from "./fluidHeight.vue";
import GroupHeader from "./groupHeader.vue";
import Radio from "./radio.vue";
import MultipleChoice from "./multipleChoice.vue";
import Sortable from "./sortable.vue";
import Filters from "./filters.vue";
import ColumnTemplate from "./column-template/index.vue";
import HeaderRenderer from "./header-renderer/index.vue";
import Expand from "./expand.vue";
import TreeTable from "./tree.vue";
import TotalRow from "./totalRow.vue";
import Merge from "./merge.vue";
import CustomIndex from "./customIndex.vue";
import Layout from "./layout.vue";
import NestProp from "./nestProp.vue";
import ImgPreview from "./imgPreview.vue";
const rendContent = (val: string) =>
`代码位置src/views/pure-table/components/${val}.vue`;
`代码位置src/views/pure-table/base/${val}.vue`;
export const list = [
{

View File

@@ -1,47 +0,0 @@
import Base from "./base.vue";
import Stripe from "./stripe.vue";
import Border from "./border.vue";
import Status from "./status.vue";
import FixHeader from "./fixHeader.vue";
import FixColumn from "./fixColumn.vue";
import FluidHeight from "./fluidHeight.vue";
import GroupHeader from "./groupHeader.vue";
import Radio from "./radio.vue";
import MultipleChoice from "./multipleChoice.vue";
import Sortable from "./sortable.vue";
import Filters from "./filters.vue";
import ColumnTemplate from "./column-template/index.vue";
import HeaderRenderer from "./header-renderer/index.vue";
import Expand from "./expand.vue";
import TreeTable from "./tree.vue";
import TotalRow from "./totalRow.vue";
import Merge from "./merge.vue";
import CustomIndex from "./customIndex.vue";
import Layout from "./layout.vue";
import NestProp from "./nestProp.vue";
import ImgPreview from "./imgPreview.vue";
export {
Base,
Stripe,
Border,
Status,
FixHeader,
FixColumn,
FluidHeight,
GroupHeader,
Radio,
MultipleChoice,
Sortable,
Filters,
ColumnTemplate,
HeaderRenderer,
Expand,
TreeTable,
TotalRow,
Merge,
CustomIndex,
Layout,
NestProp,
ImgPreview
};

View File

@@ -0,0 +1,56 @@
<script setup lang="ts">
import { list } from "./high/list";
import { Tabs, TabPane } from "@pureadmin/components";
defineOptions({
name: "PureTableHigh"
});
</script>
<template>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">
高级用法全部采用 tsx 语法充分发挥
<el-link
href="https://github.com/xiaoxian521/pure-admin-table"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
@pureadmin/table
</el-link>
的灵活性维护整体表格只需操作 columns 配置即可
</span>
</div>
</template>
<el-alert
title="高级用法中所有表格都设置了 row-key 后端需返回唯一值的字段比如id 作用1. 用来优化 Table
的渲染尤其当字段在深层结构中2. 防止拖拽后表格组件内部混乱(拖拽必须设置哦,坑都帮您们踩过啦 ❤️)"
type="info"
:closable="false"
/>
<Tabs :destroyInactiveTabPane="true">
<TabPane v-for="item of list" :key="item.key">
<template #tab>
<el-tooltip :content="item.content" placement="top-end">
<span>{{ item.title }}</span>
</el-tooltip>
</template>
<component :is="item.component" />
</TabPane>
</Tabs>
</el-card>
</template>
<style scoped>
:deep(.ant-tabs-content-holder) {
margin-top: 10px;
}
:deep(.el-alert__title) {
font-size: 16px;
}
</style>

View File

@@ -0,0 +1,88 @@
import dayjs from "dayjs";
import { clone } from "@pureadmin/utils";
const date = dayjs(new Date()).format("YYYY-MM-DD");
const tableData = [
{
date,
name: "Tom",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Jack",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Dick",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Harry",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Sam",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Lucy",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Mary",
address: "No. 189, Grove St, Los Angeles"
},
{
date,
name: "Mike",
address: "No. 189, Grove St, Los Angeles"
}
];
const tableDataMore = clone(tableData, true).map(item =>
Object.assign(item, {
state: "California",
city: "Los Angeles",
"post-code": "CA 90036"
})
);
const tableDataImage = clone(tableData, true).map((item, index) =>
Object.assign(item, {
image: `https://xiaoxian521.github.io/pure-admin-table/imgs/${
index + 1
}.jpg`
})
);
const tableDataSortable = clone(tableData, true).map((item, index) =>
Object.assign(item, {
date: `${dayjs(new Date()).format("YYYY-MM")}-${index + 1}`
})
);
const tableDataDrag = clone(tableData, true).map((item, index) => {
delete item["address"];
return Object.assign(
{
id: index + 1,
date: `${dayjs(new Date()).format("YYYY-MM")}-${index + 1}`
},
item
);
});
export {
tableData,
tableDataDrag,
tableDataMore,
tableDataImage,
tableDataSortable
};

View File

@@ -0,0 +1,68 @@
import Sortable from "sortablejs";
import { tableDataDrag } from "../../data";
import { ref, nextTick, onMounted } from "vue";
// 行拖拽演示
export function useColumns() {
const dataList = ref(tableDataDrag);
const columnsDrag = ref<TableColumnList>([
{
label: "ID",
prop: "id"
},
{
label: "日期",
prop: "date"
},
{
label: "姓名",
prop: "name"
}
]);
const columns = ref<TableColumnList>([
{
label: "ID",
prop: index => columnsDrag.value[index].prop as string
},
{
label: "日期",
prop: index => columnsDrag.value[index].prop as string
},
{
label: "姓名",
prop: index => columnsDrag.value[index].prop as string
}
]);
const columnDrop = (event: { preventDefault: () => void }) => {
event.preventDefault();
nextTick(() => {
const wrapper: HTMLElement = document.querySelector(
".el-table__header-wrapper tr"
);
Sortable.create(wrapper, {
animation: 300,
delay: 0,
onEnd: ({ newIndex, oldIndex }) => {
const oldItem = columnsDrag.value[oldIndex];
columnsDrag.value.splice(oldIndex, 1);
columnsDrag.value.splice(newIndex, 0, oldItem);
}
});
});
};
onMounted(() => {
nextTick(() => {
columnDrop(event);
});
});
return {
columns,
dataList,
columnsDrag
};
}

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { useColumns } from "./columns";
const { columns, dataList, columnsDrag } = useColumns();
</script>
<template>
<div class="flex">
<el-scrollbar height="700px">
<code>
<pre class="w-[700px]"> {{ columnsDrag }}</pre>
</code>
</el-scrollbar>
<pure-table row-key="id" :data="dataList" :columns="columns" />
</div>
</template>

View File

@@ -0,0 +1,69 @@
import Sortable from "sortablejs";
import { ref, nextTick } from "vue";
import { tableDataDrag } from "../../data";
// 行拖拽演示
export function useColumns() {
const dataList = ref(tableDataDrag);
const rowDrop = (event: { preventDefault: () => void }) => {
event.preventDefault();
nextTick(() => {
const wrapper: HTMLElement = document.querySelector(
".el-table__body-wrapper tbody"
);
Sortable.create(wrapper, {
animation: 300,
handle: ".drag-btn",
onEnd: ({ newIndex, oldIndex }) => {
const currentRow = dataList.value.splice(oldIndex, 1)[0];
dataList.value.splice(newIndex, 0, currentRow);
}
});
});
};
const columns: TableColumnList = [
// {
// width: 60,
// cellRenderer: () => (
// <iconify-icon-online
// icon="icon-park-outline:drag"
// class="drag-btn cursor-grab"
// onMouseenter={(event: { preventDefault: () => void }) =>
// rowDrop(event)
// }
// />
// )
// },
{
label: "ID",
prop: "id",
cellRenderer: ({ row }) => (
<div class="flex items-center">
<iconify-icon-online
icon="icon-park-outline:drag"
class="drag-btn cursor-grab"
onMouseenter={(event: { preventDefault: () => void }) =>
rowDrop(event)
}
/>
<p class="ml-[16px]">{row.id}</p>
</div>
)
},
{
label: "日期",
prop: "date"
},
{
label: "姓名",
prop: "name"
}
];
return {
columns,
dataList
};
}

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { useColumns } from "./columns";
const { columns, dataList } = useColumns();
</script>
<template>
<div class="flex">
<el-scrollbar height="700px">
<code>
<pre class="w-[700px]"> {{ dataList }}</pre>
</code>
</el-scrollbar>
<pure-table row-key="id" :data="dataList" :columns="columns" />
</div>
</template>

View File

@@ -0,0 +1,20 @@
import RowDrag from "./drag/row/index.vue";
import ColumnDrag from "./drag/column/index.vue";
const rendContent = (val: string) =>
`代码位置src/views/pure-table/high/${val}/index.vue`;
export const list = [
{
key: "rowDrag",
content: rendContent("drag/row"),
title: "拖拽表格(行拖拽)",
component: RowDrag
},
{
key: "columnDrag",
content: rendContent("drag/column"),
title: "拖拽表格(列拖拽)",
component: ColumnDrag
}
];

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { list } from "./list";
import { list } from "./base/list";
import { Tabs, TabPane } from "@pureadmin/components";
defineOptions({
@@ -26,6 +26,13 @@ defineOptions({
</div>
</template>
<el-alert
title="基础用法中大部分表格都没设置 row-key 不过最好都设置一下后端需返回唯一值的字段比如id 作用1. 用来优化 Table
的渲染尤其当字段在深层结构中2. 防止某些操作导致表格组件内部混乱"
type="info"
:closable="false"
/>
<Tabs :destroyInactiveTabPane="true">
<TabPane v-for="item of list" :key="item.key">
<template #tab>
@@ -43,4 +50,8 @@ defineOptions({
:deep(.ant-tabs-content-holder) {
margin-top: 10px;
}
:deep(.el-alert__title) {
font-size: 16px;
}
</style>