逻辑优化
This commit is contained in:
parent
4ab93debc7
commit
93f7b104c8
|
|
@ -14,7 +14,14 @@ import { getToken } from '../utils/storage'
|
|||
*/
|
||||
export async function getSessions() {
|
||||
const response = await get('/chat/sessions')
|
||||
return response
|
||||
// 统一返回格式
|
||||
if (response && response.code === 0) {
|
||||
return {
|
||||
success: true,
|
||||
data: Array.isArray(response.data) ? response.data : (response.data?.list || [])
|
||||
}
|
||||
}
|
||||
return { success: false, data: [] }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -105,8 +112,11 @@ export async function getUnreadCount() {
|
|||
*/
|
||||
export async function uploadVoice(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 简化 URL 拼接
|
||||
const uploadUrl = `${config.API_BASE_URL}/upload/voice`
|
||||
|
||||
uni.uploadFile({
|
||||
url: config.API_BASE_URL.replace('/api/app', '') + '/api/app/upload/voice',
|
||||
url: uploadUrl,
|
||||
filePath: filePath,
|
||||
name: 'file',
|
||||
header: {
|
||||
|
|
@ -114,18 +124,22 @@ export async function uploadVoice(filePath) {
|
|||
},
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
const data = JSON.parse(res.data)
|
||||
if (data.code === 0) {
|
||||
resolve(data)
|
||||
} else {
|
||||
reject(new Error(data.message || '上传失败'))
|
||||
try {
|
||||
const data = JSON.parse(res.data)
|
||||
if (data.code === 0) {
|
||||
resolve(data)
|
||||
} else {
|
||||
reject(new Error(data.message || '上传失败'))
|
||||
}
|
||||
} catch (e) {
|
||||
reject(new Error('解析响应失败'))
|
||||
}
|
||||
} else {
|
||||
reject(new Error('上传失败'))
|
||||
reject(new Error(`上传失败: ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
reject(new Error(err.errMsg || '网络错误'))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const ENV = {
|
|||
}
|
||||
|
||||
// 当前环境 - 开发时使用 development,打包时改为 production
|
||||
const CURRENT_ENV = 'production'
|
||||
const CURRENT_ENV = 'development'
|
||||
|
||||
// 导出配置
|
||||
export const config = {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,10 @@
|
|||
<!-- 消息状态 -->
|
||||
<view v-if="message.isMine && message.messageType === MessageType.TEXT" class="message-status">
|
||||
<text v-if="message.status === MessageStatus.SENDING" class="status sending">发送中</text>
|
||||
<text v-else-if="message.status === MessageStatus.FAILED" class="status failed">发送失败</text>
|
||||
<view v-else-if="message.status === MessageStatus.FAILED" class="status-failed-wrapper">
|
||||
<text class="status failed">发送失败</text>
|
||||
<text class="retry-btn" @click="handleRetryMessage(message)">重试</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -530,6 +533,36 @@ const handleSendMessage = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// 重试发送失败的消息
|
||||
const handleRetryMessage = async (message) => {
|
||||
if (message.status !== MessageStatus.FAILED) return
|
||||
|
||||
message.status = MessageStatus.SENDING
|
||||
|
||||
try {
|
||||
const res = await sendMessage({
|
||||
sessionId: sessionId.value,
|
||||
receiverId: targetUserId.value,
|
||||
messageType: message.messageType,
|
||||
content: message.content
|
||||
})
|
||||
|
||||
if (res && res.code === 0) {
|
||||
message.status = MessageStatus.SENT
|
||||
if (res.data?.messageId) {
|
||||
message.id = res.data.messageId
|
||||
}
|
||||
uni.showToast({ title: '发送成功', icon: 'success' })
|
||||
} else {
|
||||
message.status = MessageStatus.FAILED
|
||||
uni.showToast({ title: '发送失败', icon: 'none' })
|
||||
}
|
||||
} catch (error) {
|
||||
message.status = MessageStatus.FAILED
|
||||
uni.showToast({ title: '发送失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
// 切换输入模式
|
||||
const handleSwitchInputMode = () => {
|
||||
inputMode.value = inputMode.value === 'text' ? 'voice' : 'text'
|
||||
|
|
@ -1444,6 +1477,18 @@ onUnmounted(() => {
|
|||
color: #ff5252;
|
||||
}
|
||||
}
|
||||
|
||||
.status-failed-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
font-size: 22rpx;
|
||||
color: #1890ff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,8 @@
|
|||
if (res && res.code === 0) {
|
||||
configStore.setHomeConfig({
|
||||
banners: res.data?.banners || [],
|
||||
kingKongs: res.data?.kingKongs || []
|
||||
kingKongs: res.data?.kingKongs || [],
|
||||
defaultAvatar: res.data?.defaultAvatar || ''
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -122,12 +122,12 @@ export default {
|
|||
|
||||
// 用户协议
|
||||
const handleUserAgreement = () => {
|
||||
uni.showToast({ title: '功能开发中', icon: 'none' })
|
||||
uni.navigateTo({ url: '/pages/agreement/index?type=user' })
|
||||
}
|
||||
|
||||
// 隐私政策
|
||||
const handlePrivacyPolicy = () => {
|
||||
uni.showToast({ title: '功能开发中', icon: 'none' })
|
||||
uni.navigateTo({ url: '/pages/agreement/index?type=privacy' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ import { useUserStore } from '@/store/user.js'
|
|||
import { useConfigStore } from '@/store/config.js'
|
||||
import { getMemberInfo } from '@/api/member.js'
|
||||
import { createOrder } from '@/api/order.js'
|
||||
import { getFullImageUrl } from '@/utils/image.js'
|
||||
import Loading from '@/components/Loading/index.vue'
|
||||
|
||||
export default {
|
||||
|
|
@ -181,7 +182,7 @@ export default {
|
|||
const userInfo = computed(() => ({
|
||||
userId: userStore.userId,
|
||||
nickname: userStore.nickname,
|
||||
avatar: userStore.avatar,
|
||||
avatar: getFullImageUrl(userStore.avatar),
|
||||
isMember: userStore.isMember,
|
||||
memberLevel: userStore.memberLevel
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -108,7 +108,19 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-else-if="!pageLoading && !userStore.isLoggedIn">
|
||||
<image src="/static/ic_empty.png" mode="aspectFit" class="empty-icon" />
|
||||
<text class="empty-text">登录后查看消息</text>
|
||||
<button class="login-btn" @click="handleLogin">立即登录</button>
|
||||
</view>
|
||||
|
||||
<!-- 无聊天记录 -->
|
||||
<view class="empty-state" v-else-if="!pageLoading && sessions.length === 0">
|
||||
<image src="/static/ic_empty.png" mode="aspectFit" class="empty-icon" />
|
||||
<text class="empty-text">暂无聊天记录</text>
|
||||
<text class="empty-tip">去首页看看心仪的对象吧</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
|
@ -273,6 +285,11 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
// 跳转登录
|
||||
const handleLogin = () => {
|
||||
uni.navigateTo({ url: '/pages/login/index' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getSystemInfo()
|
||||
initPage()
|
||||
|
|
@ -289,10 +306,12 @@ export default {
|
|||
sessions,
|
||||
interactCounts,
|
||||
defaultAvatar,
|
||||
userStore,
|
||||
formatTime,
|
||||
navigateTo,
|
||||
handleSessionClick,
|
||||
handleRefresh,
|
||||
handleLogin,
|
||||
initPage,
|
||||
loadInteractCounts,
|
||||
loadSessions
|
||||
|
|
@ -591,4 +610,47 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 空状态
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 40rpx;
|
||||
|
||||
.empty-icon {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 32rpx;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: #666;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
margin-top: 32rpx;
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: linear-gradient(135deg, #FFBDC2 0%, #FF8A93 100%);
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -596,9 +596,19 @@ const getSystemInfo = () => {
|
|||
})
|
||||
}
|
||||
|
||||
// 返回
|
||||
// 返回确认
|
||||
const handleBack = () => {
|
||||
uni.navigateBack()
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要离开吗?已填写的内容将不会保存',
|
||||
confirmText: '离开',
|
||||
cancelText: '继续填写',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 步骤配置
|
||||
|
|
@ -1332,6 +1342,26 @@ onMounted(() => {
|
|||
})
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// 页面生命周期需要在普通 script 中定义
|
||||
export default {
|
||||
onBackPress() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要离开吗?已填写的内容将不会保存',
|
||||
confirmText: '离开',
|
||||
cancelText: '继续填写',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
return true // 返回 true 阻止默认返回行为
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.profile-edit-page {
|
||||
min-height: 100vh;
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ export default {
|
|||
// 上传图片(使用统一配置的地址)
|
||||
const uploadRes = await new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${API_BASE_URL}/upload`,
|
||||
url: `${API_BASE_URL}/api/app/upload/image`,
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
header: {
|
||||
|
|
|
|||
|
|
@ -54,9 +54,13 @@ class SignalRClient {
|
|||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// 构建 WebSocket URL
|
||||
// API_BASE_URL: http://localhost:5000/api/app 或 https://xxx.com/api/app
|
||||
// Hub URL: ws://localhost:5000/hubs/chat 或 wss://xxx.com/hubs/chat
|
||||
let baseUrl = config.API_BASE_URL
|
||||
// 移除 /api/app 后缀,获取服务器根地址
|
||||
const serverUrl = baseUrl.replace(/\/api\/app$/, '')
|
||||
// 将 http/https 替换为 ws/wss
|
||||
const wsUrl = baseUrl.replace(/^http/, 'ws').replace('/api/app', '') + '/hubs/chat'
|
||||
const wsUrl = serverUrl.replace(/^http/, 'ws') + '/hubs/chat'
|
||||
|
||||
console.log('[SignalR] 正在连接:', wsUrl)
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ public class HomeConfigResponse
|
|||
/// 金刚位列表
|
||||
/// </summary>
|
||||
public List<KingKongResponse> KingKongs { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 默认头像URL
|
||||
/// </summary>
|
||||
public string? DefaultAvatar { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public class ConfigService : IConfigService
|
|||
private readonly IRepository<Banner> _bannerRepository;
|
||||
private readonly IRepository<KingKong> _kingKongRepository;
|
||||
private readonly IRepository<PopupConfig> _popupConfigRepository;
|
||||
private readonly ISystemConfigService _systemConfigService;
|
||||
private readonly ILogger<ConfigService> _logger;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -29,11 +30,13 @@ public class ConfigService : IConfigService
|
|||
IRepository<Banner> bannerRepository,
|
||||
IRepository<KingKong> kingKongRepository,
|
||||
IRepository<PopupConfig> popupConfigRepository,
|
||||
ISystemConfigService systemConfigService,
|
||||
ILogger<ConfigService> logger)
|
||||
{
|
||||
_bannerRepository = bannerRepository;
|
||||
_kingKongRepository = kingKongRepository;
|
||||
_popupConfigRepository = popupConfigRepository;
|
||||
_systemConfigService = systemConfigService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -42,11 +45,13 @@ public class ConfigService : IConfigService
|
|||
{
|
||||
var banners = await GetBannersAsync();
|
||||
var kingKongs = await GetKingKongsAsync();
|
||||
var defaultAvatar = await _systemConfigService.GetDefaultAvatarAsync();
|
||||
|
||||
return new HomeConfigResponse
|
||||
{
|
||||
Banners = banners,
|
||||
KingKongs = kingKongs
|
||||
KingKongs = kingKongs,
|
||||
DefaultAvatar = defaultAvatar
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user