Commit bcc3c9da authored by spc's avatar spc

XingmaLabDetailPage

parent bb73e7ac
...@@ -167,6 +167,20 @@ ...@@ -167,6 +167,20 @@
"style": { "style": {
"navigationBarTitleText": "" "navigationBarTitleText": ""
} }
},
{
"path" : "pages/XingmaLabDetailPage/XingmaLabDetailPage",
"style" :
{
"navigationBarTitleText" : ""
}
},
{
"path" : "pages/XingmaLabPublishPage/XingmaLabPublishPage",
"style" :
{
"navigationBarTitleText" : ""
}
} }
], ],
"subPackages": [ "subPackages": [
......
# 星妈实验室详情页面 (XingmaLabDetailPage)
## 概述
这是一个基于Vue 3 Composition API开发的星妈实验室详情页面组件,用于展示藏品详情、点赞和分享功能。
## 功能特性
- **藏品展示**:展示藏品图片、编号和标题
- **动态时间**:自动显示当前时间
- **点赞功能**:支持点赞/取消点赞状态切换
- **分享功能**:集成uni-app分享API
- **响应式设计**:支持不同屏幕尺寸的适配
- **交互动画**:包含淡入动画和悬停效果
## 文件结构
```
XingmaLabDetailPage/
├── XingmaLabDetailPage.vue # 主组件文件
├── XingmaLabDetailPage.less # 样式文件
├── config.js # 配置文件
└── README.md # 说明文档
```
## 使用方法
### 1. 基本使用
```vue
<template>
<XingmaLabDetailPage />
</template>
<script setup>
import XingmaLabDetailPage from '@/pages/XingmaLabDetailPage/XingmaLabDetailPage.vue'
</script>
```
### 2. 功能说明
#### 藏品信息展示
- 藏品背景图片
- 藏品主图片
- 藏品编号(唯一标识)
- 藏品标题
#### 交互功能
- **点赞按钮**:点击切换点赞状态,显示相应提示
- **分享按钮**:调用uni-app分享功能
#### 时间显示
- 自动显示当前日期和地点
- 格式:YYYY-MM-DD 北京
## 配置说明
### 图片资源配置
`config.js` 中配置图片资源路径:
```javascript
export const xingmaLabDetailConfig = {
baseUrl: 'https://factory-walk.feihe.com',
images: {
background: '/farqbxzczytcami/images/XingmaLabDetailPage/XingmaLabDetailPageBg.png',
picBg: '/farqbxzczytcami/images/XingmaLabDetailPage/XingmaLabDetailPagePicBg.png',
pic: '/farqbxzczytcami/images/XingmaLabDetailPage/XingmaLabDetailPagePic.png',
// ... 其他图片配置
}
}
```
### 文案配置
```javascript
texts: {
title: '快来用星妈会小程序',
collectionNumber: '唯一藏品编号:'
}
```
## 样式定制
### 主要样式类
- `.xingmalabdetailpage`: 主容器
- `.xingmalabdetailpagebg`: 背景图片
- `.xingmalabdetailpagepic`: 藏品主图片
- `.xingmalabdetailpagepicbg`: 图片背景框
- `.xingmalabdetailpagebottomcon`: 底部操作容器
- `.xingmalabdetailpagebottomconlikebtn`: 点赞按钮
- `.xingmalabdetailpagebottomconsharebtn`: 分享按钮
### 响应式断点
- 默认:750rpx 宽度(移动端)
- 响应式:小于750px时自动适配为100vw
### 动画效果
- `fadeIn`: 页面淡入动画
- `slideInUp`: 图片和底部容器从下往上滑入动画
- 点赞状态变化时的视觉反馈
## 交互功能
### 点赞功能
```javascript
const handleLikeClick = () => {
isLiked.value = !isLiked.value
// 显示点赞状态提示
uni.showToast({
title: isLiked.value ? '已点赞' : '取消点赞',
icon: 'success'
})
}
```
### 分享功能
```javascript
const handleShareClick = () => {
// 调用uni-app分享API
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
}
```
## 开发规范
- 使用Vue 3 Composition API
- 遵循项目ESLint和Prettier规范
- 使用Less预处理器
- 支持uni-app跨平台开发
- 使用响应式数据管理状态
## 注意事项
1. 确保图片资源路径正确配置
2. 图片资源需要支持HTTPS协议
3. 组件使用绝对定位布局,注意父容器样式设置
4. 点赞状态会保存在组件内部,页面刷新后会重置
5. 时间显示基于客户端时间,确保设备时间准确
## 更新日志
- v1.0.0: 初始版本,支持藏品展示、点赞和分享功能
- 支持动态资源管理和响应式设计
- 集成uni-app分享API
- 添加交互动画和状态反馈
// 星妈实验室详情页面样式
.xingmalabdetailpage {
width: 750rpx;
height: 1624rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
.xingmalabdetailpagebg {
width: 750rpx;
height: 1624rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabdetailpagetext {
width: 295rpx;
height: 31rpx;
left: 233rpx;
top: 1232rpx;
position: absolute;
font-size: 32rpx;
line-height: 31rpx;
color: rgba(29, 30, 37, 1);
text-align: center;
}
.xingmalabdetailpagepicbg {
width: 730rpx;
height: 1030rpx;
left: 10rpx;
top: 191rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabdetailpagepic {
width: 688rpx;
height: 914rpx;
left: 31rpx;
top: 207rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabdetailpagenum {
width: 348rpx;
height: 26rpx;
left: 207rpx;
top: 1144rpx;
position: absolute;
font-size: 28rpx;
line-height: 26rpx;
color: rgba(178, 124, 30, 1);
text-align: center;
}
.xingmalabdetailpagebottomcon {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 1406rpx;
position: absolute;
.xingmalabdetailpagebottomconbg {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabdetailpagebottomconlikebtn {
width: 119rpx;
height: 44rpx;
left: 135rpx;
top: 56rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
.xingmalabdetailpagebottomconsharebtn {
width: 121rpx;
height: 42rpx;
left: 498rpx;
top: 58rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
.xingmalabdetailpagetime {
width: 203rpx;
height: 23rpx;
left: 41rpx;
top: 1337rpx;
position: absolute;
font-size: 24rpx;
line-height: 23rpx;
color: rgba(111, 109, 103, 1);
}
}
// 响应式适配
@media screen and (max-width: 750px) {
.xingmalabdetailpage {
width: 100vw;
height: 100vh;
.xingmalabdetailpagebg,
.xingmalabdetailpagepicbg,
.xingmalabdetailpagepic,
.xingmalabdetailpagebottomcon {
width: 100%;
height: auto;
left: 0;
top: 0;
}
.xingmalabdetailpagetext,
.xingmalabdetailpagenum,
.xingmalabdetailpagetime {
position: relative;
left: auto;
top: auto;
margin: 20rpx auto;
text-align: center;
}
}
}
// 动画效果
.xingmalabdetailpage {
animation: fadeIn 0.5s ease-in-out;
.xingmalabdetailpagepic {
animation: slideInUp 0.8s ease-out 0.2s both;
}
.xingmalabdetailpagebottomcon {
animation: slideInUp 0.8s ease-out 0.4s both;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(50rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
// 点赞状态样式
.xingmalabdetailpage {
.xingmalabdetailpagebottomconlikebtn {
&.liked {
filter: brightness(1.2);
transform: scale(1.1);
}
}
}
<template>
<view class="xingmalabdetailpage modal_center">
<span class="xingmalabdetailpagebg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span>
<span class="xingmalabdetailpagetext">{{ config.texts.title }}</span>
<span class="xingmalabdetailpagepicbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.picBg)})` }"></span>
<span class="xingmalabdetailpagepic"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.pic)})` }"></span>
<span class="xingmalabdetailpagenum">{{ config.texts.collectionNumber }}{{ collectionNumber }}</span>
<div class="xingmalabdetailpagebottomcon">
<span class="xingmalabdetailpagebottomconbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.bottomConBg)})` }"></span>
<span class="xingmalabdetailpagebottomconlikebtn" :class="{ liked: isLiked }"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.bottomConLikeBtn)})` }"
@click="handleLikeClick"></span>
<span class="xingmalabdetailpagebottomconsharebtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.bottomConShareBtn)})` }"
@click="handleShareClick"></span>
</div>
<span class="xingmalabdetailpagetime">{{ currentTime }}</span>
</view>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { xingmaLabDetailConfig, getImageUrl } from './config.js'
// 组件名称
defineOptions({
name: 'XingmaLabDetailPage'
})
// 响应式数据
const collectionNumber = ref('123456789')
const isLiked = ref(false)
// 配置对象
const config = xingmaLabDetailConfig
// 计算属性
const currentTime = computed(() => {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
return `${year}-${month}-${day} 北京`
})
// 方法
const handleLikeClick = () => {
console.log('点击点赞按钮')
isLiked.value = !isLiked.value
// 这里可以添加点赞逻辑
uni.showToast({
title: isLiked.value ? '已点赞' : '取消点赞',
icon: 'success'
})
}
const handleShareClick = () => {
console.log('点击分享按钮')
// 这里可以添加分享逻辑
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
}
// 生命周期
onMounted(() => {
console.log('星妈实验室详情页面已加载')
})
</script>
<style lang="less" scoped>
@import './XingmaLabDetailPage.less';
</style>
const version = 'v1'
// 星妈实验室详情页面配置
export const xingmaLabDetailConfig = {
// 图片资源路径配置
images: {
// 背景图片
background: `XingmaLabDetailPage/${version}/XingmaLabDetailPageBg.png`,
// 图片背景
picBg: `XingmaLabDetailPage/${version}/XingmaLabDetailPagePicBg.png`,
// 主图片
pic: `XingmaLabDetailPage/${version}/XingmaLabDetailPagePic.png`,
// 底部容器背景
bottomConBg: `XingmaLabDetailPage/${version}/XingmaLabDetailPageBottomConBg.png`,
// 点赞按钮
bottomConLikeBtn: `XingmaLabDetailPage/${version}/XingmaLabDetailPageBottomConLikeBtn.png`,
// 分享按钮
bottomConShareBtn: `XingmaLabDetailPage/${version}/XingmaLabDetailPageBottomConShareBtn.png`
},
// 文案配置
texts: {
title: '快来用星妈会小程序',
collectionNumber: '唯一藏品编号:'
},
// 页面配置
page: {
width: 750,
height: 1624
}
}
// 获取完整图片URL
export const getImageUrl = (imagePath) => {
return `${imagePath}`
}
// 获取页面尺寸配置
export const getPageConfig = () => {
return xingmaLabDetailConfig.page
}
# 星妈实验室发布页面 (XingmaLabPublishPage)
## 概述
这是一个基于Vue 3 Composition API开发的星妈实验室发布页面组件,用于展示不同状态下的页面内容和交互,支持图片上传、文案编辑、发布流程等功能。
## 功能特性
- **三种状态展示**:未选择状态、选择状态、成功状态
- **图片上传功能**:支持相机/相册选择,限制大小和格式
- **文案编辑功能**:支持纯文本输入,限制字数上限
- **发布流程管理**:包含微信授权、确认弹窗、发布成功等步骤
- **动态资源管理**:通过配置文件统一管理图片资源
- **响应式设计**:支持不同屏幕尺寸的适配
- **交互动画**:包含淡入动画和悬停效果
- **状态管理**:使用Vue 3的响应式系统管理页面状态
## 文件结构
```
XingmaLabPublishPage/
├── XingmaLabPublishPage.vue # 主组件文件
├── XingmaLabPublishPage.less # 样式文件
├── config.js # 配置文件
└── README.md # 说明文档
```
## 使用方法
### 1. 基本使用
```vue
<template>
<XingmaLabPublishPage />
</template>
<script setup>
import XingmaLabPublishPage from '@/pages/XingmaLabPublishPage/XingmaLabPublishPage.vue'
</script>
```
### 2. 状态控制
组件内部管理三种状态:
- `nosel`: 未选择状态(默认)
- `sel`: 选择状态(图片上传和文案编辑)
- `suc`: 成功状态(发布成功展示)
### 3. 功能说明
#### 图片上传功能
- **上传方式**:支持相机拍照和相册选择
- **格式限制**:仅支持jpg/png/jpeg格式
- **大小限制**:可配置最大文件大小(默认10MB)
- **数量限制**:仅限上传1张图片
- **交互反馈**:超出限制时显示相应提示信息
#### 文案编辑功能
- **输入限制**:最多输入1000字
- **字数提示**:实时显示当前字数/最大字数
- **格式支持**:纯文本输入,不支持富文本
- **交互反馈**:达到字数上限时显示提示
#### 发布流程
1. **前置检查**:必须上传图片并填写描述
2. **微信授权**:首次发布需要授权头像昵称
3. **确认弹窗**:显示发布内容预览
4. **发布执行**:调用后端API进行发布
5. **成功展示**:显示发布成功页面
## 配置说明
### 图片资源配置
`config.js` 中配置图片资源路径:
```javascript
export const xingmaLabConfig = {
baseUrl: 'https://factory-walk.feihe.com',
images: {
background: '/farqbxzczytcami/images/XingmaLabPublishPage/XingmaLabPublishPageBg.png',
// ... 其他图片配置
}
}
```
### 上传配置
```javascript
upload: {
maxSize: 10 * 1024 * 1024, // 10MB,待定
maxSizeText: '照片太大啦,换一张试试吧~',
maxWords: 1000,
maxWordsText: '字数已达上限',
allowedTypes: ['jpg', 'png', 'jpeg'],
maxCount: 1
}
```
### 发布成功文案配置
```javascript
successMessages: [
'最好的礼物不是玩具,是陪宝贝长大的光阴。欢迎将宝贝的珍贵回忆,存入你的"时光银行"。',
'时光会走远,影像能长存。星妈会,为您珍藏每一份稚的美好。',
// ... 更多文案
]
```
## 样式定制
### 主要样式类
- `.xingmalabpublishpage`: 主容器
- `.collection-image-area`: 图片上传区域
- `.collection-description-area`: 文案编辑区域
- `.confirm-popup`: 确认发布弹窗
- `.xingmalabpublishpagenosel`: 未选择状态容器
- `.xingmalabpublishpagesel`: 选择状态容器
- `.xingmalabpublishpagesuc`: 成功状态容器
### 响应式断点
- 默认:750rpx 宽度(移动端)
- 响应式:小于750px时自动适配为100vw
### 动画效果
- `fadeIn`: 页面淡入动画
- `slideInUp`: 图片和底部容器从下往上滑入动画
- 上传区域和文案区域的滑入动画
## 交互功能
### 图片上传
```javascript
const handleImageUpload = () => {
uni.chooseImage({
count: 1,
sizeType: ['original'],
sourceType: ['album', 'camera'],
success: (res) => {
// 处理图片选择和验证
}
})
}
```
### 文案编辑
```javascript
const handleDescriptionInput = (e) => {
const value = e.detail.value
if (value.length > config.upload.maxWords) {
// 显示字数超限提示
}
}
```
### 发布流程
```javascript
const handlePublishBtnClick = async () => {
// 检查前置条件
if (!canPublish.value) return
// 检查微信授权
if (!hasAuthorized.value) {
await requestWechatAuth()
return
}
// 显示确认弹窗
showConfirmPopup()
}
```
### 微信授权
```javascript
const requestWechatAuth = () => {
return new Promise((resolve) => {
uni.getUserProfile({
desc: '用于完善用户资料',
success: (res) => {
hasAuthorized.value = true
resolve(true)
},
fail: (err) => {
// 处理授权失败
resolve(false)
}
})
})
}
```
## 开发规范
- 使用Vue 3 Composition API
- 遵循项目ESLint和Prettier规范
- 使用Less预处理器
- 支持uni-app跨平台开发
- 使用响应式数据管理状态
- 集成微信授权API
## 注意事项
1. 确保图片资源路径正确配置
2. 图片资源需要支持HTTPS协议
3. 组件使用绝对定位布局,注意父容器样式设置
4. 微信授权需要在小程序环境中使用
5. 图片上传大小限制可根据实际需求调整
6. 发布成功文案会随机显示,增加用户体验
7. 确认弹窗使用uni-popup组件,确保已安装
## 更新日志
- v1.0.0: 初始版本,支持三种状态展示
- v1.1.0: 新增图片上传功能,支持格式和大小限制
- v1.2.0: 新增文案编辑功能,支持字数限制和实时统计
- v1.3.0: 新增发布流程管理,包含微信授权和确认弹窗
- v1.4.0: 新增发布成功页面,支持随机文案展示
- 支持动态资源管理和响应式设计
- 集成微信授权和分享API
- 添加交互动画和状态反馈
// 星妈实验室发布页面样式
.xingmalabpublishpage {
width: 750rpx;
height: 1624rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
.xingmalabpublishpagebg {
width: 750rpx;
height: 1624rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
// 未选择状态
.xingmalabpublishpagenosel {
width: 750rpx;
height: 1416rpx;
left: 0rpx;
top: 208rpx;
position: absolute;
.xingmalabpublishpagenoseltextplaceholder {
width: 263rpx;
height: 31rpx;
left: 41rpx;
top: 953rpx;
position: absolute;
font-size: 32rpx;
line-height: 31rpx;
color: rgba(189, 191, 195, 1);
}
.xingmalabpublishpagenoselbottomcon {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 1198rpx;
position: absolute;
.xingmalabpublishpagenoselbottomconbg {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpagenoselbottomconbtn {
width: 686rpx;
height: 94rpx;
left: 32rpx;
top: 32rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
.xingmalabpublishpagenoselbtn {
width: 686rpx;
height: 912rpx;
left: 32rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
// 选择状态
.xingmalabpublishpagesel {
width: 750rpx;
height: 1416rpx;
left: 0rpx;
top: 208rpx;
position: absolute;
.xingmalabpublishpagenoseltext {
width: 295rpx;
height: 31rpx;
left: 33rpx;
top: 949rpx;
position: absolute;
font-size: 32rpx;
line-height: 31rpx;
color: rgba(29, 30, 37, 1);
}
// 藏品图片上传区域
.collection-image-area {
position: absolute;
left: 32rpx;
top: 200rpx;
width: 686rpx;
height: 400rpx;
.upload-placeholder {
width: 100%;
height: 100%;
border: 2rpx dashed #ddd;
border-radius: 16rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f8f9fa;
transition: all 0.3s ease;
&:hover {
border-color: #007aff;
background-color: #f0f8ff;
}
.upload-icon {
font-size: 80rpx;
color: #999;
margin-bottom: 20rpx;
}
.upload-text {
font-size: 28rpx;
color: #666;
}
}
.uploaded-image-container {
width: 100%;
height: 100%;
position: relative;
.uploaded-image {
width: 100%;
height: 100%;
border-radius: 16rpx;
object-fit: cover;
}
.reupload-btn {
position: absolute;
bottom: 20rpx;
right: 20rpx;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 12rpx 24rpx;
border-radius: 20rpx;
font-size: 24rpx;
transition: all 0.3s ease;
&:hover {
background-color: rgba(0, 0, 0, 0.9);
}
}
}
}
// 藏品文案介绍区域
.collection-description-area {
position: absolute;
left: 32rpx;
top: 650rpx;
width: 686rpx;
height: 200rpx;
.description-textarea {
width: 100%;
height: 160rpx;
border: 2rpx solid #e0e0e0;
border-radius: 16rpx;
padding: 20rpx;
font-size: 28rpx;
line-height: 1.5;
resize: none;
background-color: white;
&:focus {
border-color: #007aff;
outline: none;
}
}
.word-count {
position: absolute;
bottom: 10rpx;
right: 20rpx;
font-size: 24rpx;
color: #999;
}
}
.xingmalabpublishpageselbottomcon {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 1198rpx;
position: absolute;
.xingmalabpublishpageselbottomconpublishbtnbg {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpageselbottomconpublishbtn {
width: 686rpx;
height: 94rpx;
left: 32rpx;
top: 32rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
.xingmalabpublishpageselpic {
width: 686rpx;
height: 912rpx;
left: 32rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpageselcpver {
width: 686rpx;
height: 189rpx;
left: 32rpx;
top: 723rpx;
position: absolute;
opacity: 0.3;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpageselretry {
width: 270rpx;
height: 76rpx;
left: 240rpx;
top: 804rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
// 成功状态
.xingmalabpublishpagesuc {
width: 750rpx;
height: 1413rpx;
left: 0rpx;
top: 211rpx;
position: absolute;
.xingmalabpublishpagesucbottomconicon {
width: 125rpx;
height: 148rpx;
left: 312rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpagesucbottomcon {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 1195rpx;
position: absolute;
.xingmalabpublishpagesucbottomconbg {
width: 750rpx;
height: 218rpx;
left: 0rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpagesucbottomconbtn {
width: 686rpx;
height: 94rpx;
left: 32rpx;
top: 32rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
.xingmalabpublishpagesucdesc {
width: 538rpx;
height: 117rpx;
left: 111rpx;
top: 191rpx;
position: absolute;
font-size: 30rpx;
color: rgba(29, 30, 37, 1);
line-height: 1.5;
text-align: center;
}
.xingmalabpublishpagesucpicbg {
width: 576rpx;
height: 812rpx;
left: 87rpx;
top: 341rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.xingmalabpublishpagesucpic {
width: 534rpx;
height: 708rpx;
left: 108rpx;
top: 356rpx;
position: absolute;
object-fit: cover;
border-radius: 16rpx;
}
.xingmalabpublishpagesucnum {
width: 222rpx;
height: 25rpx;
left: 271rpx;
top: 1081rpx;
position: absolute;
font-size: 32rpx;
line-height: 25rpx;
color: rgba(178, 124, 30, 1);
text-align: center;
}
}
}
// 确认发布弹窗样式
.confirm-popup {
background: white;
border-radius: 24rpx;
padding: 40rpx;
width: 600rpx;
max-width: 90vw;
.confirm-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 40rpx;
color: #333;
}
.confirm-content {
margin-bottom: 40rpx;
.confirm-image {
width: 100%;
height: 300rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
overflow: hidden;
image {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.confirm-description {
font-size: 28rpx;
color: #666;
line-height: 1.5;
text-align: center;
padding: 20rpx;
background-color: #f8f9fa;
border-radius: 12rpx;
min-height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
.confirm-actions {
display: flex;
gap: 20rpx;
.confirm-btn {
flex: 1;
height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
border: none;
transition: all 0.3s ease;
&.cancel {
background-color: #f0f0f0;
color: #666;
&:hover {
background-color: #e0e0e0;
}
}
&.confirm {
background-color: #007aff;
color: white;
&:hover {
background-color: #0056cc;
}
}
}
}
}
// 响应式适配
@media screen and (max-width: 750px) {
.xingmalabpublishpage {
width: 100vw;
height: 100vh;
.xingmalabpublishpagebg,
.xingmalabpublishpagenosel,
.xingmalabpublishpagesel,
.xingmalabpublishpagesuc {
width: 100%;
height: 100%;
left: 0;
top: 0;
}
.collection-image-area,
.collection-description-area {
position: relative;
left: auto;
top: auto;
margin: 20rpx auto;
width: 90%;
}
}
}
// 动画效果
.xingmalabpublishpage {
.xingmalabpublishpagenosel,
.xingmalabpublishpagesel,
.xingmalabpublishpagesuc {
animation: fadeIn 0.5s ease-in-out;
}
.collection-image-area,
.collection-description-area {
animation: slideInUp 0.8s ease-out 0.3s both;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(50rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
// 上传状态样式
.upload-placeholder {
&.uploading {
opacity: 0.7;
pointer-events: none;
}
}
// 文案输入框焦点样式
.description-textarea {
&:focus {
box-shadow: 0 0 0 4rpx rgba(0, 122, 255, 0.2);
}
}
<template>
<view class="xingmalabpublishpage modal_center">
<span class="xingmalabpublishpagebg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span>
<!-- 未选择状态 -->
<div class="xingmalabpublishpagenosel" v-if="currentState === config.states.NOSEL">
<span class="xingmalabpublishpagenoseltextplaceholder">{{ config.texts.noSel.placeholder }}</span>
<div class="xingmalabpublishpagenoselbottomcon">
<span class="xingmalabpublishpagenoselbottomconbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.bottomConBg)})` }"></span>
<span class="xingmalabpublishpagenoselbottomconbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.bottomConBtn)})` }"
@click="handleNoSelBtnClick"></span>
</div>
<span class="xingmalabpublishpagenoselbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.btn)})` }"
@click="handleNoSelBtnClick"></span>
</div>
<!-- 选择状态 -->
<div class="xingmalabpublishpagesel" v-if="currentState === config.states.SEL">
<span class="xingmalabpublishpagenoseltext">{{ config.texts.sel.title }}</span>
<div class="xingmalabpublishpageselbottomcon">
<span class="xingmalabpublishpageselbottomconpublishbtnbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.bottomConPublishBtnBg)})` }"></span>
<span class="xingmalabpublishpageselbottomconpublishbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.bottomConPublishBtn)})` }"
@click="handlePublishBtnClick"></span>
</div>
<span class="xingmalabpublishpageselpic"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.pic)})` }"></span>
<span class="xingmalabpublishpageselcpver"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.cpver)})` }"></span>
<span class="xingmalabpublishpageselretry"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.retry)})` }"
@click="handleRetryClick"></span>
</div>
<!-- 成功状态 -->
<div class="xingmalabpublishpagesuc" v-if="currentState === config.states.SUC">
<span class="xingmalabpublishpagesucbottomconicon"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.suc.bottomConIcon)})` }"></span>
<div class="xingmalabpublishpagesucbottomcon">
<span class="xingmalabpublishpagesucbottomconbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.suc.bottomConBg)})` }"></span>
<span class="xingmalabpublishpagesucbottomconbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.suc.bottomConBtn)})` }"
@click="handleSuccessBtnClick"></span>
</div>
<span class="xingmalabpublishpagesucdesc">
{{ config.texts.suc.desc }}
</span>
<span class="xingmalabpublishpagesucpicbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.suc.picBg)})` }"></span>
<span class="xingmalabpublishpagesucpic"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.suc.pic)})` }"></span>
<span class="xingmalabpublishpagesucnum">{{ config.texts.suc.numberPrefix }}{{ publishNumber }}</span>
</div>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { xingmaLabConfig, getImageUrl } from './config.js'
// 组件名称
defineOptions({
name: 'XingmaLabPublishPage'
})
// 响应式数据
const currentState = ref(xingmaLabConfig.states.NOSEL) // nosel, sel, suc
const publishNumber = ref('123456789')
// 配置对象
const config = xingmaLabConfig
// 方法
const handleNoSelBtnClick = () => {
console.log('点击未选择状态按钮')
// 这里可以添加跳转逻辑或状态切换
// 例如:跳转到选择页面
// currentState.value = config.states.SEL
}
const handlePublishBtnClick = () => {
console.log('点击发布按钮')
// 模拟发布过程
setTimeout(() => {
currentState.value = config.states.SUC
// 生成随机发布编号
publishNumber.value = Math.random().toString().slice(2, 11)
}, 1000)
}
const handleRetryClick = () => {
console.log('点击重试按钮')
// 重置状态
currentState.value = config.states.NOSEL
}
const handleSuccessBtnClick = () => {
console.log('点击成功状态按钮')
// 这里可以添加完成后的跳转逻辑
uni.navigateBack()
}
// 生命周期
onMounted(() => {
console.log('星妈实验室发布页面已加载')
})
</script>
<style lang="less" scoped>
@import './XingmaLabPublishPage.less';
</style>
const version = 'v1'
// 星妈实验室发布页面配置
export const xingmaLabConfig = {
// 图片资源路径配置
images: {
// 背景图片
background: `XingmaLabPublishPage/${version}/XingmaLabPublishPageBg.png`,
// 未选择状态图片
noSel: {
bottomConBg: `XingmaLabPublishPage/${version}/XingmaLabPublishPageNoSelBottomConBg.png`,
bottomConBtn: `XingmaLabPublishPage/${version}/XingmaLabPublishPageNoSelBottomConBtn.png`,
btn: `XingmaLabPublishPage/${version}/XingmaLabPublishPageNoSelBtn.png`
},
// 选择状态图片
sel: {
bottomConPublishBtnBg: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSelBottomConPublishBtnBg.png`,
bottomConPublishBtn: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSelBottomConPublishBtn.png`,
pic: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSelPic.png`,
cpver: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSelCpver.png`,
retry: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSelRetry.png`
},
// 成功状态图片
suc: {
bottomConIcon: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSucBottomConIcon.png`,
bottomConBg: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSucBottomConBg.png`,
bottomConBtn: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSucBottomConBtn.png`,
picBg: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSucPicBg.png`,
pic: `XingmaLabPublishPage/${version}/XingmaLabPublishPageSucPic.png`
}
},
// 页面状态配置
states: {
NOSEL: 'nosel', // 未选择状态
SEL: 'sel', // 选择状态
SUC: 'suc' // 成功状态
},
// 文案配置
texts: {
noSel: {
placeholder: '记录这个时刻……'
},
sel: {
title: '快来用星妈会小程序'
},
suc: {
numberPrefix: 'No.'
}
},
// 发布成功文案配置
successMessages: [
'最好的礼物不是玩具,是陪宝贝长大的光阴。欢迎将宝贝的珍贵回忆,存入你的"时光银行"。',
'时光会走远,影像能长存。星妈会,为您珍藏每一份稚的美好。',
'孩子终将长大,但「星妈会Lab」会帮你永远记得宝贝现在的样子。',
'孩子是我们写在时光里的诗,每一次记录,都是爱的注脚。',
'照片是时间的化石,为易逝的童年建立不朽的纪念碑。',
'有一天,孩子会离开我去闯荡世界。所以现在,我们要认真记录现在ta依恋我们的样子。',
'父母与子女的缘分,就是不断目送他的背影渐行渐远。而照片,能让那背影在记忆中永不模糊。'
],
// 图片上传配置
upload: {
maxSize: 10 * 1024 * 1024, // 10MB,待定
maxSizeText: '照片太大啦,换一张试试吧~',
maxWords: 1000,
maxWordsText: '字数已达上限',
allowedTypes: ['jpg', 'png', 'jpeg'],
maxCount: 1
}
}
// 获取完整图片URL
export const getImageUrl = (imagePath) => {
return `${imagePath}`
}
// 获取状态对应的图片配置
export const getStateImages = (state) => {
switch (state) {
case xingmaLabConfig.states.NOSEL:
return xingmaLabConfig.images.noSel
case xingmaLabConfig.states.SEL:
return xingmaLabConfig.images.sel
case xingmaLabConfig.states.SUC:
return xingmaLabConfig.images.suc
default:
return xingmaLabConfig.images.noSel
}
}
// 获取随机成功文案
export const getRandomSuccessMessage = () => {
const messages = xingmaLabConfig.successMessages
const randomIndex = Math.floor(Math.random() * messages.length)
return messages[randomIndex]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment