搜索结果列表页面开发
This commit is contained in:
38
src/components/MemberItems/README.md
Normal file
38
src/components/MemberItems/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
TS接口文档可以查看同文件夹下的types.ts, demo可以访问/demo777进行查看
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|----------------|-------------------------|-------------------------------|-----------|-------|
|
||||
| data | 人员列表数据 | Array<MemberItemData> | — | [] |
|
||||
| size? | 头像尺寸 | number | — | 48 |
|
||||
| round? | 是否为圆形头像 | boolean | — | true |
|
||||
| statusOptions? | 用户身份下拉数据项 | {label: string; value: string | number}[] | — | [] |
|
||||
| isHandling? | 是否处于事务处理中,设为true会禁用右边操作 | boolean | — | false |
|
||||
| isManager? | 当前用户是否为管理员 | boolean | — | false |
|
||||
| showTags? | 是否显示身份标签 | boolean | — | true |
|
||||
|
||||
### Emits
|
||||
|
||||
注意:以下事件都是组件内部对应的按钮点击触发,如果用插槽自定义对应区域的内容的话,事件自行监听即可
|
||||
|
||||
| 方法 | 说明 | 返回值 |
|
||||
|-----------|--------|-----------------------|
|
||||
| cancelInvited | 取消邀请 | { data: MemberItemData; index: number } |
|
||||
| exitProject | 退出项目 | { data: MemberItemData; index: number } |
|
||||
| removeMember | 移除成员 | { data: MemberItemData; index: number } |
|
||||
| applyPass | 通过申请 | { data: MemberItemData; index: number } |
|
||||
| applyRefuse | 拒绝申请 | { data: MemberItemData; index: number } |
|
||||
| statusChange | 成员身份变化 | { data: MemberItemData; index: number } |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|--------------------|-------------------------------|
|
||||
| avatar | 组件头像区域插槽 |
|
||||
| name | 组件名称区域插槽 |
|
||||
| tags | 组件标签区域插槽 |
|
||||
| extra-tags | 组件额外标签区域插槽,在只对当前组件标签进行拓展时可以使用 |
|
||||
| status | 组件成员身份选择区域插槽 |
|
||||
| action | 组件动作区域插槽 |
|
||||
| extra-action | 组件额外动作区域插槽,在只对当前组件标签进行拓展时可以使用 |
|
||||
343
src/components/MemberItems/index.vue
Normal file
343
src/components/MemberItems/index.vue
Normal file
@@ -0,0 +1,343 @@
|
||||
<template>
|
||||
<section class="g-member-items">
|
||||
<div
|
||||
v-for="(item, index) in data"
|
||||
:key="index"
|
||||
class="g-member-items-item g-border-bottom"
|
||||
:class="{ 'is-last-item': index === data.length - 1 }"
|
||||
>
|
||||
<div class="g-member-items-item-info">
|
||||
<div class="g-member-items-item-avatar">
|
||||
<slot name="avatar" :data="item" :index="index">
|
||||
<router-link :to="item.path">
|
||||
<GAvatar
|
||||
:src="item.imageSrc"
|
||||
:name="item.nickname"
|
||||
:width="size"
|
||||
:height="size"
|
||||
:is_round="round"
|
||||
></GAvatar>
|
||||
</router-link>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="g-member-items-item-names w-[280px]">
|
||||
<slot name="name" :data="item" :index="index">
|
||||
<router-link :to="item.path">
|
||||
<div class="g-member-items-item-nickname flex items-center">
|
||||
<GText class="devui-link-hover">{{ xssPurify(item.nickname) }}</GText>
|
||||
<custom-tag
|
||||
v-if="item.isSelf"
|
||||
class="g-member-items-item-tag shrink-0 ml-2"
|
||||
color="#9FA7B3"
|
||||
border-color="#E4E9F0"
|
||||
bg-color="#ffffff"
|
||||
>
|
||||
自己
|
||||
</custom-tag>
|
||||
</div>
|
||||
<div class="g-member-items-item-userName devui-link-hover ellipsis">@{{ item.userName }}</div>
|
||||
</router-link>
|
||||
</slot>
|
||||
</div>
|
||||
<div v-if="showTags" class="g-member-items-item-tags shrink-0 ml-2">
|
||||
<slot name="tags" :data="item" :index="index">
|
||||
<custom-tag v-if="item.isToBeInvited" class="g-member-items-item-tag">
|
||||
待接受邀请
|
||||
</custom-tag>
|
||||
<custom-tag
|
||||
v-if="item.isManager"
|
||||
class="g-member-items-item-tag"
|
||||
color="#2865E0"
|
||||
border-color="#E4E9F0">
|
||||
管理者
|
||||
</custom-tag>
|
||||
<custom-tag
|
||||
v-if="item.isVisitor && (item.join_way === 'inherit' || !(isManager && isAdmin) )"
|
||||
class="g-member-items-item-tag"
|
||||
color="#0EB07B"
|
||||
border-color="#E4E9F0">
|
||||
浏览者
|
||||
</custom-tag>
|
||||
<custom-tag
|
||||
v-if="item.isDeveloper && (item.join_way === 'inherit' || !(isManager && isAdmin) )"
|
||||
class="g-member-items-item-tag"
|
||||
color="#707A87"
|
||||
border-color="#E4E9F0">
|
||||
开发者
|
||||
</custom-tag>
|
||||
</slot>
|
||||
<!--用户额外补充标志-->
|
||||
<slot name="extra-tags" :data="item" :index="index"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-member-items-item-actions" v-if="item.join_way !== 'inherit'">
|
||||
<slot v-if="isManager && !item.isSelf && isAdmin" name="status" :data="item" :index="index">
|
||||
<div class="g-member-items-item-status">
|
||||
<d-select
|
||||
class="g-member-items-item-status-select g-member-items-item-remove-member"
|
||||
v-model="item.status"
|
||||
:options="item.type === 'GroupMember' ? item?.statusOptions || statusOptions : item?.statusOptions || statusOptions.slice(1)"
|
||||
:disabled="(item.disabledOption || isHandling) || !isAdmin"
|
||||
size="sm"
|
||||
placeholder="身份"
|
||||
@value-change="emits('statusChange', { data: item, index })"
|
||||
>
|
||||
</d-select>
|
||||
</div>
|
||||
</slot>
|
||||
<slot v-if="(isManager) || item.isSelf" name="action" :data="item" :index="index">
|
||||
<div class="g-member-items-item-action">
|
||||
<d-button
|
||||
v-if="item.isToBeInvited && isManager"
|
||||
icon="close"
|
||||
variant="text"
|
||||
:loading="isHandling"
|
||||
class="g-member-items-item-cancel"
|
||||
@click="emits('cancelInvited', { data: item, index })"
|
||||
>
|
||||
撤销邀请
|
||||
</d-button>
|
||||
<d-button
|
||||
v-if="item.isSelf && item.allowedExit"
|
||||
icon="exit"
|
||||
variant="text"
|
||||
:loading="isHandling"
|
||||
class="g-member-items-item-cancel"
|
||||
@click="emits('exitProject', { data: item, index })"
|
||||
>
|
||||
退出{{ item.type === 'GroupMember' ? '组织': '项目' }}
|
||||
</d-button>
|
||||
<d-button
|
||||
v-if="isManager && !item.isToBeInvited && !item.isSelf && !item.isApplying && isAdmin"
|
||||
icon="remove-member-icon"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
:loading="isHandling"
|
||||
class="g-member-items-item-remove-member"
|
||||
@click="emits('removeMember', { data: item, index })"
|
||||
>
|
||||
移除成员
|
||||
</d-button>
|
||||
<template v-if="item.isApplying">
|
||||
<d-button
|
||||
icon="add"
|
||||
variant="text"
|
||||
:loading="isHandling"
|
||||
class="g-member-items-item-pass"
|
||||
@click="emits('applyPass', { data: item, index })"
|
||||
>
|
||||
通过申请
|
||||
</d-button>
|
||||
<d-button
|
||||
icon="close"
|
||||
variant="solid"
|
||||
:loading="isHandling"
|
||||
class="g-member-items-item-refuse"
|
||||
@click="emits('applyRefuse', { data: item, index })"
|
||||
>
|
||||
拒绝申请
|
||||
</d-button>
|
||||
</template>
|
||||
</div>
|
||||
</slot>
|
||||
<slot name="extra-action" :data="item" :index="index"></slot>
|
||||
</div>
|
||||
<d-tooltip position="top" v-else :content="'该成员权限继承自组织,请前往组织管理中调整该组织成员权限'">
|
||||
<div><span class="mr-1">组织成员</span><Icon name="gt-tooltip"/></div>
|
||||
</d-tooltip>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'member-items'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { MemberItemData } from '@/components/MemberItems/types';
|
||||
import CustomTag from '@/components/CustomTag/index.vue';
|
||||
import { xssPurify } from '@/utils';
|
||||
|
||||
withDefaults(defineProps<{
|
||||
data: MemberItemData[];
|
||||
// 头像尺寸
|
||||
size?: number;
|
||||
// 是否显示圆形头像
|
||||
round?: boolean;
|
||||
// 用户身份下拉数据
|
||||
statusOptions?: { name: string; value: string | number }[];
|
||||
// 是否处于事务处理中,设为true会禁用右边操作
|
||||
isHandling?: boolean;
|
||||
// 当前用户是否为管理员
|
||||
isManager?: boolean;
|
||||
// 是否显示标签
|
||||
showTags?: boolean;
|
||||
// 是否是管理者权限
|
||||
isAdmin?: boolean
|
||||
}>(), {
|
||||
data: () => [],
|
||||
size: 48,
|
||||
round: true,
|
||||
statusOptions: () => [
|
||||
{ /** 个人不允许设置为管理员 */
|
||||
name: '管理员',
|
||||
value: '50'
|
||||
},
|
||||
{
|
||||
name: '开发者',
|
||||
value: '30'
|
||||
},
|
||||
{
|
||||
name: '浏览者',
|
||||
value: '10'
|
||||
}
|
||||
],
|
||||
isHandling: false,
|
||||
isManager: false,
|
||||
showTags: true,
|
||||
isAdmin: true
|
||||
});
|
||||
|
||||
const emits = defineEmits<{(e: 'cancelInvited', data: { data: MemberItemData; index: number }): void;
|
||||
(e: 'exitProject', data: { data: MemberItemData; index: number }): void;
|
||||
(e: 'removeMember', data: { data: MemberItemData; index: number }): void;
|
||||
(e: 'applyPass', data: { data: MemberItemData; index: number }): void;
|
||||
(e: 'applyRefuse', data: { data: MemberItemData; index: number }): void;
|
||||
(e: 'statusChange', data: { data: MemberItemData; index: number }): void;
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$g-member-items-border-radius: 4px;
|
||||
$g-member-items-text-color: #2D2D2E;
|
||||
$g-member-items-text-color-second: #707A87;
|
||||
$g-member-items-text-color-third: #606060;
|
||||
$g-member-items-tag-border-color: #D3D3D3;
|
||||
$g-member-items-tag-bg-color: #F5F7F9;
|
||||
.g-member-items {
|
||||
&-item {
|
||||
padding: 14px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
&.is-last-item {
|
||||
border-bottom: none;
|
||||
}
|
||||
&-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: space-between;
|
||||
// width: 50%;
|
||||
}
|
||||
&-avatar {
|
||||
:deep(.devui-avatar) {
|
||||
display: block;
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
:deep(.devui-avatar--style) {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
}
|
||||
&-names {
|
||||
margin-left: 20px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
&-nickname {
|
||||
color: $g-member-items-text-color;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
&-userName {
|
||||
color: $g-member-items-text-color-second;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
margin-top: 8px;
|
||||
}
|
||||
&-tags {
|
||||
margin-left: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
&-tag {
|
||||
// padding: 6px 12px;
|
||||
}
|
||||
&-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
:deep(.devui-button--text) {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
}
|
||||
&-cancel {
|
||||
:deep(.devui-button__icon-fix) {
|
||||
color: #FF3241 !important;
|
||||
}
|
||||
}
|
||||
&-pass {
|
||||
:deep(.devui-button__icon-fix) {
|
||||
color: #0EB07B !important;
|
||||
}
|
||||
}
|
||||
&-status {
|
||||
&-select {
|
||||
:deep(.devui-select__selection) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
}
|
||||
:deep(.devui-select__input) {
|
||||
color: $g-member-items-text-color-third;
|
||||
}
|
||||
:deep(.devui-select__input) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-action {
|
||||
margin-left: 16px;
|
||||
}
|
||||
&-refuse {
|
||||
margin-left: 16px;
|
||||
color: #FF3241;
|
||||
background-color: $g-member-items-tag-bg-color;
|
||||
border: 1px solid $g-member-items-tag-border-color;
|
||||
border-radius: $g-member-items-border-radius;
|
||||
padding: 4px 10px;
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
&:active {
|
||||
opacity: 0.6;
|
||||
}
|
||||
:deep(i) {
|
||||
color: #FF3241;
|
||||
}
|
||||
}
|
||||
&-remove-member {
|
||||
color: $g-member-items-text-color-third;
|
||||
background-color: $g-member-items-tag-bg-color;
|
||||
border: 1px solid $g-member-items-tag-border-color;
|
||||
border-radius: $g-member-items-border-radius;
|
||||
padding: 4px 10px;
|
||||
width: 100px;
|
||||
// &:hover {
|
||||
// opacity: 0.8;
|
||||
// }
|
||||
&:active {
|
||||
opacity: 0.6;
|
||||
}
|
||||
:deep(i) {
|
||||
color: $g-member-items-text-color-third;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
28
src/components/MemberItems/types.ts
Normal file
28
src/components/MemberItems/types.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// 传入的成员列表数据
|
||||
export type MemberItemData = {
|
||||
// 头像图片
|
||||
imageSrc?: null | string;
|
||||
// 用户昵称
|
||||
nickname: string;
|
||||
// 个人中心访问路径
|
||||
path: string;
|
||||
// 用户名
|
||||
userName: string;
|
||||
// 是否为本人
|
||||
isSelf?: boolean;
|
||||
// 是否为管理员
|
||||
isManager?: boolean;
|
||||
// 是否为被邀请人员
|
||||
isToBeInvited?: boolean;
|
||||
// 用户身份
|
||||
status: string | number;
|
||||
// 是否为申请中
|
||||
isApplying?: boolean;
|
||||
// 是否允许退出项目 个人项目本人不允许退出 组织项目最后一个管理员不允许退出
|
||||
allowedExit?: boolean;
|
||||
// 禁用option修改权限
|
||||
disabledOption?: boolean;
|
||||
// 权限下拉列表 用于组织成员设置管理员权限
|
||||
statusOptions?: { name: string, value: string }[]
|
||||
[propName: string]: any;
|
||||
}
|
||||
Reference in New Issue
Block a user