chore: establish V1.1 recovery baseline
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* ActivityCard 活动卡片(规范 §43-46)
|
||||
*
|
||||
* 不变量(AGENTS.md 第 1 条):feeType=paid 仅作展示字段,前端不实现任何支付入口。
|
||||
* "公益免费"作为主要视觉标识突出展示。
|
||||
*/
|
||||
Component({
|
||||
options: { addGlobalClass: true },
|
||||
properties: {
|
||||
activity: { type: Object, value: null },
|
||||
showStatusBadge: { type: Boolean, value: true },
|
||||
compact: { type: Boolean, value: false }, // 紧凑模式(首页推荐位)
|
||||
},
|
||||
methods: {
|
||||
onTap() {
|
||||
if (!this.data.activity) return;
|
||||
this.triggerEvent('tap', { activityId: this.data.activity.activityId });
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"ui-status-badge": "../status-badge/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<view class="ui-act {{compact ? 'ui-act--compact' : ''}}" bindtap="onTap">
|
||||
<view class="ui-act__cover">
|
||||
<image
|
||||
wx:if="{{activity.coverUrl}}"
|
||||
class="ui-act__cover-img"
|
||||
src="{{activity.coverUrl}}"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view wx:else class="ui-act__cover-placeholder">
|
||||
<view class="ui-act__cover-icon"></view>
|
||||
</view>
|
||||
<view class="ui-act__fee-badge {{activity.feeType === 'paid' ? 'ui-act__fee-badge--paid' : 'ui-act__fee-badge--free'}}">
|
||||
{{activity.feeType === 'paid' ? '付费' : '公益免费'}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="ui-act__body">
|
||||
<view class="ui-act__title">{{activity.title}}</view>
|
||||
<view class="ui-act__meta">
|
||||
<text class="ui-act__time">{{activity.startAtText || activity.startAt}}</text>
|
||||
<text wx:if="{{activity.location}}"> · {{activity.location}}</text>
|
||||
</view>
|
||||
<view wx:if="{{activity.organizer}}" class="ui-act__meta ui-act__organizer">
|
||||
主办:{{activity.organizer}}
|
||||
</view>
|
||||
<view wx:if="{{activity.suitableFor}}" class="ui-act__meta">
|
||||
适合:{{activity.suitableFor}}
|
||||
</view>
|
||||
<view wx:if="{{!compact}}" class="ui-act__intro">{{activity.intro}}</view>
|
||||
<view class="ui-act__footer">
|
||||
<view class="ui-act__capacity">
|
||||
<text wx:if="{{activity.capacity}}">容量 {{activity.capacity}}</text>
|
||||
</view>
|
||||
<view wx:if="{{showStatusBadge}}">
|
||||
<ui-status-badge
|
||||
wx:if="{{activity.status === 'registration_open'}}"
|
||||
kind="success"
|
||||
label="报名中"
|
||||
/>
|
||||
<ui-status-badge
|
||||
wx:elif="{{activity.status === 'registration_closed'}}"
|
||||
kind="warning"
|
||||
label="报名截止"
|
||||
/>
|
||||
<ui-status-badge
|
||||
wx:elif="{{activity.status === 'ongoing'}}"
|
||||
kind="info"
|
||||
label="进行中"
|
||||
/>
|
||||
<ui-status-badge
|
||||
wx:elif="{{activity.status === 'ended'}}"
|
||||
kind="disabled"
|
||||
label="已结束"
|
||||
/>
|
||||
<ui-status-badge
|
||||
wx:elif="{{activity.status === 'cancelled'}}"
|
||||
kind="danger"
|
||||
label="已取消"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,108 @@
|
||||
.ui-act {
|
||||
background: var(--color-bg-card);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-card);
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
.ui-act__cover {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background: var(--color-bg-disabled);
|
||||
}
|
||||
.ui-act__cover-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
.ui-act__cover-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--color-primary-light);
|
||||
}
|
||||
.ui-act__cover-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background: var(--color-primary);
|
||||
opacity: 0.4;
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
.ui-act__fee-badge {
|
||||
position: absolute;
|
||||
top: var(--spacing-2);
|
||||
right: var(--spacing-2);
|
||||
padding: 6rpx 14rpx;
|
||||
border-radius: var(--radius-full);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.ui-act__fee-badge--free {
|
||||
background: var(--color-success);
|
||||
}
|
||||
.ui-act__fee-badge--paid {
|
||||
background: var(--color-text-tertiary);
|
||||
}
|
||||
.ui-act__body {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
}
|
||||
.ui-act__title {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text-primary);
|
||||
line-height: var(--line-height-tight);
|
||||
margin-bottom: var(--spacing-1);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ui-act__meta {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-text-tertiary);
|
||||
line-height: var(--line-height-normal);
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
.ui-act__organizer {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
.ui-act__intro {
|
||||
margin-top: var(--spacing-2);
|
||||
font-size: var(--font-size-md);
|
||||
color: var(--color-text-secondary);
|
||||
line-height: var(--line-height-relaxed);
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ui-act__footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: var(--spacing-3);
|
||||
}
|
||||
.ui-act__capacity {
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--color-text-tertiary);
|
||||
}
|
||||
.ui-act--compact {
|
||||
display: flex;
|
||||
height: 200rpx;
|
||||
}
|
||||
.ui-act--compact .ui-act__cover {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ui-act--compact .ui-act__body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
}
|
||||
.ui-act--compact .ui-act__intro {
|
||||
display: none;
|
||||
}
|
||||
Reference in New Issue
Block a user