feat: table
This commit is contained in:
parent
81c27df227
commit
be792dd961
|
@ -11,6 +11,8 @@ node_modules
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
yarn.lock
|
||||||
|
components.d.ts
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode
|
.vscode
|
||||||
|
|
|
@ -18,6 +18,8 @@ declare module '@vue/runtime-core' {
|
||||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||||
|
ACard: typeof import('ant-design-vue/es')['Card']
|
||||||
|
ACol: typeof import('ant-design-vue/es')['Col']
|
||||||
ARow: typeof import('ant-design-vue/es')['Row']
|
ARow: typeof import('ant-design-vue/es')['Row']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
.jtable-body {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 24px 24px;
|
||||||
|
background-color: white;
|
||||||
|
.jtable-body-header {
|
||||||
|
padding: 16px 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.jtable-body-header-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
.jtable-setting-item {
|
||||||
|
color: rgba(0, 0, 0, 0.75);
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @primary-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: @primary-color-active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.jtable-content {
|
||||||
|
.jtable-card {
|
||||||
|
.jtable-card-items {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 26px;
|
||||||
|
// grid-template-columns: repeat(4, 1fr);
|
||||||
|
.jtable-card-item {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.jtable-pagination {
|
||||||
|
position: absolute;
|
||||||
|
right: 24px;
|
||||||
|
bottom: 24px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
import { UnorderedListOutlined, AppstoreOutlined } from '@ant-design/icons-vue'
|
||||||
|
import styles from './index.module.less'
|
||||||
|
import { Space, Pagination, Table, Empty } from 'ant-design-vue'
|
||||||
|
import type { TableProps } from 'ant-design-vue/es/table'
|
||||||
|
enum ModelEnum {
|
||||||
|
TABLE = 'TABLE',
|
||||||
|
CARD = 'CARD',
|
||||||
|
}
|
||||||
|
|
||||||
|
export declare type RequestData = {
|
||||||
|
code: string;
|
||||||
|
result: {
|
||||||
|
data: any[] | undefined;
|
||||||
|
pageIndex: number;
|
||||||
|
pageSize: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
status: number;
|
||||||
|
} & Record<string, any>;
|
||||||
|
// interface ColumnType extends
|
||||||
|
|
||||||
|
interface JTableProps extends TableProps{
|
||||||
|
// columns?: ColumnsType<RecordType>;
|
||||||
|
request: (params: Record<string, any> & {
|
||||||
|
pageSize?: number;
|
||||||
|
pageIndex?: number;
|
||||||
|
}) => Promise<Partial<RequestData>>;
|
||||||
|
cardBodyClass?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JTable = defineComponent<JTableProps>({
|
||||||
|
name: 'JTable',
|
||||||
|
slots: [
|
||||||
|
'headerTitle', // 顶部左边插槽
|
||||||
|
'cardRender', // 卡片内容
|
||||||
|
],
|
||||||
|
emits: [
|
||||||
|
'modelChange', // 切换卡片和表格
|
||||||
|
],
|
||||||
|
setup(props: JTableProps, { slots, emit }){
|
||||||
|
const model = ref<keyof typeof ModelEnum>(ModelEnum.CARD); // 模式切换
|
||||||
|
const column = ref<number>(3);
|
||||||
|
console.log(props)
|
||||||
|
const dataSource = ref<any[]>([
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
name: '胡彦斌',
|
||||||
|
age: 32,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
name: '胡彦祖1',
|
||||||
|
age: 42,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
name: '胡彦斌',
|
||||||
|
age: 32,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '4',
|
||||||
|
name: '胡彦祖1',
|
||||||
|
age: 42,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '5',
|
||||||
|
name: '胡彦斌',
|
||||||
|
age: 32,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '6',
|
||||||
|
name: '胡彦祖1',
|
||||||
|
age: 42,
|
||||||
|
address: '西湖区湖底公园1号',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => <div class={styles["jtable-body"]}>
|
||||||
|
<div class={styles["jtable-body-header"]}>
|
||||||
|
<div class={styles["jtable-body-header-left"]}>
|
||||||
|
{/* 顶部左边插槽 */}
|
||||||
|
{slots.headerTitle && slots.headerTitle()}
|
||||||
|
</div>
|
||||||
|
<div class={styles["jtable-body-header-right"]}>
|
||||||
|
{/* <Space> */}
|
||||||
|
<div class={[styles["jtable-setting-item"], ModelEnum.CARD === model.value ? styles['active'] : '']} onClick={() => {
|
||||||
|
model.value = ModelEnum.CARD
|
||||||
|
}}>
|
||||||
|
<AppstoreOutlined />
|
||||||
|
</div>
|
||||||
|
<div class={[styles["jtable-setting-item"], ModelEnum.TABLE === model.value ? styles['active'] : '']} onClick={() => {
|
||||||
|
model.value = ModelEnum.TABLE
|
||||||
|
}}>
|
||||||
|
<UnorderedListOutlined />
|
||||||
|
</div>
|
||||||
|
{/* </Space> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* content */}
|
||||||
|
<div class={styles['jtable-content']}>
|
||||||
|
{
|
||||||
|
model.value === ModelEnum.CARD ?
|
||||||
|
<div class={styles['jtable-card']}>
|
||||||
|
{
|
||||||
|
dataSource.value.length ?
|
||||||
|
<div
|
||||||
|
class={styles['jtable-card-items']}
|
||||||
|
style={{gridTemplateColumns: `repeat(${column.value}, 1fr)`}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
dataSource.value.map(item => slots.cardRender ?
|
||||||
|
<div class={[styles['jtable-card-item'], props.cardBodyClass]}>{slots.cardRender(item)}</div>
|
||||||
|
: null)
|
||||||
|
}
|
||||||
|
</div> :
|
||||||
|
<div><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /></div>
|
||||||
|
}
|
||||||
|
</div> :
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
dataSource={dataSource.value}
|
||||||
|
columns={props.columns}
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{/* 分页 */}
|
||||||
|
{
|
||||||
|
dataSource.value.length &&
|
||||||
|
<div class={styles['jtable-pagination']}>
|
||||||
|
<Pagination
|
||||||
|
size="small"
|
||||||
|
total={50}
|
||||||
|
showTotal={(total) => {
|
||||||
|
const min = 1
|
||||||
|
const max = 1
|
||||||
|
return `第 ${min} - ${max} 条/总共 ${total} 条`
|
||||||
|
}}
|
||||||
|
onChange={() => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
onShowSizeChange={() => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default JTable
|
|
@ -1,10 +1,12 @@
|
||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
import AIcon from './AIcon'
|
import AIcon from './AIcon'
|
||||||
import PermissionButton from './PermissionButton/index.vue'
|
import PermissionButton from './PermissionButton/index.vue'
|
||||||
|
import JTable from './Table/index'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app: App) {
|
install(app: App) {
|
||||||
app.component('AIcon', AIcon)
|
app.component('AIcon', AIcon)
|
||||||
app.component('PermissionButton', PermissionButton)
|
app.component('PermissionButton', PermissionButton)
|
||||||
|
app.component('JTable', JTable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,10 @@ export default [
|
||||||
path: '/iot/home',
|
path: '/iot/home',
|
||||||
component: () => import('@/views/iot/home/index.vue')
|
component: () => import('@/views/iot/home/index.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/table',
|
||||||
|
component: () => import('@/views/table/index.vue')
|
||||||
|
},
|
||||||
// end: 测试用, 可删除
|
// end: 测试用, 可删除
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<template>
|
||||||
|
<div class="box">
|
||||||
|
<JTable
|
||||||
|
:columns="[
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '年龄',
|
||||||
|
dataIndex: 'age',
|
||||||
|
key: 'age',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '住址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
key: 'address',
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<template #headerTitle>
|
||||||
|
<a-button type="primary">新增</a-button>
|
||||||
|
</template>
|
||||||
|
<template #cardRender="slotProps">
|
||||||
|
{{slotProps.name}}
|
||||||
|
</template>
|
||||||
|
</JTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.box {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue