搜索结果列表页面开发
This commit is contained in:
124
src/components/IssueItem/README.md
Normal file
124
src/components/IssueItem/README.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# IssueItem
|
||||
|
||||
### 说明
|
||||
- IssueItem组件为issue卡片或列表展示时使用
|
||||
|
||||
``` js
|
||||
// tempalte
|
||||
<issue-item
|
||||
:data="IssueItemData"
|
||||
:hideChecked="false"
|
||||
:key="updateCheckedKey"
|
||||
@updateChecked="updateChecked"
|
||||
@handleComments="handleComments"
|
||||
@handleAvatar="handleAvatar"
|
||||
>
|
||||
</issue-item>
|
||||
|
||||
// script
|
||||
const IssueItemData = [
|
||||
{
|
||||
checked: true,
|
||||
isOpen: true,
|
||||
title: 'Import Bug Fix',
|
||||
tags: ['线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化'],
|
||||
index: 1,
|
||||
userName: '李轩杨',
|
||||
createdTime: '2023-07-22',
|
||||
milestoneName: '里程碑名称',
|
||||
midNum: 1,
|
||||
commentsNum: 23,
|
||||
updateTime: '2023-07-23',
|
||||
statusIcon: 'icon-infomation',
|
||||
statusIconColor: 'red',
|
||||
avatarArr: [
|
||||
{
|
||||
imgSrc: 'https://avatars.githubusercontent.com/u/48074435?v=4'
|
||||
},
|
||||
{
|
||||
imgSrc: 'https://avatars.githubusercontent.com/u/40119767?v=4'
|
||||
},
|
||||
{
|
||||
imgSrc: 'https://avatars.githubusercontent.com/u/48074435?v=4'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
checked: false,
|
||||
isOpen: false,
|
||||
title: 'Import Bug Fix',
|
||||
tags: ['线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化', '线上故障', '功能优化'],
|
||||
index: 1,
|
||||
userName: '李轩杨',
|
||||
createdTime: '2023-07-22',
|
||||
milestoneName: '里程碑名称',
|
||||
midNum: 1,
|
||||
commentsNum: 23,
|
||||
updateTime: '2023-07-23'
|
||||
}
|
||||
];
|
||||
const updateCheckedKey = ref(0);
|
||||
const updateChecked = (checked:boolean, item:object, index:number) => {
|
||||
|
||||
IssueItemData[index].checked = checked;
|
||||
|
||||
updateCheckedKey.value += 1;
|
||||
};
|
||||
|
||||
const handleComments = (item:object, index:number) => {
|
||||
|
||||
};
|
||||
|
||||
const handleAvatar = (item:object, index:number) => {
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
| ------------ | ------------ | --------------------------------- | ------ | ------ |
|
||||
| data | 列表数据 | array(row参数见下表props(data)) | | [] |
|
||||
| hideChecked? | 隐藏checkbox | boolean | | false |
|
||||
|
||||
### Props(data)
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|-----------|------------------------|----------------------------|----------|-----------|
|
||||
| checked? | 是否选中 | boolean | | false |
|
||||
| isOpen? | 是否开启 | boolean | | false |
|
||||
| title | 标题 | string | | |
|
||||
| tags | 标签数组 | array | | |
|
||||
| indexLabel? | index自定义名称 | string \| number | | |
|
||||
| userName | 用户名 | string | | |
|
||||
| createdTime | 创建时间 | string | | |
|
||||
| milestoneName | 里程碑名称 | string | | |
|
||||
| midNum? | 中间布局数值 | string \| number | | |
|
||||
| commentsNum | 评论数 | string \| number | | |
|
||||
| updateTime | 更新时间 | string | | |
|
||||
| statusIcon? | 状态颜色 | string | | |
|
||||
| statusIconColor? | 状态icon | string | | |
|
||||
| avatarArr? | 右侧头像列表 | array | 例如:[{imgSrc:'xxx'}] | |
|
||||
|
||||
### Emits
|
||||
|
||||
| 方法 | 说明 | 返回值 |
|
||||
|-----------------|------------------------------------|---------------------|
|
||||
| updateChecked | 点击checkbox触发 | checked, item, index(分别为:是否选中,当前行对象,index索引) |
|
||||
| handleComments | 点击评论数触发 | item, index(分别为:当前行对象,index索引) |
|
||||
| handleMidNum | 点击中间数字触发 | item, index(分别为:当前行对象,index索引) |
|
||||
| handleAvatar | 点击头像区域触发 | item, index(分别为:当前行对象,index索引) |
|
||||
| handleTitle | 点击标题触发 | item, index(分别为:当前行对象,index索引) |
|
||||
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|---------------------|---------------------------------------------|
|
||||
| checkbox | checkbox区域插槽 |
|
||||
| tags | 标签区域插槽 |
|
||||
| status | 索引前icon区域插槽 |
|
||||
| midNum | 中间列区域插槽 |
|
||||
| right | 右侧区域插槽 |
|
||||
| avatar | 头像列表区域插槽 |
|
||||
|
||||
184
src/components/IssueItem/index.vue
Normal file
184
src/components/IssueItem/index.vue
Normal file
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<section >
|
||||
<div class="g-issue-item" v-for="(item,index) in data" :key="index">
|
||||
<div class="g-issue-item-card">
|
||||
<div class="g-issue-item-card-checked" v-if="!hideChecked">
|
||||
<slot name="checkbox">
|
||||
<d-checkbox v-model="item.checked" @change="emits('updateChecked',item.checked,item,index)" />
|
||||
</slot>
|
||||
</div>
|
||||
<div class="g-issue-item-left">
|
||||
<div class="g-issue-item-left-header">
|
||||
<div class="g-issue-item-left-header-title">
|
||||
<d-icon name="icon-lock-private" v-if="!item.isOpen"></d-icon>
|
||||
<slot name="title"></slot>
|
||||
<p v-if='!$slots.title' @click="emits('handleTitle',item.checked,item,index)">{{item.title}}</p>
|
||||
<slot name="tags">
|
||||
<template v-for="(tag,index) in item.tags" :key="index">
|
||||
<custom-tag
|
||||
color="#ffffff"
|
||||
border-color="#606060"
|
||||
bg-color="#606060"
|
||||
:title="tag"
|
||||
/>
|
||||
</template>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="g-issue-item-left-content">
|
||||
<span>
|
||||
<slot name="status">
|
||||
<d-icon :color="item.statusIconColor" :name="item.statusIcon ? item.statusIcon : 'icon-start-use'"></d-icon> {{ item.indexLabel || `#${index + 1}` }}
|
||||
</slot>
|
||||
</span>
|
||||
<span class="g-issue-item-dot">
|
||||
</span>
|
||||
<span>
|
||||
{{item.userName}} <Time :time="item.createdTime"/>创建
|
||||
</span>
|
||||
|
||||
<template v-if="item.milestoneName">
|
||||
<span class="g-issue-item-dot"></span>
|
||||
<span><d-icon name="icon-milestone"></d-icon> {{ item.milestoneName }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-issue-item-right">
|
||||
<slot name="right">
|
||||
|
||||
<div class="g-issue-item-right-num" @click="emits('handleMidNum',item,index)">
|
||||
<slot name="midNum">
|
||||
<d-icon name="icon-merge-request"></d-icon> {{ item.midNum }}
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="g-issue-item-right-time">
|
||||
<span class="g-issue-item-right-handle" >
|
||||
<div class="g-issue-item-right-avatar" @click="emits('handleAvatar',item,index)">
|
||||
<slot name="avatar">
|
||||
<template v-for="(head,index) in item.avatarArr && item.avatarArr.slice(0,3)" :key="index">
|
||||
<GAvatar :src="head.imgSrc" :width="20" :height="20"></GAvatar>
|
||||
</template>
|
||||
</slot>
|
||||
</div>
|
||||
<span @click="emits('handleComments',item,index)">
|
||||
<d-icon name="icon-message"></d-icon> {{ item.commentsNum }}
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<Time :time="item.updateTime"/>更新
|
||||
</span>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { IssueItemRow } from '@/components/IssueItem/types';
|
||||
import CustomTag from '@/components/CustomTag/index.vue';
|
||||
import Time from '@/components/Time/index.vue';
|
||||
|
||||
withDefaults(defineProps<{
|
||||
data: IssueItemRow[];
|
||||
hideChecked: boolean
|
||||
}>(), {
|
||||
data: () => [],
|
||||
hideChecked: false
|
||||
});
|
||||
|
||||
const emits = defineEmits(['updateChecked', 'handleTitle', 'handleComments', 'handleMidNum', 'handleAvatar']);
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$g-issue-item-border-radius: 4px;
|
||||
$g-issue-item-text-color: #606060;
|
||||
|
||||
.g-issue-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.devui-icon__container {
|
||||
vertical-align: middle;
|
||||
}
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
&-dot {
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background-color: $g-issue-item-text-color;
|
||||
border-radius: 50%;
|
||||
margin-top: 8px;
|
||||
}
|
||||
&-card {
|
||||
display: flex;
|
||||
&-checked {
|
||||
margin: 20px 16px auto 0;
|
||||
}
|
||||
}
|
||||
&-left {
|
||||
&-header {
|
||||
&-title {
|
||||
font-size: 18px;
|
||||
margin-right: 16px;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
.g-custom-tag {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.devui-icon__container {
|
||||
margin-right: 4px;
|
||||
}
|
||||
p{
|
||||
margin-top: -2px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-content {
|
||||
display: flex;
|
||||
margin-top: 12px;
|
||||
span {
|
||||
display: block;
|
||||
margin-right: 16px;
|
||||
color: $g-issue-item-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
&-right {
|
||||
display: flex;
|
||||
color: $g-issue-item-text-color;
|
||||
flex-shrink: 0;
|
||||
&-num {
|
||||
margin: 20px 48px;
|
||||
}
|
||||
&-handle {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
cursor: pointer;
|
||||
.devui-avatar {
|
||||
display: flex;
|
||||
margin-left: -8px;
|
||||
}
|
||||
}
|
||||
&-avatar {
|
||||
display: flex;
|
||||
margin-right: 8px;
|
||||
width: 40px;
|
||||
flex-flow: row-reverse;
|
||||
}
|
||||
&-time {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
20
src/components/IssueItem/types.ts
Normal file
20
src/components/IssueItem/types.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
type avatarObj = {
|
||||
imgSrc: string
|
||||
}
|
||||
export type IssueItemRow = {
|
||||
checked: boolean,
|
||||
isOpen?: boolean,
|
||||
title?: string
|
||||
tags: Array<string>,
|
||||
indexLabel?: string | number,
|
||||
userName: string
|
||||
createdTime: string
|
||||
milestoneName: string
|
||||
midNum?:string | number
|
||||
commentsNum: string | number
|
||||
updateTime: string
|
||||
statusIcon?: string
|
||||
statusIconColor?: string
|
||||
avatarArr?: Array<avatarObj>
|
||||
}
|
||||
Reference in New Issue
Block a user