【新增】数据列表组件:XnDataList

pull/176/head
这么诚实 2023-11-16 15:31:33 +08:00
parent 58eaf57633
commit 17db535cbf
2 changed files with 256 additions and 0 deletions

View File

@ -0,0 +1,67 @@
# 小诺数据列表的组件
## 说明
### props定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|------------|---------|-------|------------------|
| 1 | dataSource | Array | 数据源 | 见dataSource字段定义 |
| 2 | page | Object | 分页 | 见page字段定义 |
| 3 | actions | Array | 操作数组 | 见action字段定义 |
| 4 | loading | Boolean | 加载中提示 | - |
> dataSource字段定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|--------------|--------|-----------------|-------------------|
| 1 | title | String | 标题 | 设备编码 |
| 2 | descriptions | Array | 描述 | 见description字段定义 |
| 3 | contents | Array | 内容 | 见content字段定义 |
| 4 | record | Object | 数据记录emit触发回调参数 | |
> description字段定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|---------|--------|----|------|
| 1 | title | String | 标题 | 设备名称 |
| 2 | content | Object | 内容 | 测试设备 |
> content字段定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|---------|--------|----|---------------------|
| 1 | title | String | 标题 | 数据更新时间 |
| 2 | content | Object | 内容 | 2023-11-14 09:00:00 |
> action字段定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|-------|--------|----|---------|
| 1 | key | String | 键 | setting |
| 2 | label | String | 标签 | 所属产品 |
| 3 | icon | String | 图标 | setting |
| 4 | color | String | 颜色 | red |
> page字段定义
| 序号 | 编码 | 类型 | 说明 | 示例 |
|----|---------|--------|------|----|
| 1 | current | Number | 当前页 | 1 |
| 2 | size | Number | 每页大小 | 6 |
| 3 | total | Number | 总数 | 0 |
### emits定义
| 序号 | 方法名 | 参数类型 | 参数示例 |
|----|-------------|--------|-----------------------------|
| 1 | title | Object | {record: {...}} |
| 1 | action | Object | {key: 'edit', record:{...}} |
| 2 | page-change | Number | 1 |
### slots定义
| 序号 | 名称 | 说明 | 示例 |
|----|--------------|--------|----|
| 1 | title-prefix | 标题前缀插槽 | - |
| 2 | title-suffix | 内容后缀插槽 | - |

View File

@ -0,0 +1,189 @@
<template>
<a-list item-layout="vertical" :data-source="props.dataSource" :pagination="pagination" :loading="loading">
<template #renderItem="{ item, index }">
<a-list-item :key="index" class="xn-data-list-item">
<a-list-item-meta class="xn-data-list-item-meta">
<template #avatar>
<a-avatar shape="square" :size="50">{{ index + 1 }}</a-avatar>
</template>
<template #title>
<div class="xn-data-list-item-meta-title">
<div class="xn-data-list-item-meta-title-prefix">
<slot name="title-prefix" :record="item.record"></slot>
</div>
<a @click="clickTitle(item)">{{ item.title }}</a>
<div class="xn-data-list-item-meta-title-suffix">
<slot name="title-suffix" :record="item.record"></slot>
</div>
</div>
</template>
<template #description>
<a-tooltip placement="top" v-for="description in item.descriptions">
<template #title>
<span>{{ description.title }}</span>
</template>
<a-tag>{{ description.content }}</a-tag>
</a-tooltip>
</template>
</a-list-item-meta>
<div class="xn-content" v-if="item.contents">
<div class="xn-statistics" v-for="content in item.contents">
<div class="xn-statistic-title">
{{ content.title }}
</div>
<div class="xn-statistic-content">
<span>{{ content.content }}</span>
</div>
</div>
</div>
<template #extra v-if="item.extra">
<div class="xn-extra">
<div class="xn-statistics">
<div class="xn-statistic-title">{{ item.extra.title }}</div>
<div class="xn-statistic-content">
<span>{{ item.extra.content }}</span>
</div>
</div>
</div>
</template>
<template #actions>
<a-button type="link" @click="doAction(key, item)"
v-for="{ key, label, icon, color} in props.actions">
<template #icon>
<component :is="icon" :style="{color:color}"/>
</template>
{{ label }}
</a-button>
</template>
</a-list-item>
</template>
</a-list>
</template>
<script setup name="xnDataList">
import {message} from "ant-design-vue";
const props = defineProps({
//
dataSource: {
type: Array,
required: true
},
//
page: {
type: Object,
required: true
},
//
actions: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['title', 'action', 'page-change'])
//
const {current, size, total} = toRefs(props.page)
const pagination = reactive({
onChange: current => {
emit('page-change', current)
},
current: current,
pageSize: size,
total: total
})
//
const clickTitle = (item) => {
if (!item.record) {
message.error('记录参数[record]错误')
return
}
emit('title', {record: item.record})
}
// action
const doAction = (key, item) => {
if (!item.record) {
message.error('记录参数[record]错误')
return
}
emit('action', {key, record: item.record})
}
</script>
<style lang="less" scoped>
.xn-data-list-item {
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
padding: 12px 15px;
margin-bottom: 10px;
.xn-data-list-item-meta {
align-items: center;
padding-bottom: 15px;
border-bottom: 1px solid #f0f0f0;
.xn-data-list-item-meta-title {
display: flex;
align-items: center;
.xn-data-list-item-meta-title-prefix {
padding-left: 5px;
}
a {
color: var(--text-color);
transition: all 0.3s;
padding: 0 5px;
}
.xn-data-list-item-meta-title-suffix {
display: flex;
flex: 1;
justify-content: flex-end;
}
}
}
.xn-content {
//box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
}
.xn-extra {
display: flex;
align-items: center;
height: 100%;
}
}
.xn-statistics {
display: inline-block;
box-sizing: border-box;
margin: 5px 20px;
padding: 10px;
color: var(--text-color);
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: 'tnum';
&:hover {
box-shadow: var(--card-shadow);
}
.xn-statistic-title {
margin-bottom: 4px;
color: var(--text-color-secondary);
font-size: 14px;
}
.xn-statistic-content {
color: var(--heading-color);
font-size: 15px;
}
}
</style>