feat(projects): 微调

This commit is contained in:
2026-06-17 19:27:17 +08:00
parent 1543bf76a9
commit 31344f1d58
18 changed files with 876 additions and 219 deletions

View File

@@ -2,6 +2,8 @@ import { computed, defineComponent, h, ref } from 'vue';
import type { Component, PropType } from 'vue';
import { ElButton, ElPopover, ElTooltip } from 'element-plus';
import { $t } from '@/locales';
import IconMdiDotsHorizontal from '~icons/mdi/dots-horizontal';
import IconMdiChevronDown from '~icons/mdi/chevron-down';
export type BusinessTableAction = {
key: string;
@@ -162,11 +164,11 @@ export default defineComponent({
onClick={event => event.stopPropagation()}
>
{props.variant === 'icon' ? (
<icon-mdi-dots-horizontal class="business-table-action-icon" />
<IconMdiDotsHorizontal class="business-table-action-icon" />
) : (
<span class="inline-flex items-center gap-4px">
{$t('common.more')}
<icon-mdi-chevron-down class="text-14px" />
<IconMdiChevronDown class="text-14px" />
</span>
)}
</ElButton>

View File

@@ -0,0 +1,84 @@
<script setup lang="ts">
import { computed } from 'vue';
import { ElTag } from 'element-plus';
defineOptions({ name: 'CurrentUserRoleTags' });
interface Props {
/** 当前登录用户在该对象(产品/项目)的角色;无角色为 []。后端只读计算字段,随登录身份变化 */
roles?: Api.Common.CurrentUserRole[] | null;
/** 无业务角色时的占位文案 */
emptyText?: string;
}
const props = withDefaults(defineProps<Props>(), { roles: () => [], emptyText: '--' });
/**
* 角色族按 roleKey 后缀匹配。
*
* 后端 roleKey 为域前缀风格product_manager / project_manager / product_creator /
* project_creator / *_observer 等(见 src/constants/business.ts 的经理 code
* 文档示例里的裸 creator / implicit_observer 不是真实 key故不能按字面量精确匹配。
*/
function isManagerRole(roleKey: string) {
return /manager$/i.test(roleKey);
}
function isCreatorRole(roleKey: string) {
return /creator$/i.test(roleKey);
}
/** 系统隐式角色:创建者 / 隐式观察者,弱化为淡灰标签 */
function isMuted(roleKey: string) {
return isCreatorRole(roleKey) || /observer$/i.test(roleKey) || roleKey.includes('implicit');
}
const items = computed(() => {
const roles = props.roles ?? [];
// 当前用户是产品经理 / 项目经理时,隐藏创建者标签(隐式观察者不受影响)
const hasManager = roles.some(role => isManagerRole(role.roleKey));
const visibleRoles = hasManager ? roles.filter(role => !isCreatorRole(role.roleKey)) : roles;
return visibleRoles.map((role, index) => ({
key: `${role.roleKey}-${index}`,
roleName: role.roleName,
muted: isMuted(role.roleKey)
}));
});
</script>
<template>
<div v-if="items.length" class="current-user-role-tags">
<ElTag
v-for="item in items"
:key="item.key"
size="small"
effect="plain"
round
:type="item.muted ? 'info' : 'primary'"
:class="{ 'current-user-role-tags__muted': item.muted }"
>
{{ item.roleName }}
</ElTag>
</div>
<span v-else class="current-user-role-tags__empty">{{ emptyText }}</span>
</template>
<style lang="scss" scoped>
.current-user-role-tags {
display: flex;
flex-wrap: wrap;
// 列设置 align="center" 只影响文本流flex 容器需显式居中标签
justify-content: center;
gap: 4px;
}
// 隐式角色(创建者 / 隐式观察者)弱化:在灰色 info 标签基础上再降透明度
.current-user-role-tags__muted {
opacity: 0.65;
}
.current-user-role-tags__empty {
color: var(--el-text-color-placeholder);
}
</style>