Browse Source

智能体替换

dev_des
1054425342@qq.com 4 weeks ago
parent
commit
09af5062f8
  1. 77
      components/GPT/index.vue
  2. 3
      components/GPT/utils/pcm-player.js
  3. 69
      components/WaterfallLayout.vue
  4. 338
      pages/index/components/FollowTab.vue
  5. 4
      pages/index/iSoul.vue
  6. 57
      pages/index/timeShopBank.vue
  7. 27
      pages/notes/detail.vue
  8. BIN
      static/imgs/icon-stop.png

77
components/GPT/index.vue

@ -56,9 +56,10 @@
</view> </view>
<view class="chat-wrap__main-footer"> <view class="chat-wrap__main-footer">
<view class="disabled-loadding" v-if="disabledStatus"></view>
<view class="chatinput-wrapper"> <view class="chatinput-wrapper">
<view class="chatinput-content"> <view class="chatinput-content">
<view class="input-content">
<view class="disabled-loadding" v-if="disabledStatus"></view>
<view class='chatinput-input-wrap' v-if="videoStatus"> <view class='chatinput-input-wrap' v-if="videoStatus">
<view style="text-align: center; flex: 1; color:#9FA0A0" @longpress="startVideo" @touchend="stopVideo"> <view style="text-align: center; flex: 1; color:#9FA0A0" @longpress="startVideo" @touchend="stopVideo">
按住 说话 按住 说话
@ -67,10 +68,15 @@
<view v-else class='chatinput-input-wrap'> <view v-else class='chatinput-input-wrap'>
<input v-model="inputValue" @focus="inputFocus" @input="inputChange" @confirm="inputSend" placeholder="想对TA说点什么呢…" confirm-type='send' /> <input v-model="inputValue" @focus="inputFocus" @input="inputChange" @confirm="inputSend" placeholder="想对TA说点什么呢…" confirm-type='send' />
</view> </view>
</view>
<view class="chatinput-btn-wrap"> <view class="chatinput-btn-wrap">
<!-- <image v-if="!isEditInput" :src="videoStatus ? './../../static/imgs/icon-txt.png' :'./../../static/imgs/icon-video.png'" class='chatinput-img' @click="changeVideoStatus"></image> --> <!-- <image v-if="!isEditInput" :src="videoStatus ? './../../static/imgs/icon-txt.png' :'./../../static/imgs/icon-video.png'" class='chatinput-img' @click="changeVideoStatus"></image> -->
<!-- <image v-if="!isEditInput" src="./../../static/imgs/icon-pic.png" class='chatinput-img' @click="tapChooseImage"></image> --> <!-- <image v-if="!isEditInput" src="./../../static/imgs/icon-pic.png" class='chatinput-img' @click="tapChooseImage"></image> -->
<!-- <button v-if="isEditInput" class="chatinput-send">发送</button> --> <!-- <button v-if="isEditInput" class="chatinput-send">发送</button> -->
<template v-if="disabledStatus">
<image src="./../../static/imgs/icon-stop.png" class="chatinput-img" @click="stopMessage"></image>
</template>
<template v-else>
<template v-if="videoStatus"> <template v-if="videoStatus">
<image src="./../../static/imgs/icon-txt.png" class="chatinput-img" @click="changeVideoStatus"></image> <image src="./../../static/imgs/icon-txt.png" class="chatinput-img" @click="changeVideoStatus"></image>
</template> </template>
@ -79,6 +85,7 @@
<image v-else src="./../../static/imgs/icon-video.png" class='chatinput-img' @click="changeVideoStatus"></image> <image v-else src="./../../static/imgs/icon-video.png" class='chatinput-img' @click="changeVideoStatus"></image>
</template> </template>
</template>
</view> </view>
</view> </view>
</view> </view>
@ -141,7 +148,9 @@ export default {
requestMsg: {}, requestMsg: {},
disabledStatus: false, disabledStatus: false,
audioOBJ: null, audioOBJ: null,
reAudioType: false reAudioType: false,
stopStatus: false
} }
}, },
onLoad() { onLoad() {
@ -161,8 +170,9 @@ export default {
this.audioActive = '' this.audioActive = ''
this.audioStatus = false this.audioStatus = false
this.asrStatus = false this.asrStatus = false
this.player && this.player.destroy() this.player && this.player.destroy()
this.stopStatus = false
this.currentRecordId = ''
}, },
onHide() { onHide() {
console.log('【hide message connect type------>】',); console.log('【hide message connect type------>】',);
@ -171,7 +181,40 @@ export default {
this.scrollToBottom() this.scrollToBottom()
}, },
methods: { methods: {
stopMessage(){
//
console.log('暂停语音',);
this.stopStatus = true
//
this.stopMSN()
//
if (this.player) {
this.player.destroy()
}
// pending
if (this.msgList && this.msgList.length) {
const last = this.msgList[this.msgList.length - 1]
console.log('last', last);
if (last.pending) {
this.msgList.pop()
}
}
this.audioActive = ''
this.disabledStatus = false
},
stopMSN () {
if (this.socketObj && this.socketObj.socket) {
const options = { data: "42" + JSON.stringify(["stop_generation", {
payload: {
record_id: this.currentRecordId
}
}]) }
this.socketObj.send(options)
}
},
/* 4. 滚动日志 */ /* 4. 滚动日志 */
appendLog(str) { appendLog(str) {
console.log(1111, str) console.log(1111, str)
@ -181,6 +224,11 @@ export default {
sampleRate: 16000, sampleRate: 16000,
onPlay: (obj) => { onPlay: (obj) => {
console.log('播放文字', obj) console.log('播放文字', obj)
//
if (this.stopStatus) {
return
}
this.disabledStatus = true this.disabledStatus = true
if (obj.is_final) { if (obj.is_final) {
// //
@ -250,6 +298,11 @@ export default {
// const player = new AudioStreamPlayer() // const player = new AudioStreamPlayer()
this.audioOBJ = new Audio({ this.audioOBJ = new Audio({
onMessage: (e) => { onMessage: (e) => {
//
if (this.stopStatus) {
return
}
if (e instanceof ArrayBuffer) { if (e instanceof ArrayBuffer) {
this.player.feed(e) this.player.feed(e)
return return
@ -328,7 +381,15 @@ export default {
this.socketObj = new Socket({ this.socketObj = new Socket({
agentId: this.agentId, agentId: this.agentId,
onMessage: (e) => { onMessage: (e) => {
console.log(e.request_id + '回复内容', e.content) console.log(111111, e.record_id, e.request_id + '回复内容', e.content)
// id
self.currentRecordId = e.record_id
//
if (this.stopStatus) {
this.stopMSN()
return
}
e.pending = false e.pending = false
self.requestMsg[e.request_id] = (self.requestMsg[e.request_id] ? self.requestMsg[e.request_id] : '') + e.content self.requestMsg[e.request_id] = (self.requestMsg[e.request_id] ? self.requestMsg[e.request_id] : '') + e.content
@ -389,6 +450,7 @@ export default {
async audio(n, status) { async audio(n, status) {
console.log('【audio------>】', n, status); console.log('【audio------>】', n, status);
this.stopStatus = false
this.reAudioType = !status this.reAudioType = !status
this.audioArray = [] this.audioArray = []
// this.audioArray = this.audioArray.slice(-10) // this.audioArray = this.audioArray.slice(-10)
@ -708,6 +770,7 @@ export default {
}) })
}, },
onSendQuestion(e) { onSendQuestion(e) {
this.stopStatus = false
let self = this let self = this
if (e === '') { if (e === '') {
return wx.showToast({ title: '不能发送空白消息', icon: 'none' }) return wx.showToast({ title: '不能发送空白消息', icon: 'none' })
@ -843,6 +906,12 @@ export default {
margin: 0 20rpx; margin: 0 20rpx;
background: #fff; background: #fff;
.input-content {
flex: 1;
display: flex;
position: relative;
}
.chatinput-input-wrap { .chatinput-input-wrap {
flex: 1; flex: 1;
height: 80rpx; height: 80rpx;

3
components/GPT/utils/pcm-player.js

@ -83,7 +83,8 @@ export default class PcmPlayer {
} }
// 3. 播放并等待结束 // 3. 播放并等待结束
await new Promise((resolve) => { await new Promise((resolve, reject) => {
if (!this.isPlaying) {return reject()}
const src = this.audioCtx.createBufferSource(); const src = this.audioCtx.createBufferSource();
src.buffer = buf; src.buffer = buf;
src.connect(this.audioCtx.destination); src.connect(this.audioCtx.destination);

69
components/WaterfallLayout.vue

@ -15,12 +15,23 @@
class="waterfall-item" class="waterfall-item"
@click="handleItemClick(index, leftItems)" @click="handleItemClick(index, leftItems)"
> >
<view class="image-container">
<image <image
v-if="item.coverImage" v-if="item.coverImage"
:src="item.coverImage && item.coverImage.split(',')[0]" :src="item.coverImage && item.coverImage.split(',')[0]"
class="item-image" class="item-image"
mode="aspectFill" mode="aspectFill"
/> />
<!-- 状态蒙层 -->
<view
v-if="item.status === 0 || item.status === -1"
class="status-overlay"
>
<text class="status-text">{{
item.status === 0 ? "待审核" : "审核不通过"
}}</text>
</view>
</view>
<view class="item-content"> <view class="item-content">
<text v-if="item.title" class="item-title">{{ item.title }}</text> <text v-if="item.title" class="item-title">{{ item.title }}</text>
<view class="item-footer"> <view class="item-footer">
@ -32,7 +43,11 @@
/> />
<text class="username">{{ item.nickname }}</text> <text class="username">{{ item.nickname }}</text>
</view> </view>
<view class="like-info" @click.stop="handleLikeClick(item)"> <view
v-if="item.status !== 0 && item.status !== -1"
class="like-info"
@click.stop="handleLikeClick(item)"
>
<image <image
v-if="!item.userLiked" v-if="!item.userLiked"
src="https://epic.js-dyyj.com/uploads/20250728/2f3ae212c01fa3b67be81abc5723cf5c.png" src="https://epic.js-dyyj.com/uploads/20250728/2f3ae212c01fa3b67be81abc5723cf5c.png"
@ -57,12 +72,23 @@
class="waterfall-item" class="waterfall-item"
@click="handleItemClick(index, rightItems)" @click="handleItemClick(index, rightItems)"
> >
<view class="image-container">
<image <image
v-if="item.coverImage" v-if="item.coverImage"
:src="item.coverImage && item.coverImage.split(',')[0]" :src="item.coverImage && item.coverImage.split(',')[0]"
class="item-image" class="item-image"
mode="aspectFill" mode="aspectFill"
/> />
<!-- 状态蒙层 -->
<view
v-if="item.status === 0 || item.status === -1"
class="status-overlay"
>
<text class="status-text">{{
item.status === 0 ? "待审核" : "审核不通过"
}}</text>
</view>
</view>
<view class="item-content"> <view class="item-content">
<text v-if="item.title" class="item-title">{{ item.title }}</text> <text v-if="item.title" class="item-title">{{ item.title }}</text>
<view class="item-footer"> <view class="item-footer">
@ -77,7 +103,11 @@
}}{{ item.nickname }}</text }}{{ item.nickname }}</text
> >
</view> </view>
<view class="like-info" @click.stop="handleLikeClick(item)"> <view
v-if="item.status !== 0 && item.status !== -1"
class="like-info"
@click.stop="handleLikeClick(item)"
>
<image <image
v-if="!item.userLiked" v-if="!item.userLiked"
src="https://epic.js-dyyj.com/uploads/20250728/2f3ae212c01fa3b67be81abc5723cf5c.png" src="https://epic.js-dyyj.com/uploads/20250728/2f3ae212c01fa3b67be81abc5723cf5c.png"
@ -186,10 +216,10 @@ export default {
}); });
// //
uni.$emit('note-like-change', { uni.$emit("note-like-change", {
noteId: item.id, noteId: item.id,
isLiked: isLiked, isLiked: isLiked,
likeCount: item.likeCount likeCount: item.likeCount,
}); });
} }
}) })
@ -343,6 +373,7 @@ export default {
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
overflow: hidden; overflow: hidden;
transition: transform 0.2s ease; transition: transform 0.2s ease;
position: relative;
} }
.waterfall-item:active { .waterfall-item:active {
@ -444,4 +475,34 @@ export default {
font-size: 22rpx; font-size: 22rpx;
color: #666; color: #666;
} }
.image-container {
position: relative;
width: 100%;
overflow: hidden;
height: 476rpx;
}
/* 状态蒙层样式 */
.status-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
}
.status-text {
color: #ffffff;
font-size: 28rpx;
font-weight: 500;
padding: 10rpx 20rpx;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 8rpx;
}
</style> </style>

338
pages/index/components/FollowTab.vue

@ -3,19 +3,24 @@
<!-- 搜索栏 --> <!-- 搜索栏 -->
<view class="search-section"> <view class="search-section">
<view class="search-bar"> <view class="search-bar">
<image class="search-icon" :src="showImg('/uploads/20250826/a4d605e82622223c270df0af4e378ab3.png')"></image> <image
class="search-icon"
:src="
showImg('/uploads/20250826/a4d605e82622223c270df0af4e378ab3.png')
"
></image>
<input <input
class="search-input" class="search-input"
placeholder="搜索已关注的人" placeholder="搜索已关注的人"
v-model="searchText" v-model="searchText"
@input="handleSearch" @confirm="handleSearch"
/> />
</view> </view>
</view> </view>
<!-- 我的关注标题和排序 --> <!-- 我的关注标题和排序 -->
<view class="follows-header"> <view class="follows-header">
<text class="follows-title">我的关注 ({{ followsList.length||0 }})</text> <text class="follows-title">我的关注 ({{ totalCount || 0 }})</text>
<!-- <view class="sort-option" @click="toggleSort"> <!-- <view class="sort-option" @click="toggleSort">
<text class="sort-text">综合排序</text> <text class="sort-text">综合排序</text>
<image class="sort-arrow" :src="showImg('/uploads/20250826/8e40deaa0bc67da3a9b104ff0e6b3e7c.png')"></image> <image class="sort-arrow" :src="showImg('/uploads/20250826/8e40deaa0bc67da3a9b104ff0e6b3e7c.png')"></image>
@ -42,25 +47,52 @@
<!-- 关注用户列表 --> <!-- 关注用户列表 -->
<view class="follows-list"> <view class="follows-list">
<!-- 加载状态 -->
<view class="loading-state" v-if="loading">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 空状态显示 -->
<view class="empty-state" v-else-if="filteredFollowsList.length === 0">
<image
class="empty-icon"
:src="
showImg('/uploads/20250826/a4d605e82622223c270df0af4e378ab3.png')
"
mode="aspectFit"
></image>
<text class="empty-text">{{
searchText ? "未找到相关用户" : "暂无关注"
}}</text>
<text class="empty-desc">{{
searchText ? "换个关键词试试吧" : "关注你感兴趣的人,获取更多精彩内容"
}}</text>
</view>
<view <view
class="follow-item" class="follow-item"
v-for="(item, index) in filteredFollowsList" v-for="(item, index) in filteredFollowsList"
:key="item.id" :key="item.id"
> >
<image class="user-avatar" src="https://epic.js-dyyj.com/uploads/20250728/7d9ba1fe109643681396cb03f60f3218.png" mode="aspectFill"></image> <image
class="user-avatar"
:src="
item.followUserHeadimg ||
'https://epic.js-dyyj.com/uploads/20250728/7d9ba1fe109643681396cb03f60f3218.png'
"
mode="aspectFill"
></image>
<view class="user-info"> <view class="user-info">
<text class="user-name">{{ item.name }}</text> <text class="user-name">{{ item.followUserNickname }}</text>
<view class="update-tag" v-if="item.newItems > 0"> <view class="update-time">
{{ item.newItems }}件商品上新 {{ item.formatTime }}
</view> </view>
</view> </view>
<view class="action-buttons"> <view class="action-buttons">
<view class="follow-status-btn"> <view class="follow-status-btn"> 已关注 </view>
已关注 <view class="more-options" @click="showOptions(item)">
</view>
<!-- <view class="more-options" @click="showOptions(item)">
<text class="more-dots"></text> <text class="more-dots"></text>
</view> --> </view>
</view> </view>
</view> </view>
</view> </view>
@ -71,9 +103,17 @@
<!-- 推荐用户区域 --> <!-- 推荐用户区域 -->
<view class="recommend-section" v-if="false"> <view class="recommend-section" v-if="false">
<view class="recommend-header"> <view class="recommend-header">
<view class="recommend-title" style="display: flex;align-items: center;"> <view
class="recommend-title"
style="display: flex; align-items: center"
>
你可能感兴趣的人 你可能感兴趣的人
<image style="width: 30rpx;height: 30rpx;margin-left: 10rpx;" :src="showImg('/uploads/20250826/f1422cbef4c33e8c21d9e7e805c8bad9.png')"></image> <image
style="width: 30rpx; height: 30rpx; margin-left: 10rpx"
:src="
showImg('/uploads/20250826/f1422cbef4c33e8c21d9e7e805c8bad9.png')
"
></image>
</view> </view>
<view class="close-btn" @click="closeRecommend"> <view class="close-btn" @click="closeRecommend">
<text class="close-text">关闭</text> <text class="close-text">关闭</text>
@ -96,9 +136,7 @@
<text class="user-desc">{{ item.description }}</text> <text class="user-desc">{{ item.description }}</text>
</view> </view>
<view class="action-buttons"> <view class="action-buttons">
<view class="follow-btn" @click="followUser(item)"> <view class="follow-btn" @click="followUser(item)"> 关注 </view>
关注
</view>
<view class="dismiss-btn" @click="dismissUser(item)"> <view class="dismiss-btn" @click="dismissUser(item)">
<text class="dismiss-text">×</text> <text class="dismiss-text">×</text>
</view> </view>
@ -116,29 +154,7 @@ export default {
return { return {
searchText: "", searchText: "",
activeCategory: "all", activeCategory: "all",
followsList: [ followsList: [],
{
id: 1,
name: "主理人—颜真卿",
avatar: "/uploads/20250826/avatar1.png",
newItems: 1,
category: "merchant",
},
{
id: 2,
name: "主理人—颜真卿",
avatar: "/uploads/20250826/avatar1.png",
newItems: 0,
category: "merchant",
},
{
id: 3,
name: "主理人—颜真卿",
avatar: "/uploads/20250826/avatar1.png",
newItems: 2,
category: "user",
},
],
recommendList: [ recommendList: [
{ {
id: 101, id: 101,
@ -153,32 +169,36 @@ export default {
description: "介绍介绍介绍", description: "介绍介绍介绍",
}, },
], ],
//
pageNum: 1,
pageSize: 10,
loading: false,
hasMore: true,
totalCount: 0,
}; };
}, },
computed: { computed: {
filteredFollowsList() { filteredFollowsList() {
let filtered = this.followsList; //
return this.followsList;
// },
if (this.activeCategory !== "all") {
filtered = filtered.filter(
(item) => item.category === this.activeCategory
);
}
//
if (this.searchText.trim()) {
filtered = filtered.filter((item) =>
item.name.toLowerCase().includes(this.searchText.toLowerCase())
);
}
return filtered;
}, },
mounted() {
//
this.getFollowList();
},
//
onReachBottom() {
this.loadMoreFollows();
},
//
onPullDownRefresh() {
this.getFollowList();
}, },
methods: { methods: {
handleSearch() { handleSearch() {
// computed //
this.getFollowList();
}, },
toggleSort() { toggleSort() {
@ -193,9 +213,84 @@ export default {
this.activeCategory = category; this.activeCategory = category;
}, },
//
getFollowList(refresh = true) {
let token = uni.getStorageSync("token1");
if (!token) {
uni.showToast({
title: "请先登录",
icon: "none",
});
uni.navigateTo({
url: "/pages/login/login",
});
return;
}
if (this.loading) return;
if (refresh) {
this.pageNum = 1;
this.hasMore = true;
}
this.loading = true;
const params = {
pageNum: this.pageNum,
pageSize: this.pageSize,
};
//
if (this.searchText.trim()) {
params.followUserNickname = this.searchText.trim();
}
this.Post(params, "/framework/follow/followList", "DES")
.then((res) => {
if (res.code === 200 && res.rows) {
const newItems = res.rows || [];
if (this.pageNum === 1) {
//
this.followsList = newItems;
this.totalCount = res.total || 0;
} else {
//
this.followsList.push(...newItems);
}
//
this.hasMore = newItems.length === this.pageSize;
} else {
uni.showToast({
title: res.msg || "获取关注列表失败",
icon: "none",
});
}
})
.catch((error) => {
console.error("获取关注列表失败:", error);
uni.showToast({
title: "加载失败,请重试",
icon: "none",
});
})
.finally(() => {
this.loading = false;
uni.stopPullDownRefresh();
});
},
//
loadMoreFollows() {
if (!this.loading && this.hasMore) {
this.pageNum++;
this.getFollowList(false);
}
},
showOptions(item) { showOptions(item) {
uni.showActionSheet({ uni.showActionSheet({
itemList: ["取消关注", "举报", "拉黑"], itemList: ["取消关注"],
success: (res) => { success: (res) => {
switch (res.tapIndex) { switch (res.tapIndex) {
case 0: case 0:
@ -213,15 +308,53 @@ export default {
}, },
unfollowUser(item) { unfollowUser(item) {
const index = this.followsList.findIndex((user) => user.id === item.id); uni.showModal({
title: "提示",
content: "确定要取消关注该用户吗?",
success: (res) => {
if (res.confirm) {
//
this.Post(
{
followUserId: item.followUserId,
type: 2, // 2
},
"/framework/follow/followUser",
"DES"
)
.then((res) => {
if (res.code === 200) {
//
const index = this.followsList.findIndex(
(user) => user.id === item.id
);
if (index > -1) { if (index > -1) {
this.followsList.splice(index, 1); this.followsList.splice(index, 1);
this.totalCount--;
}
uni.showToast({ uni.showToast({
title: "已取消关注", title: "已取消关注",
icon: "success", icon: "success",
}); });
} else {
uni.showToast({
title: res.msg || "取消关注失败",
icon: "none",
});
}
})
.catch((error) => {
console.error("取消关注失败:", error);
uni.showToast({
title: "操作失败,请重试",
icon: "none",
});
});
} }
}, },
});
},
reportUser(item) { reportUser(item) {
uni.showToast({ uni.showToast({
@ -301,8 +434,8 @@ export default {
height: 80rpx; height: 80rpx;
.search-icon { .search-icon {
width:32rpx ; width: 32rpx;
height:32rpx ; height: 32rpx;
margin-right: 16rpx; margin-right: 16rpx;
color: #999; color: #999;
} }
@ -344,7 +477,7 @@ export default {
} }
.sort-arrow { .sort-arrow {
width:9rpx; width: 9rpx;
height: 24rpx; height: 24rpx;
} }
} }
@ -363,15 +496,13 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 15rpx 30rpx; padding: 15rpx 30rpx;
font-size: 28rpx; font-size: 28rpx;
color: #000000; color: #000000;
font-weight: bold; font-weight: bold;
&.active { &.active {
background: #00FFFF; background: #00ffff;
color: #000000; color: #000000;
} }
} }
} }
@ -380,6 +511,69 @@ font-size: 28rpx;
.follows-list { .follows-list {
padding: 0 32rpx; padding: 0 32rpx;
/* 加载状态样式 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #f3f3f3;
border-top: 4rpx solid #00ffff;
border-radius: 50%;
margin-bottom: 20rpx;
animation: spin 1s linear infinite;
}
.loading-text {
font-size: 28rpx;
color: #999;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 空状态样式 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-icon {
width: 120rpx;
height: 120rpx;
margin-bottom: 30rpx;
opacity: 0.5;
}
.empty-text {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 16rpx;
}
.empty-desc {
font-size: 26rpx;
color: #999;
text-align: center;
max-width: 80%;
}
}
.follow-item { .follow-item {
display: flex; display: flex;
align-items: center; align-items: center;
@ -413,9 +607,13 @@ font-size: 28rpx;
background: #f8f9fa; background: #f8f9fa;
border-radius: 16rpx; border-radius: 16rpx;
padding: 10rpx 12rpx; padding: 10rpx 12rpx;
font-size: 24rpx; font-size: 24rpx;
color: #666; color: #666;
}
.update-time {
font-size: 24rpx;
color: #999;
} }
} }
@ -430,7 +628,6 @@ font-size: 24rpx;
border: 2rpx solid #e5e5e5; border: 2rpx solid #e5e5e5;
font-size: 26rpx; font-size: 26rpx;
color: #666; color: #666;
} }
.more-options { .more-options {
@ -521,13 +718,12 @@ font-size: 24rpx;
gap: 16rpx; gap: 16rpx;
.follow-btn { .follow-btn {
border: 2rpx solid #00FFFF; border: 2rpx solid #00ffff;
border-radius: 24rpx; border-radius: 24rpx;
padding: 12rpx 24rpx; padding: 12rpx 24rpx;
font-size: 26rpx; font-size: 26rpx;
color: #000; color: #000;
font-weight: bold; font-weight: bold;
} }
.dismiss-btn { .dismiss-btn {

4
pages/index/iSoul.vue

@ -61,11 +61,11 @@
<view class="stats-section"> <view class="stats-section">
<view class="stats-left"> <view class="stats-left">
<view class="stat-item"> <view class="stat-item">
<view class="stat-number">{{ userStats.following || "0" }}</view> <view class="stat-number">{{ userInfo.followCount || "0" }}</view>
<view class="stat-label">关注</view> <view class="stat-label">关注</view>
</view> </view>
<view class="stat-item"> <view class="stat-item">
<view class="stat-number">{{ userInfo.followers || "0" }}</view> <view class="stat-number">{{ userInfo.fansCount || "0" }}</view>
<view class="stat-label">粉丝</view> <view class="stat-label">粉丝</view>
</view> </view>
<view class="stat-item"> <view class="stat-item">

57
pages/index/timeShopBank.vue

@ -59,8 +59,8 @@
</view> --> </view> -->
<!-- 关注tab内容 --> <!-- 关注tab内容 -->
<view v-if="currentTab == 1" class="follow-content"> <view v-if="currentTab == 1" class="follow-content">
<!-- <FollowTab /> --> <FollowTab ref="followTab" />
<text class="coming-soon">关注功能开发中...</text> <!-- <text class="coming-soon">关注功能开发中...</text> -->
</view> </view>
<!-- 推荐tab内容 --> <!-- 推荐tab内容 -->
@ -76,15 +76,13 @@
/> />
</view> </view>
</view> </view>
<!-- <view class="fab-container"> <view class="fab-container">
<image <image
@click="goToPublish" @click="goToPublish"
:src=" :src="showImg('/uploads/20250825/7ea7864b8abb89c3dd7834f025e49b3f.png')"
showImg('/uploads/20250825/7ea7864b8abb89c3dd7834f025e49b3f.png')
"
style="width: 91rpx; height: 91rpx" style="width: 91rpx; height: 91rpx"
></image> ></image>
</view> --> </view>
<!-- 控制按钮 --> <!-- 控制按钮 -->
<!-- <view class="controls"> <!-- <view class="controls">
<button @click="addRandomItem" class="control-btn primary"> <button @click="addRandomItem" class="control-btn primary">
@ -179,8 +177,29 @@ export default {
}); });
}, },
//
refreshFollowList() {
// FollowTab
if (this.$refs.followTab) {
this.$refs.followTab.getFollowList();
}
},
// //
getRecommendList(type = 1) { getRecommendList(type = 1) {
if (type == 0) {
let token = uni.getStorageSync("token1");
if (!token) {
uni.showToast({
title: "请先登录",
icon: "none",
});
uni.navigateTo({
url: "/pages/login/login",
});
return;
}
}
if (this.loading) return; if (this.loading) return;
this.loading = true; this.loading = true;
@ -242,6 +261,17 @@ export default {
// //
goToPublish() { goToPublish() {
console.log(this.userInfo, "userInfo");
if (!this.userInfo.id) {
uni.showToast({
title: "请先登录",
icon: "none",
});
uni.navigateTo({
url: "/pages/login/login",
});
return;
}
uni.navigateTo({ uni.navigateTo({
url: "/pages/notes/publish", url: "/pages/notes/publish",
}); });
@ -270,6 +300,11 @@ export default {
this.currentTab = index; this.currentTab = index;
// tab // tab
this.loadTabContent(this.tabs[index].id); this.loadTabContent(this.tabs[index].id);
//
if (this.tabs[index].id === "follow") {
this.refreshFollowList();
}
}, },
// tab // tab
@ -281,8 +316,14 @@ export default {
this.waterfallItems = []; this.waterfallItems = [];
this.hasMore = true; this.hasMore = true;
this.getRecommendList(0); this.getRecommendList(0);
} else if (tabId === "recommend") {
// tab:
this.pageNum = 1;
this.waterfallItems = [];
this.hasMore = true;
this.getRecommendList(1);
} }
// tab // tab
}, },
// //

27
pages/notes/detail.vue

@ -46,10 +46,10 @@
</view> </view>
<view <view
class="follow-btn" class="follow-btn"
:class="{ followed: noteDetail.user.isFollowed }" :class="{ followed: noteDetail.userFollowed }"
@click="toggleFollow" @click="toggleFollow"
> >
{{ noteDetail.user.isFollowed ? "已关注" : "关注" }} {{ noteDetail.userFollowed ? "已关注" : "关注" }}
</view> </view>
</view> </view>
<!-- 笔记标题 --> <!-- 笔记标题 -->
@ -551,34 +551,35 @@ export default {
// //
async toggleFollow() { async toggleFollow() {
try { try {
const action = this.noteDetail.user.isFollowed ? "cancel" : "follow"; // type12
const type = this.noteDetail.userFollowed ? 2 : 1;
const res = await this.Post( const res = await this.Post(
{ {
method: "POST", followUserId: this.noteDetail.userId, // id
userId: this.noteDetail.user.id, type: type, // 1. 2.
action: action,
}, },
"/framework/user/follow", "/framework/follow/followUser",
"DES" "DES"
); );
console.log(res);
if (res.code === 200) { if (res.code === 200) {
this.noteDetail.user.isFollowed = !this.noteDetail.user.isFollowed; this.noteDetail.userFollowed = !this.noteDetail.userFollowed;
uni.showToast({ uni.showToast({
title: this.noteDetail.user.isFollowed ? "已关注" : "取消关注", title: this.noteDetail.userFollowed ? "已关注" : "取消关注",
icon: "success", icon: "success",
}); });
} else { } else {
uni.showToast({ uni.showToast({
title: title: res.msg || (type === 1 ? "关注失败" : "取消关注失败"),
res.msg || (action === "follow" ? "关注失败" : "取消关注失败"),
icon: "none", icon: "none",
}); });
} }
} catch (error) { } catch (error) {
let res = error.data;
console.error("关注操作失败:", error); console.error("关注操作失败:", error);
uni.showToast({ uni.showToast({
title: "操作失败", title: res.msg || (type === 1 ? "关注失败" : "取消关注失败"),
icon: "none", icon: "none",
}); });
} }
@ -853,7 +854,7 @@ export default {
background-color: white; background-color: white;
padding: 12rpx 30rpx; padding: 12rpx 30rpx;
&.followed { &.followed {
background: #ccc; background: #02fcfc;
} }
} }
} }

BIN
static/imgs/icon-stop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Loading…
Cancel
Save