Files
platforms/frontend/platform_admin/src/views/resource/ResourceAccountSummary.vue

207 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
功能展示账户类资源的头像用户名唯一标识和创建时间摘要
版本v1.1.0
-->
<template>
<a-card class="account-card" :bordered="false">
<div class="account-summary" :class="{ 'account-summary-text': !avatarEnabled }">
<div v-if="avatarEnabled" class="avatar-column">
<button
class="avatar-button"
type="button"
:disabled="mode === 'detail' || !avatarEnabled"
:aria-label="mode === 'detail' || !avatarEnabled ? '账户头像' : '选择账户头像'"
@click="chooseAvatar"
>
<a-avatar :size="120" class="account-avatar">
<img :src="avatarUrl" alt="账户头像" />
</a-avatar>
<span v-if="mode !== 'detail' && avatarEnabled" class="camera-badge"><icon-camera /></span>
</button>
<input
ref="avatarInput"
class="avatar-input"
type="file"
accept="image/jpeg,image/png"
@change="onAvatarSelected"
/>
<span v-if="mode !== 'detail' && avatarEnabled" class="avatar-help">JPG/PNG最大 2 MB</span>
<a-button v-if="mode !== 'detail' && avatarEnabled && canClear" type="text" size="mini" @click="emit('clear-avatar')">
恢复默认头像
</a-button>
</div>
<div class="identity-summary">
<h2>{{ summaryTitle }}</h2>
<dl>
<div>
<dt>用户名</dt>
<dd>{{ String(record.username ?? '保存后确定') }}</dd>
</div>
<div>
<dt>唯一标识</dt>
<dd class="identity-value">{{ String(record.identity ?? '保存后生成') }}</dd>
</div>
<div>
<dt>创建时间</dt>
<dd>{{ displayRawValue('created_at', record.created_at) }}</dd>
</div>
</dl>
</div>
</div>
</a-card>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { IconCamera } from '@arco-design/web-vue/es/icon';
import { displayRawValue } from '@/api/resource-display';
import type { ResourceRow, RecordPageMode } from '@/api/resource-page-rules';
const props = defineProps<{
mode: RecordPageMode;
title: string;
record: ResourceRow;
avatarUrl: string;
avatarEnabled: boolean;
canClear: boolean;
}>();
const emit = defineEmits<{
'select-avatar': [file: File];
'clear-avatar': [];
}>();
const avatarInput = ref<HTMLInputElement>();
const summaryTitle = computed(() =>
String(
props.record.name ??
props.record.display_name ??
props.record.real_name ??
props.record.username ??
(props.mode === 'create' ? `新建${props.title}` : props.title),
),
);
function chooseAvatar() {
if (props.mode !== 'detail' && props.avatarEnabled)
avatarInput.value?.click();
}
function onAvatarSelected(event: Event) {
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
if (file) emit('select-avatar', file);
input.value = '';
}
</script>
<style scoped lang="less">
.account-card {
border-radius: 10px;
}
.account-summary {
display: grid;
grid-template-columns: 180px minmax(360px, 500px);
justify-content: center;
align-items: center;
gap: 44px;
min-height: 168px;
padding: 18px 32px;
}
.account-summary-text {
grid-template-columns: minmax(420px, 720px);
justify-content: start;
min-height: 116px;
padding: 14px 32px;
}
.account-summary-text .identity-summary {
width: 100%;
}
.avatar-column {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.avatar-button {
position: relative;
padding: 0;
background: transparent;
border: 0;
cursor: pointer;
}
.avatar-button:disabled {
cursor: default;
}
.account-avatar {
background: var(--color-fill-3);
}
.account-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.camera-badge {
position: absolute;
right: 2px;
bottom: 2px;
display: grid;
width: 34px;
height: 34px;
place-items: center;
color: rgb(var(--primary-6));
background: var(--color-bg-2);
border: 3px solid var(--color-bg-2);
border-radius: 50%;
box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
}
.avatar-input {
display: none;
}
.avatar-help {
color: var(--color-text-3);
font-size: 12px;
}
.identity-summary h2 {
margin: 0 0 14px;
color: var(--color-text-1);
font-size: 20px;
}
.identity-summary dl,
.identity-summary dd {
margin: 0;
}
.identity-summary dl > div {
display: grid;
grid-template-columns: 92px minmax(0, 1fr);
align-items: center;
min-height: 38px;
}
.identity-summary dt {
color: var(--color-text-3);
text-align: right;
}
.identity-summary dd {
color: var(--color-text-1);
font-size: 15px;
}
.identity-value {
color: rgb(var(--primary-6)) !important;
word-break: break-all;
}
@media (max-width: 760px) {
.account-summary {
grid-template-columns: 1fr;
gap: 20px;
padding: 20px 8px;
}
.identity-summary {
width: min(100%, 440px);
margin: 0 auto;
}
.account-summary-text {
grid-template-columns: 1fr;
min-height: auto;
padding: 14px 8px;
}
}
</style>