mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-01-23 09:40:25 +08:00
feat: add CardList component
This commit is contained in:
parent
1ddfc31c3c
commit
0f5ddbf1ec
4
src/components/CardList/index.ts
Normal file
4
src/components/CardList/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { withInstall } from '/@/utils';
|
||||
import cardList from './src/CardList.vue';
|
||||
|
||||
export const CardList = withInstall(cardList);
|
185
src/components/CardList/src/CardList.vue
Normal file
185
src/components/CardList/src/CardList.vue
Normal file
@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="bg-white mb-2 p-4">
|
||||
<BasicForm @register="registerForm" />
|
||||
</div>
|
||||
{{ sliderProp.width }}
|
||||
<div class="bg-white p-2"
|
||||
><List
|
||||
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
|
||||
:data-source="data"
|
||||
:pagination="paginationProp"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-end space-x-2"
|
||||
><slot name="header"></slot>
|
||||
<Tooltip>
|
||||
<template #title>
|
||||
<div class="w-50">每行显示数量</div
|
||||
><Slider
|
||||
id="slider"
|
||||
v-bind="sliderProp"
|
||||
v-model:value="grid"
|
||||
@change="sliderChange"
|
||||
/></template>
|
||||
<Button><TableOutlined /></Button>
|
||||
</Tooltip>
|
||||
<Tooltip @click="fetch">
|
||||
<template #title>刷新</template>
|
||||
<Button><RedoOutlined /></Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #renderItem="{ item }">
|
||||
<ListItem>
|
||||
<Card>
|
||||
<template #title></template>
|
||||
<template #cover>
|
||||
<div :class="height">
|
||||
<Image :src="item.imgs[0]" />
|
||||
</div>
|
||||
</template>
|
||||
<template class="ant-card-actions" #actions>
|
||||
<!-- <SettingOutlined key="setting" />-->
|
||||
<EditOutlined key="edit" />
|
||||
<Dropdown
|
||||
:trigger="['hover']"
|
||||
:dropMenuList="[
|
||||
{
|
||||
text: '删除',
|
||||
event: '1',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, item.id),
|
||||
},
|
||||
},
|
||||
]"
|
||||
popconfirm
|
||||
>
|
||||
<EllipsisOutlined key="ellipsis" />
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
<CardMeta>
|
||||
<template #title>
|
||||
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
|
||||
</template>
|
||||
<template #avatar>
|
||||
<Avatar :src="item.avatar" />
|
||||
</template>
|
||||
<template #description>{{ item.time }}</template>
|
||||
</CardMeta>
|
||||
</Card>
|
||||
</ListItem>
|
||||
</template>
|
||||
</List></div
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import {
|
||||
EditOutlined,
|
||||
EllipsisOutlined,
|
||||
RedoOutlined,
|
||||
TableOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
Card,
|
||||
CardMeta,
|
||||
Image,
|
||||
TypographyText,
|
||||
Tooltip,
|
||||
Slider,
|
||||
Avatar,
|
||||
} from 'ant-design-vue';
|
||||
import { Dropdown } from '/@/components/Dropdown';
|
||||
import { BasicForm, useForm } from '/@/components/Form';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { Button } from '/@/components/Button';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { useSlider, grid } from './data';
|
||||
// 获取slider属性
|
||||
const sliderProp = computed(() => useSlider(4));
|
||||
// 组件接收参数
|
||||
const props = defineProps({
|
||||
// 请求API的参数
|
||||
params: propTypes.object.def({}),
|
||||
//api
|
||||
api: propTypes.func,
|
||||
});
|
||||
//暴露内部方法
|
||||
const emit = defineEmits(['getMethod', 'delete']);
|
||||
//数据
|
||||
const data = ref([]);
|
||||
// 切换每行个数
|
||||
// cover图片自适应高度
|
||||
//修改pageSize并重新请求数据
|
||||
|
||||
const height = computed(() => {
|
||||
return `h-${120 - grid.value * 6}`;
|
||||
});
|
||||
//表单
|
||||
const [registerForm, { validate }] = useForm({
|
||||
schemas: [{ field: 'type', component: 'Input', label: '类型' }],
|
||||
labelWidth: 80,
|
||||
baseColProps: { span: 6 },
|
||||
actionColOptions: { span: 24 },
|
||||
autoSubmitOnEnter: true,
|
||||
submitFunc: handleSubmit,
|
||||
});
|
||||
//表单提交
|
||||
async function handleSubmit() {
|
||||
const data = await validate();
|
||||
await fetch(data);
|
||||
}
|
||||
function sliderChange(n) {
|
||||
pageSize.value = n * 4;
|
||||
fetch();
|
||||
}
|
||||
|
||||
// 自动请求并暴露内部方法
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
emit('getMethod', fetch);
|
||||
});
|
||||
|
||||
async function fetch(p = {}) {
|
||||
const { api, params } = props;
|
||||
if (api && isFunction(api)) {
|
||||
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p });
|
||||
data.value = res.items;
|
||||
total.value = res.total;
|
||||
}
|
||||
}
|
||||
//分页相关
|
||||
const page = ref(1);
|
||||
const pageSize = ref(36);
|
||||
const total = ref(0);
|
||||
const paginationProp = ref({
|
||||
showSizeChanger: false,
|
||||
showQuickJumper: true,
|
||||
pageSize,
|
||||
current: page,
|
||||
total,
|
||||
showTotal: (total) => `总 ${total} 条`,
|
||||
onChange: pageChange,
|
||||
onShowSizeChange: pageSizeChange,
|
||||
});
|
||||
|
||||
function pageChange(p, pz) {
|
||||
page.value = p;
|
||||
pageSize.value = pz;
|
||||
fetch();
|
||||
}
|
||||
function pageSizeChange(current, size) {
|
||||
pageSize.value = size;
|
||||
fetch();
|
||||
}
|
||||
|
||||
async function handleDelete(id) {
|
||||
emit('delete', id);
|
||||
}
|
||||
</script>
|
25
src/components/CardList/src/data.ts
Normal file
25
src/components/CardList/src/data.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { ref } from 'vue';
|
||||
//每行个数
|
||||
export const grid = ref(12);
|
||||
// slider属性
|
||||
export const useSlider = (min = 6, max = 12) => {
|
||||
// 每行显示个数滑动条
|
||||
const getMarks = () => {
|
||||
const l = {};
|
||||
for (let i = min; i < max + 1; i++) {
|
||||
l[i] = {
|
||||
style: {
|
||||
color: '#fff',
|
||||
},
|
||||
label: i,
|
||||
};
|
||||
}
|
||||
return l;
|
||||
};
|
||||
return {
|
||||
min,
|
||||
max,
|
||||
marks: getMarks(),
|
||||
step: 1,
|
||||
};
|
||||
};
|
@ -45,6 +45,7 @@ export default {
|
||||
|
||||
time: 'Relative Time',
|
||||
cropperImage: 'Cropper Image',
|
||||
cardList: 'Card List',
|
||||
},
|
||||
editor: {
|
||||
editor: 'Editor',
|
||||
|
@ -44,6 +44,7 @@ export default {
|
||||
|
||||
time: '相对时间',
|
||||
cropperImage: '图片裁剪',
|
||||
cardList: '卡片列表',
|
||||
},
|
||||
editor: {
|
||||
editor: '编辑器',
|
||||
|
@ -534,6 +534,14 @@ const comp: AppRouteModule = {
|
||||
title: t('routes.demo.comp.loading'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'cardList',
|
||||
name: 'CardListDemo',
|
||||
component: () => import('/@/views/demo/comp/card-list/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.cardList'),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
32
src/views/demo/comp/card-list/index.vue
Normal file
32
src/views/demo/comp/card-list/index.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<PageWrapper title="卡片列表示例" content="基础封装">
|
||||
<CardList :params="params" :api="demoListApi" @getMethod="getMethod" @delete="handleDel">
|
||||
<template #header>
|
||||
<Button type="primary" color="error"> 按钮1 </Button>
|
||||
<Button type="primary" color="success"> 按钮2 </Button>
|
||||
</template>
|
||||
</CardList>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { CardList } from '/@/components/CardList';
|
||||
import { Button } from '/@/components/Button';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
const { notification } = useMessage();
|
||||
// 请求api时附带参数
|
||||
const params = {};
|
||||
|
||||
let reload = () => {};
|
||||
// 获取内部fetch方法;
|
||||
function getMethod(m: any) {
|
||||
reload = m;
|
||||
}
|
||||
//删除按钮事件
|
||||
function handleDel(id) {
|
||||
console.log(id);
|
||||
notification.success({ message: `成功删除${id}` });
|
||||
reload();
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user