chore: establish V1.1 recovery baseline
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Avatar 头像(规范 §22 用户卡片)
|
||||
*
|
||||
* 显示用户头像 + 已实名 / 已审核徽标。
|
||||
* 不变量(AGENTS 第 8 条):头像 URL 来自 OSS 公开链接,不携带任何敏感身份字段。
|
||||
* 用法:
|
||||
* <ui-avatar src="{{user.avatarUrl}}" size="lg"
|
||||
* verified="{{user.verified}}" reviewed="{{user.reviewed}}" />
|
||||
*/
|
||||
Component({
|
||||
options: { addGlobalClass: true },
|
||||
properties: {
|
||||
src: { type: String, value: '' },
|
||||
size: { type: String, value: 'md' }, // sm|md|lg|xl
|
||||
shape: { type: String, value: 'circle' }, // circle|square
|
||||
verified: { type: Boolean, value: false },
|
||||
reviewed: { type: Boolean, value: false },
|
||||
showBadge: { type: Boolean, value: true },
|
||||
// 兜底默认头像(不依赖外部资源)
|
||||
defaultText: { type: String, value: '' }, // 没图时显示首字(如"王")
|
||||
},
|
||||
data: {
|
||||
loadError: false,
|
||||
},
|
||||
methods: {
|
||||
onError() {
|
||||
this.setData({ loadError: true });
|
||||
this.triggerEvent('error', {});
|
||||
},
|
||||
onTap() {
|
||||
this.triggerEvent('tap', {});
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<view
|
||||
class="ui-avatar ui-avatar--{{size}} ui-avatar--{{shape}}"
|
||||
bindtap="onTap"
|
||||
>
|
||||
<image
|
||||
wx:if="{{src && !loadError}}"
|
||||
class="ui-avatar__img"
|
||||
src="{{src}}"
|
||||
mode="aspectFill"
|
||||
binderror="onError"
|
||||
/>
|
||||
<view wx:else class="ui-avatar__fallback">
|
||||
<text wx:if="{{defaultText}}" class="ui-avatar__fallback-text">{{defaultText}}</text>
|
||||
<view wx:else class="ui-avatar__fallback-icon"></view>
|
||||
</view>
|
||||
<view wx:if="{{showBadge && (verified || reviewed)}}" class="ui-avatar__badges">
|
||||
<view wx:if="{{verified}}" class="ui-avatar__badge ui-avatar__badge--verified">实名</view>
|
||||
<view wx:if="{{reviewed}}" class="ui-avatar__badge ui-avatar__badge--reviewed">审核</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,62 @@
|
||||
.ui-avatar {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
background: var(--color-bg-disabled);
|
||||
overflow: hidden;
|
||||
}
|
||||
.ui-avatar--circle { border-radius: 50%; }
|
||||
.ui-avatar--square { border-radius: var(--radius-md); }
|
||||
|
||||
/* 尺寸:sm 60 / md 88 / lg 120 / xl 160 */
|
||||
.ui-avatar--sm { width: 60rpx; height: 60rpx; }
|
||||
.ui-avatar--md { width: 88rpx; height: 88rpx; }
|
||||
.ui-avatar--lg { width: 120rpx; height: 120rpx; }
|
||||
.ui-avatar--xl { width: 160rpx; height: 160rpx; }
|
||||
|
||||
.ui-avatar__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
.ui-avatar__fallback {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--color-primary-light);
|
||||
}
|
||||
.ui-avatar__fallback-text {
|
||||
font-size: var(--font-size-lg);
|
||||
color: var(--color-primary);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
.ui-avatar__fallback-icon {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
border-radius: 50%;
|
||||
background: var(--color-primary);
|
||||
opacity: 0.6;
|
||||
}
|
||||
.ui-avatar__badges {
|
||||
position: absolute;
|
||||
bottom: -4rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
gap: 6rpx;
|
||||
}
|
||||
.ui-avatar__badge {
|
||||
font-size: 16rpx;
|
||||
line-height: 1;
|
||||
padding: 4rpx 8rpx;
|
||||
border-radius: var(--radius-full);
|
||||
color: #FFFFFF;
|
||||
font-weight: var(--font-weight-medium);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui-avatar__badge--verified { background: var(--color-success); }
|
||||
.ui-avatar__badge--reviewed { background: var(--color-info); }
|
||||
|
||||
/* 小尺寸时隐藏徽标避免溢出 */
|
||||
.ui-avatar--sm .ui-avatar__badges { display: none; }
|
||||
Reference in New Issue
Block a user