Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
飞
飞鹤小程序
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
FH
飞鹤小程序
Commits
4b8db5af
Commit
4b8db5af
authored
Aug 27, 2025
by
spc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
xingmalab
parent
5c39ee79
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
482 additions
and
390 deletions
+482
-390
CHANGELOG.md
pages/XingmaLabPublishPage/CHANGELOG.md
+93
-0
README.md
pages/XingmaLabPublishPage/README.md
+65
-218
XingmaLabPublishPage.less
pages/XingmaLabPublishPage/XingmaLabPublishPage.less
+27
-130
XingmaLabPublishPage.vue
pages/XingmaLabPublishPage/XingmaLabPublishPage.vue
+293
-40
config.js
pages/XingmaLabPublishPage/config.js
+4
-2
No files found.
pages/XingmaLabPublishPage/CHANGELOG.md
0 → 100644
View file @
4b8db5af
# 星妈实验室发布页面更新日志
## 版本 1.1.0 - 2024-01-XX
### 新增功能
#### 1. 藏品图片上传功能
-
✅ 支持单张图片上传(限制1张)
-
✅ 固定宽度显示,不限制高度比例
-
✅ 文件大小限制(可配置,默认10MB)
-
✅ 支持格式:jpg、png、jpeg
-
✅ 点击上传区域拉起相机/相册选择器
-
✅ 超过大小限制时显示友好提示:"照片太大啦,换一张试试吧~"
#### 2. 重新上传功能
-
✅ 已上传图片右下角显示"重新上传"按钮
-
✅ 点击重新拉起相机/相册图库
-
✅ 支持jpg/png/jpeg格式选择
-
✅ 上传中状态显示
#### 3. 藏品文案介绍
-
✅ 最多输入1000字限制
-
✅ 点击拉起输入键盘
-
✅ 纯文本输入,不支持富文本
-
✅ 实时字数统计显示
-
✅ 达到字数上限时提示:"字数已达上限"
#### 4. 发布按钮交互优化
-
✅ 首次发布用户自动拉起微信头像昵称授权
-
✅ 已有头像昵称信息用户直接进入确认弹窗
-
✅ 授权拒绝时停留当前页面,再次点击重新拉起授权
-
✅ 确认弹窗显示上传图片和文案内容
-
✅ 后端校验发布次数限制
-
✅ 发布成功后显示随机成功文案
### 技术改进
#### 状态管理
-
✅ 完善的三状态管理:未选择、选择、成功
-
✅ 响应式数据绑定
-
✅ 计算属性优化
#### 用户体验
-
✅ 完善的错误处理和提示
-
✅ 加载状态显示
-
✅ 友好的交互反馈
-
✅ 响应式布局适配
#### 代码质量
-
✅ 遵循Vue 3 Composition API规范
-
✅ 模块化配置管理
-
✅ 完善的注释和文档
-
✅ 保持原有样式格局不变
### 配置项
```
javascript
// 图片上传配置
upload
:
{
maxSize
:
10
*
1024
*
1024
,
// 10MB
maxSizeText
:
'照片太大啦,换一张试试吧~'
,
maxWords
:
1000
,
maxWordsText
:
'字数已达上限'
,
allowedTypes
:
[
'jpg'
,
'png'
,
'jpeg'
],
maxCount
:
1
}
```
### 文件结构
```
pages/XingmaLabPublishPage/
├── XingmaLabPublishPage.vue # 主组件文件
├── XingmaLabPublishPage.less # 样式文件
├── config.js # 配置文件
├── README.md # 功能说明文档
└── CHANGELOG.md # 更新日志
```
### 兼容性
-
✅ 微信小程序
-
✅ uni-app框架
-
✅ Vue 3 Composition API
-
✅ 响应式设计
### 注意事项
1.
保持原有样式和图片格局完全不变
2.
所有交互遵循微信小程序开发规范
3.
错误处理完善,用户体验友好
4.
支持跨平台适配
5.
遵循项目开发规范
pages/XingmaLabPublishPage/README.md
View file @
4b8db5af
# 星妈实验室发布页面
(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格式
### 1. 藏品图片上传
-
**限制数量**
:仅限上传1张图片
-
**尺寸限制**
:固定宽度,不限制高度比例
-
**大小限制**
:可配置最大文件大小(默认10MB)
-
**数量限制**
:仅限上传1张图片
-
**交互反馈**
:超出限制时显示相应提示信息
#### 文案编辑功能
-
**输入限制**
:最多输入1000字
-
**格式支持**
:jpg、png、jpeg
-
**交互方式**
:点击上传区域拉起相机/相册选择器
-
**错误提示**
:超过大小限制时显示"照片太大啦,换一张试试吧~"
### 2. 重新上传功能
-
**触发方式**
:点击"重新上传"按钮
-
**选择方式**
:拉起相机/相册图库
-
**格式限制**
:jpg/png/jpeg
-
**位置**
:已上传图片右下角
### 3. 藏品文案介绍
-
**字数限制**
:最多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
-
**超限提示**
:达到上限时显示"字数已达上限"
### 4. 发布按钮交互
-
**首次发布**
:需要拉起微信头像昵称授权
-
**授权处理**
:
-
允许:进入确认弹窗页面
-
拒绝:停留当前页面,再次点击重新拉起授权
-
**非首次发布**
:直接进入确认弹窗页面
-
**确认弹窗**
:显示上传的图片和文案,用户确认后才发布
-
**次数限制**
:后端校验用户发布次数是否已达上限
## 技术实现
### 状态管理
-
`NOSEL`
:未选择状态
-
`SEL`
:选择状态(已上传图片和文案)
-
`SUC`
:发布成功状态
### 关键方法
-
`handleImageUpload()`
:处理图片上传
-
`handleDescriptionInput()`
:处理文案输入
-
`handlePublishBtnClick()`
:处理发布按钮点击
-
`requestUserInfo()`
:请求用户信息授权
-
`checkPublishLimit()`
:检查发布次数限制
### 配置项
-
图片大小限制:
`config.upload.maxSize`
-
文案字数限制:
`config.upload.maxWords`
-
支持的文件格式:
`config.upload.allowedTypes`
## 使用说明
1.
用户进入页面后,点击"记录这个时刻"按钮进入选择状态
2.
上传藏品图片(必填)
3.
输入藏品文案介绍(可选,最多1000字)
4.
点击发布按钮
5.
首次发布需要授权微信头像昵称
6.
确认发布内容后完成发布
7.
显示发布成功页面
## 注意事项
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
-
添加交互动画和状态反馈
-
保持原有样式和图片格局不变
-
所有交互都遵循微信小程序规范
-
错误处理完善,用户体验友好
-
支持响应式布局
-
遵循Vue 3 Composition API开发规范
\ No newline at end of file
pages/XingmaLabPublishPage/XingmaLabPublishPage.less
View file @
4b8db5af
...
...
@@ -26,14 +26,22 @@
position: absolute;
.xingmalabpublishpagenoseltextplaceholder {
width:
263
rpx;
height:
31
rpx;
left:
41
rpx;
top: 9
53
rpx;
width:
684
rpx;
height:
160
rpx;
left:
33
rpx;
top: 9
49
rpx;
position: absolute;
font-size: 32rpx;
line-height: 31rpx;
color: rgba(189, 191, 195, 1);
line-height: 1.5;
color: rgba(0, 0, 0, 1);
border: none;
background: transparent;
resize: none;
outline: none;
&::placeholder {
color: rgba(189, 191, 195, 1);
}
}
.xingmalabpublishpagenoselbottomcon {
...
...
@@ -90,129 +98,18 @@
}
}
// 选择状态
.xingmalabpublishpagesel {
width: 750rpx;
height: 1416rpx;
left: 0rpx;
top: 208rpx;
position: absolute;
.xingmalabpublishpagenoseltext {
width: 295rpx;
height: 31rpx;
// 主内容区域(整合未选择状态和选择状态)
.xingmalabpublishpagenosel {
// 选择状态下的文案输入框样式
&:has(.xingmalabpublishpageselbottomcon) .xingmalabpublishpagenoseltextplaceholder {
width: 684rpx;
height: 160rpx;
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;
}
color: rgba(0, 0, 0, 1);
}
// 选择状态下的底部按钮区域
.xingmalabpublishpageselbottomcon {
width: 750rpx;
height: 218rpx;
...
...
@@ -249,15 +146,15 @@
}
}
// 已上传图片显示
.xingmalabpublishpageselpic {
width: 686rpx;
height: 912rpx;
left: 32rpx;
top: 0rpx;
position: absolute;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
object-fit: cover;
border-radius: 16rpx;
}
.xingmalabpublishpageselcpver {
...
...
@@ -293,9 +190,9 @@
// 成功状态
.xingmalabpublishpagesuc {
width: 750rpx;
height: 141
3
rpx;
height: 141
6
rpx;
left: 0rpx;
top: 2
11
rpx;
top: 2
08
rpx;
position: absolute;
.xingmalabpublishpagesucbottomconicon {
...
...
pages/XingmaLabPublishPage/XingmaLabPublishPage.vue
View file @
4b8db5af
...
...
@@ -3,38 +3,43 @@
<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"
>
<!-- 主内容区域 -->
<div
class=
"xingmalabpublishpagenosel"
v-if=
"currentState !== config.states.SUC"
>
<!-- 文案输入框 -->
<textarea
v-model=
"description"
class=
"xingmalabpublishpagenoseltextplaceholder"
:placeholder=
"hasContent ? config.texts.sel.descriptionPlaceholder : config.texts.noSel.placeholder"
:maxlength=
"config.upload.maxWords"
@
input=
"handleDescriptionInput"
></textarea>
<!-- 底部按钮区域 -->
<div
class=
"xingmalabpublishpagenoselbottomcon"
v-if=
"!hasContent"
>
<span
class=
"xingmalabpublishpagenoselbottomconbg"
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.bottomConBg)})` }">
</span>
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.bottomConBg)})` }"
@click="handleImageUpload">
</span>
<span
class=
"xingmalabpublishpagenoselbottomconbtn"
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.bottomConBtn)})` }"
@click="handle
NoSelBtnClick
">
</span>
@click="handle
ImageUpload
">
</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"
>
<div
class=
"xingmalabpublishpageselbottomcon"
v-if=
"hasContent"
>
<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"
<!-- 上传按钮 -->
<span
class=
"xingmalabpublishpagenoselbtn"
v-if=
"!hasContent"
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noSel.btn)})` }"
@click="handleImageUpload">
</span>
<!-- 已上传图片显示 -->
<image
v-if=
"uploadedImage"
:src=
"uploadedImage"
class=
"xingmalabpublishpageselpic"
mode=
"aspectFill"
/>
<span
class=
"xingmalabpublishpageselcpver"
v-if=
"uploadedImage"
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.cpver)})` }">
</span>
<span
class=
"xingmalabpublishpageselretry"
<span
class=
"xingmalabpublishpageselretry"
v-if=
"uploadedImage"
:style=
"
{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.sel.retry)})` }"
@click="handle
RetryClick
">
</span>
@click="handle
ImageUpload
">
</span>
</div>
<!-- 成功状态 -->
...
...
@@ -49,20 +54,38 @@
@click="handleSuccessBtnClick">
</span>
</div>
<span
class=
"xingmalabpublishpagesucdesc"
>
{{
config
.
texts
.
suc
.
desc
}}
{{
successMessage
}}
</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>
<image
v-if=
"uploadedImage"
:src=
"uploadedImage"
class=
"xingmalabpublishpagesucpic"
mode=
"aspectFill"
/>
<span
class=
"xingmalabpublishpagesucnum"
>
{{
config
.
texts
.
suc
.
numberPrefix
}}{{
publishNumber
}}
</span>
</div>
<!-- 确认发布弹窗 -->
<uni-popup
ref=
"confirmPopup"
type=
"center"
:mask-click=
"false"
>
<view
class=
"confirm-popup"
>
<view
class=
"confirm-title"
>
确认发布
</view>
<view
class=
"confirm-content"
>
<view
class=
"confirm-image"
v-if=
"uploadedImage"
>
<image
:src=
"uploadedImage"
mode=
"aspectFill"
/>
</view>
<view
class=
"confirm-description"
>
{{
description
||
'暂无文案介绍'
}}
</view>
</view>
<view
class=
"confirm-actions"
>
<button
class=
"confirm-btn cancel"
@
click=
"handleCancelPublish"
>
取消
</button>
<button
class=
"confirm-btn confirm"
@
click=
"handleConfirmPublish"
>
确认发布
</button>
</view>
</view>
</uni-popup>
</view>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
{
xingmaLabConfig
,
getImageUrl
}
from
'./config.js'
import
{
ref
,
onMounted
,
computed
}
from
'vue'
import
{
xingmaLabConfig
,
getImageUrl
,
getRandomSuccessMessage
}
from
'./config.js'
// 组件名称
defineOptions
({
...
...
@@ -72,32 +95,260 @@ defineOptions({
// 响应式数据
const
currentState
=
ref
(
xingmaLabConfig
.
states
.
NOSEL
)
// nosel, sel, suc
const
publishNumber
=
ref
(
'123456789'
)
const
uploadedImage
=
ref
(
''
)
// 上传的图片
const
description
=
ref
(
''
)
// 藏品文案介绍
const
isUploading
=
ref
(
false
)
// 上传状态
const
confirmPopup
=
ref
(
null
)
// 确认弹窗引用
const
successMessage
=
ref
(
''
)
// 成功文案
// 配置对象
const
config
=
xingmaLabConfig
// 方法
const
handleNoSelBtnClick
=
()
=>
{
console
.
log
(
'点击未选择状态按钮'
)
// 这里可以添加跳转逻辑或状态切换
// 例如:跳转到选择页面
// currentState.value = config.states.SEL
// 计算属性 - 判断是否有内容(图片和文案都要有)
const
hasContent
=
computed
(()
=>
{
return
uploadedImage
.
value
&&
description
.
value
.
trim
()
})
// 计算属性
const
isFirstTimePublish
=
computed
(()
=>
{
// 检查用户是否首次发布(这里需要根据实际业务逻辑判断)
// 可以通过本地存储或用户信息来判断
const
hasPublished
=
uni
.
getStorageSync
(
'hasPublished'
)
return
!
hasPublished
})
const
hasUserInfo
=
computed
(()
=>
{
// 检查用户是否已有头像昵称信息
const
userInfo
=
uni
.
getStorageSync
(
'userInfo'
)
return
userInfo
&&
userInfo
.
avatarUrl
&&
userInfo
.
nickName
})
// 图片上传处理
const
handleImageUpload
=
()
=>
{
if
(
isUploading
.
value
)
return
uni
.
chooseImage
({
count
:
1
,
sizeType
:
[
'original'
,
'compressed'
],
sourceType
:
[
'album'
,
'camera'
],
success
:
(
res
)
=>
{
const
tempFilePath
=
res
.
tempFilePaths
[
0
]
// 检查文件大小
uni
.
getFileInfo
({
filePath
:
tempFilePath
,
success
:
(
fileInfo
)
=>
{
if
(
fileInfo
.
size
>
config
.
upload
.
maxSize
)
{
uni
.
showToast
({
title
:
config
.
upload
.
maxSizeText
,
icon
:
'none'
,
duration
:
2000
})
return
}
// 检查文件格式
const
fileExtension
=
tempFilePath
.
split
(
'.'
).
pop
().
toLowerCase
()
if
(
!
config
.
upload
.
allowedTypes
.
includes
(
fileExtension
))
{
uni
.
showToast
({
title
:
'请选择jpg、png或jpeg格式的图片'
,
icon
:
'none'
,
duration
:
2000
})
return
}
// 上传图片
uploadImage
(
tempFilePath
)
},
fail
:
()
=>
{
uni
.
showToast
({
title
:
'获取文件信息失败'
,
icon
:
'none'
})
}
})
},
fail
:
(
err
)
=>
{
console
.
log
(
'选择图片失败:'
,
err
)
}
})
}
const
handlePublishBtnClick
=
()
=>
{
console
.
log
(
'点击发布按钮'
)
// 模拟发布过程
// 上传图片到服务器
const
uploadImage
=
(
filePath
)
=>
{
isUploading
.
value
=
true
// 这里应该调用实际的上传接口
// 暂时使用本地路径作为示例
setTimeout
(()
=>
{
currentState
.
value
=
config
.
states
.
SUC
// 生成随机发布编号
publishNumber
.
value
=
Math
.
random
().
toString
().
slice
(
2
,
11
)
uploadedImage
.
value
=
filePath
isUploading
.
value
=
false
uni
.
showToast
({
title
:
'图片上传成功'
,
icon
:
'success'
})
},
1000
)
}
const
handleRetryClick
=
()
=>
{
console
.
log
(
'点击重试按钮'
)
// 重置状态
currentState
.
value
=
config
.
states
.
NOSEL
// 文案输入处理
const
handleDescriptionInput
=
(
e
)
=>
{
const
value
=
e
.
detail
.
value
if
(
value
.
length
>
config
.
upload
.
maxWords
)
{
uni
.
showToast
({
title
:
config
.
upload
.
maxWordsText
,
icon
:
'none'
,
duration
:
2000
})
description
.
value
=
value
.
substring
(
0
,
config
.
upload
.
maxWords
)
}
else
{
description
.
value
=
value
}
}
// 发布按钮点击处理
const
handlePublishBtnClick
=
async
()
=>
{
console
.
log
(
'点击发布按钮'
,
isFirstTimePublish
.
value
,
hasUserInfo
.
value
)
// 检查是否首次发布且需要授权
// if (isFirstTimePublish.value && !hasUserInfo.value) {
await
requestUserInfo
()
return
// }
// 显示确认弹窗
confirmPopup
.
value
.
open
()
}
// 请求用户信息授权
const
requestUserInfo
=
()
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
// 使用新的授权方式
uni
.
getUserInfo
({
success
:
(
res
)
=>
{
console
.
log
(
'获取用户信息成功:'
,
res
)
// 保存用户信息
uni
.
setStorageSync
(
'userInfo'
,
res
.
userInfo
)
// 显示确认弹窗
confirmPopup
.
value
.
open
()
resolve
(
res
)
},
fail
:
(
err
)
=>
{
console
.
log
(
'获取用户信息失败:'
,
err
)
// 如果获取失败,尝试使用按钮授权
uni
.
showModal
({
title
:
'授权提示'
,
content
:
'需要获取您的头像和昵称信息才能发布内容'
,
confirmText
:
'去授权'
,
success
:
(
modalRes
)
=>
{
if
(
modalRes
.
confirm
)
{
// 引导用户到设置页面授权
uni
.
openSetting
({
success
:
(
settingRes
)
=>
{
if
(
settingRes
.
authSetting
[
'scope.userInfo'
])
{
// 用户已授权,重新获取用户信息
uni
.
getUserInfo
({
success
:
(
userRes
)
=>
{
uni
.
setStorageSync
(
'userInfo'
,
userRes
.
userInfo
)
confirmPopup
.
value
.
open
()
resolve
(
userRes
)
},
fail
:
()
=>
{
uni
.
showToast
({
title
:
'授权失败,请重试'
,
icon
:
'none'
})
reject
()
}
})
}
else
{
uni
.
showToast
({
title
:
'需要授权才能发布'
,
icon
:
'none'
})
reject
()
}
}
})
}
else
{
uni
.
showToast
({
title
:
'需要授权才能发布'
,
icon
:
'none'
})
reject
()
}
}
})
}
})
})
}
// 取消发布
const
handleCancelPublish
=
()
=>
{
confirmPopup
.
value
.
close
()
}
// 确认发布
const
handleConfirmPublish
=
async
()
=>
{
confirmPopup
.
value
.
close
()
try
{
// 检查发布次数限制
const
canPublish
=
await
checkPublishLimit
()
if
(
!
canPublish
)
{
uni
.
showToast
({
title
:
'发布次数已达上限'
,
icon
:
'none'
})
return
}
// 执行发布
await
performPublish
()
// 标记用户已发布过
uni
.
setStorageSync
(
'hasPublished'
,
true
)
// 切换到成功状态
currentState
.
value
=
config
.
states
.
SUC
successMessage
.
value
=
getRandomSuccessMessage
()
publishNumber
.
value
=
generatePublishNumber
()
}
catch
(
error
)
{
console
.
error
(
'发布失败:'
,
error
)
uni
.
showToast
({
title
:
'发布失败,请重试'
,
icon
:
'none'
})
}
}
// 检查发布次数限制
const
checkPublishLimit
=
async
()
=>
{
// 这里应该调用后端接口检查发布次数
// 暂时返回true作为示例
return
new
Promise
((
resolve
)
=>
{
setTimeout
(()
=>
{
resolve
(
true
)
},
500
)
})
}
// 执行发布
const
performPublish
=
async
()
=>
{
// 这里应该调用后端发布接口
return
new
Promise
((
resolve
)
=>
{
setTimeout
(()
=>
{
console
.
log
(
'发布成功'
)
resolve
()
},
1000
)
})
}
// 生成发布编号
const
generatePublishNumber
=
()
=>
{
return
Math
.
random
().
toString
().
slice
(
2
,
11
)
}
const
handleSuccessBtnClick
=
()
=>
{
...
...
@@ -109,6 +360,8 @@ const handleSuccessBtnClick = () => {
// 生命周期
onMounted
(()
=>
{
console
.
log
(
'星妈实验室发布页面已加载'
)
// 生成随机成功文案
successMessage
.
value
=
getRandomSuccessMessage
()
})
</
script
>
...
...
pages/XingmaLabPublishPage/config.js
View file @
4b8db5af
...
...
@@ -47,10 +47,12 @@ export const xingmaLabConfig = {
placeholder
:
'记录这个时刻……'
},
sel
:
{
title
:
'快来用星妈会小程序'
title
:
'快来用星妈会小程序'
,
descriptionPlaceholder
:
'请输入藏品文案介绍...'
},
suc
:
{
numberPrefix
:
'No.'
numberPrefix
:
'No.'
,
desc
:
'发布成功!'
}
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment