feat: 搭建微信小程序展示端

- 初始化小程序工程配置与类型声明

- 增加首页、律所、律师列表、详情与历史页面

- 补充公共组件、运行时配置与示例素材
This commit is contained in:
2026-03-20 12:44:31 +08:00
parent 86c321e832
commit 9605384edc
87 changed files with 26373 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,97 @@
.lawyer-card {
display: flex;
align-items: center;
background: var(--bg-card);
border-radius: var(--border-radius-base);
padding: var(--spacing-md);
box-shadow: var(--shadow-sm);
position: relative;
overflow: hidden;
transition: transform 0.1s;
}
.lawyer-card:active {
transform: scale(0.98);
}
.avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
border: 4rpx solid var(--bg-page);
flex-shrink: 0;
margin-right: var(--spacing-sm);
background: var(--bg-surface);
}
.content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
justify-content: center;
}
.header-row {
display: flex;
align-items: center;
margin-bottom: 6rpx;
}
.name {
font-size: 32rpx;
font-weight: 600;
color: var(--text-main);
margin-right: 12rpx;
}
.title {
font-size: 22rpx;
color: var(--primary-color);
background: rgba(142, 34, 48, 0.08);
/* Primary opacity */
padding: 2rpx 10rpx;
border-radius: 8rpx;
font-weight: 500;
}
.office {
font-size: 24rpx;
color: var(--text-tertiary);
margin-bottom: 12rpx;
}
.tags-row {
display: flex;
flex-wrap: wrap;
gap: 8rpx;
}
.tag {
font-size: 20rpx;
color: var(--text-secondary);
background: var(--bg-page);
padding: 4rpx 12rpx;
border-radius: 6rpx;
}
.tag-more {
font-size: 20rpx;
color: var(--text-tertiary);
padding: 4rpx 0;
}
.action-col {
margin-left: var(--spacing-md);
display: flex;
align-items: center;
}
.consult-btn {
font-size: 24rpx;
color: var(--primary-color);
border: 1rpx solid var(--primary-color);
padding: 6rpx 20rpx;
border-radius: 24rpx;
font-weight: 500;
}

View File

@@ -0,0 +1,33 @@
Component({
data: {
specialtiesText: '',
},
properties: {
lawyer: {
type: Object,
value: null,
},
showOffice: {
type: Boolean,
value: true,
},
},
observers: {
lawyer(lawyer: { specialties?: string[] } | null) {
const specialties =
lawyer && Array.isArray(lawyer.specialties) ? lawyer.specialties : [];
this.setData({
specialties, // Expose array for wx:for
specialtiesText: specialties.join(' | '),
});
},
},
methods: {
handleTap() {
const lawyer = this.properties.lawyer as { id?: string } | null;
this.triggerEvent('select', {
id: lawyer && typeof lawyer.id === 'string' ? lawyer.id : '',
});
},
},
});

View File

@@ -0,0 +1,21 @@
<view class="lawyer-card" bindtap="handleTap">
<image class="avatar" src="{{lawyer.avatar}}" mode="aspectFill"></image>
<view class="content">
<view class="header-row">
<text class="name">{{lawyer.name}}</text>
<text class="title">{{lawyer.title}}</text>
</view>
<text wx:if="{{showOffice}}" class="office">{{lawyer.office}}</text>
<view class="tags-row">
<text class="tag" wx:for="{{specialties}}" wx:key="*this" wx:if="{{index < 3}}">{{item}}</text>
<text class="tag-more" wx:if="{{specialties.length > 3}}">...</text>
</view>
</view>
<view class="action-col">
<text class="consult-btn">咨询</text>
</view>
</view>