feat: 搭建微信小程序展示端
- 初始化小程序工程配置与类型声明 - 增加首页、律所、律师列表、详情与历史页面 - 补充公共组件、运行时配置与示例素材
This commit is contained in:
5
frontend_miniprogram/miniprogram/pages/firm/index.json
Normal file
5
frontend_miniprogram/miniprogram/pages/firm/index.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"app-header": "/components/app-header/app-header"
|
||||
}
|
||||
}
|
||||
182
frontend_miniprogram/miniprogram/pages/firm/index.less
Normal file
182
frontend_miniprogram/miniprogram/pages/firm/index.less
Normal file
@@ -0,0 +1,182 @@
|
||||
.firm-page {
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.hero-section {
|
||||
position: relative;
|
||||
height: 520rpx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 80rpx;
|
||||
/* Space for overlap */
|
||||
}
|
||||
|
||||
.hero-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.hero-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* Updated gradient to match Burgundy Red */
|
||||
background: linear-gradient(to bottom, rgba(142, 34, 48, 0.4), rgba(92, 13, 21, 0.9));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0 var(--spacing-lg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 72rpx;
|
||||
}
|
||||
|
||||
.firm-stats {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
padding: 14rpx 22rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.32);
|
||||
background: linear-gradient(120deg, rgba(10, 21, 34, 0.62), rgba(19, 38, 56, 0.36));
|
||||
box-shadow: 0 10rpx 28rpx rgba(7, 15, 27, 0.35), inset 0 1rpx 0 rgba(255, 255, 255, 0.24);
|
||||
backdrop-filter: blur(10rpx);
|
||||
-webkit-backdrop-filter: blur(10rpx);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 120rpx;
|
||||
}
|
||||
|
||||
.stat-num {
|
||||
font-size: 44rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.2;
|
||||
text-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: rgba(242, 247, 252, 0.92);
|
||||
margin-top: 4rpx;
|
||||
text-shadow: 0 1rpx 8rpx rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
|
||||
.stat-divider {
|
||||
width: 2rpx;
|
||||
height: 40rpx;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.52), rgba(255, 255, 255, 0.12));
|
||||
margin: 0 24rpx;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
margin-top: -60rpx;
|
||||
background: var(--bg-page);
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
padding: var(--spacing-lg) var(--spacing-md);
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.address-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--spacing-md);
|
||||
margin-bottom: var(--spacing-lg);
|
||||
background: #fff;
|
||||
box-shadow: var(--shadow-base);
|
||||
}
|
||||
|
||||
.address-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.address-label {
|
||||
font-size: 24rpx;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.address-text {
|
||||
font-size: 28rpx;
|
||||
color: var(--text-main);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.address-icon {
|
||||
font-size: 32rpx;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
font-size: 28rpx;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.8;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.tags-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.area-tag {
|
||||
font-size: 26rpx;
|
||||
color: var(--primary-color);
|
||||
background: rgba(142, 34, 48, 0.08);
|
||||
/* Primary color opacity */
|
||||
padding: 10rpx 24rpx;
|
||||
border-radius: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
padding: 20rpx var(--spacing-md);
|
||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.05);
|
||||
z-index: 10;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
background: var(--primary-color);
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 50rpx;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 20rpx rgba(142, 34, 48, 0.3);
|
||||
}
|
||||
|
||||
.cta-btn::after {
|
||||
border: none;
|
||||
}
|
||||
71
frontend_miniprogram/miniprogram/pages/firm/index.ts
Normal file
71
frontend_miniprogram/miniprogram/pages/firm/index.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { getFirmProfile } from '../../api/open';
|
||||
import type { FirmInfo } from '../../types/card';
|
||||
|
||||
function createEmptyFirm(): FirmInfo {
|
||||
return {
|
||||
id: '',
|
||||
name: '',
|
||||
logo: '',
|
||||
intro: '',
|
||||
hotlinePhone: '',
|
||||
hqAddress: '',
|
||||
hqLatitude: 0,
|
||||
hqLongitude: 0,
|
||||
officeCount: 0,
|
||||
lawyerCount: 0,
|
||||
heroImage: '',
|
||||
officeList: [],
|
||||
practiceAreas: [],
|
||||
};
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
firm: createEmptyFirm(),
|
||||
loading: false,
|
||||
},
|
||||
onLoad() {
|
||||
this.loadFirmProfile();
|
||||
},
|
||||
async loadFirmProfile() {
|
||||
this.setData({ loading: true });
|
||||
try {
|
||||
const firm = await getFirmProfile();
|
||||
this.setData({ firm });
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : '加载事务所信息失败';
|
||||
wx.showToast({
|
||||
title: message,
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.setData({ loading: false });
|
||||
}
|
||||
},
|
||||
goLawyerList() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/lawyer-list/index',
|
||||
});
|
||||
},
|
||||
openLocation() {
|
||||
const { firm } = this.data;
|
||||
if (!firm.hqLatitude || !firm.hqLongitude) {
|
||||
wx.showToast({
|
||||
title: '暂未配置地图位置',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.openLocation({
|
||||
latitude: firm.hqLatitude,
|
||||
longitude: firm.hqLongitude,
|
||||
name: firm.name,
|
||||
address: firm.hqAddress,
|
||||
scale: 18,
|
||||
fail: () => {
|
||||
wx.showToast({ title: '打开地图失败', icon: 'none' });
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
60
frontend_miniprogram/miniprogram/pages/firm/index.wxml
Normal file
60
frontend_miniprogram/miniprogram/pages/firm/index.wxml
Normal file
@@ -0,0 +1,60 @@
|
||||
<view class="container-page firm-page">
|
||||
<!-- Custom Navigation Bar with transparent background initially if possible, or just standard -->
|
||||
<app-header title="{{firm.name}}" back="{{false}}" background="rgba(255,255,255,0.9)"></app-header>
|
||||
|
||||
<scroll-view class="page-content" scroll-y="true" type="list">
|
||||
|
||||
<!-- Hero Section -->
|
||||
<view class="hero-section">
|
||||
<image wx:if="{{firm.heroImage}}" class="hero-bg" mode="aspectFill" src="{{firm.heroImage}}"></image>
|
||||
<view wx:if="{{!firm.heroImage}}" class="hero-overlay"></view>
|
||||
<view class="hero-content">
|
||||
<view class="firm-stats">
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">{{firm.officeCount}}</text>
|
||||
<text class="stat-label">办公机构</text>
|
||||
</view>
|
||||
<view class="stat-divider"></view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">{{firm.lawyerCount}}</text>
|
||||
<text class="stat-label">专业律师</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Content Container (Overlapping) -->
|
||||
<view class="content-container">
|
||||
|
||||
<!-- Address Card -->
|
||||
<view class="card address-card" bindtap="openLocation">
|
||||
<view class="address-info">
|
||||
<text class="address-label">总部地址</text>
|
||||
<text class="address-text">{{firm.hqAddress}}</text>
|
||||
</view>
|
||||
<text class="address-icon">></text>
|
||||
</view>
|
||||
|
||||
<!-- Intro Section -->
|
||||
<view class="section">
|
||||
<view class="section-title">律所简介</view>
|
||||
<text class="intro-text">{{firm.intro}}</text>
|
||||
</view>
|
||||
|
||||
<!-- Practice Areas -->
|
||||
<view class="section">
|
||||
<view class="section-title">专业领域</view>
|
||||
<view class="tags-wrapper">
|
||||
<view class="area-tag" wx:for="{{firm.practiceAreas}}" wx:key="*this">{{item}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="safe-area-bottom" style="height: 120rpx;"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- Bottom CTA -->
|
||||
<view class="bottom-bar safe-area-bottom">
|
||||
<button class="cta-btn" bindtap="goLawyerList">查找专业律师</button>
|
||||
</view>
|
||||
</view>
|
||||
Reference in New Issue
Block a user