diff --git a/src/api/shop/shopChatConversation/index.ts b/src/api/shop/shopChatConversation/index.ts new file mode 100644 index 0000000..6a5ba5b --- /dev/null +++ b/src/api/shop/shopChatConversation/index.ts @@ -0,0 +1,101 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { ShopChatConversation, ShopChatConversationParam } from './model'; + +/** + * 分页查询聊天会话表 + */ +export async function pageShopChatConversation(params: ShopChatConversationParam) { + const res = await request.get>>( + '/shop/shop-chat-conversation/page', + params + ); + if (res.code === 0) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询聊天会话表列表 + */ +export async function listShopChatConversation(params?: ShopChatConversationParam) { + const res = await request.get>( + '/shop/shop-chat-conversation', + params + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加聊天会话表 + */ +export async function addShopChatConversation(data: ShopChatConversation) { + const res = await request.post>( + '/shop/shop-chat-conversation', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改聊天会话表 + */ +export async function updateShopChatConversation(data: ShopChatConversation) { + const res = await request.put>( + '/shop/shop-chat-conversation', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除聊天会话表 + */ +export async function removeShopChatConversation(id?: number) { + const res = await request.del>( + '/shop/shop-chat-conversation/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除聊天会话表 + */ +export async function removeShopBatchChatConversation(data: (number | undefined)[]) { + const res = await request.del>( + '/shop/shop-chat-conversation/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询聊天会话表 + */ +export async function getShopChatConversation(id: number) { + const res = await request.get>( + '/shop/shop-chat-conversation/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/shop/shopChatConversation/model/index.ts b/src/api/shop/shopChatConversation/model/index.ts new file mode 100644 index 0000000..ea6a9b3 --- /dev/null +++ b/src/api/shop/shopChatConversation/model/index.ts @@ -0,0 +1,37 @@ +import type { PageParam } from '@/api'; + +/** + * 聊天消息表 + */ +export interface ShopChatConversation { + // 自增ID + id?: number; + // 用户ID + userId?: number; + // 好友ID + friendId?: number; + // 消息类型 + type?: number; + // 消息内容 + content?: string; + // 未读消息 + unRead?: number; + // 状态, 0未读, 1已读 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 注册时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 聊天消息表搜索条件 + */ +export interface ShopChatConversationParam extends PageParam { + id?: number; + keywords?: string; +} diff --git a/src/api/shop/shopChatMessage/index.ts b/src/api/shop/shopChatMessage/index.ts new file mode 100644 index 0000000..4667ce7 --- /dev/null +++ b/src/api/shop/shopChatMessage/index.ts @@ -0,0 +1,115 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { ShopChatMessage, ShopChatMessageParam } from './model'; + +/** + * 分页查询聊天消息表 + */ +export async function pageShopChatMessage(params: ShopChatMessageParam) { + const res = await request.get>>( + '/shop/shop-chat-message/page', + params + ); + if (res.code === 0) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询聊天消息表列表 + */ +export async function listShopChatMessage(params?: ShopChatMessageParam) { + const res = await request.get>( + '/shop/shop-chat-message', + params + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加聊天消息表 + */ +export async function addShopChatMessage(data: ShopChatMessage) { + const res = await request.post>( + '/shop/shop-chat-message', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加聊天消息表 + */ +export async function addShopBatchChatMessage(data: ShopChatMessage[]) { + const res = await request.post>( + '/shop/shop-chat-message/batch', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改聊天消息表 + */ +export async function updateShopChatMessage(data: ShopChatMessage) { + const res = await request.put>( + '/shop/shop-chat-message', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除聊天消息表 + */ +export async function removeShopChatMessage(id?: number) { + const res = await request.del>( + '/shop/shop-chat-message/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除聊天消息表 + */ +export async function removeShopBatchChatMessage(data: (number | undefined)[]) { + const res = await request.del>( + '/shop/shop-chat-message/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询聊天消息表 + */ +export async function getShopChatMessage(id: number) { + const res = await request.get>( + '/shop/shop-chat-message/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/shop/shopChatMessage/model/index.ts b/src/api/shop/shopChatMessage/model/index.ts new file mode 100644 index 0000000..411d45c --- /dev/null +++ b/src/api/shop/shopChatMessage/model/index.ts @@ -0,0 +1,63 @@ +import type { PageParam } from '@/api'; + +/** + * 聊天消息表 + */ +export interface ShopChatMessage { + // 自增ID + id?: number; + // 发送人ID + formUserId?: number; + // 发送人名称 + formUserName?: string; + // 发送人头像 + formUserAvatar?: string; + // 发送人手机号 + formUserPhone?: string; + // 发送人别名 + formUserAlias?: string; + // 接收人ID + toUserId?: number; + // 接收人名称 + toUserName?: string; + // 接收人头像 + toUserAvatar?: string; + // 接收人手机号 + toUserPhone?: string; + // 接收人别名 + toUserAlias?: string; + // 消息类型 + type?: string; + // 消息内容 + content?: string; + // 屏蔽接收方 + sideTo?: number; + // 屏蔽发送方 + sideFrom?: number; + // 是否撤回 + withdraw?: number; + // 文件信息 + fileInfo?: string; + // 批量发送 + toUserIds?: any[]; + // 存在联系方式 + hasContact?: number; + // 状态, 0未读, 1已读 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 注册时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 聊天消息表搜索条件 + */ +export interface ShopChatMessageParam extends PageParam { + id?: number; + keywords?: string; +} diff --git a/src/api/shop/shopDealerReferee/model/index.ts b/src/api/shop/shopDealerReferee/model/index.ts index 61c1e49..044a77d 100644 --- a/src/api/shop/shopDealerReferee/model/index.ts +++ b/src/api/shop/shopDealerReferee/model/index.ts @@ -27,4 +27,5 @@ export interface ShopDealerRefereeParam extends PageParam { id?: number; dealerId?: number; keywords?: string; + deleted?: number; } diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts index c0f144f..0c55116 100644 --- a/src/api/system/user/index.ts +++ b/src/api/system/user/index.ts @@ -1,5 +1,5 @@ import request from '@/utils/request'; -import type {ApiResult, PageResult} from '@/api/index'; +import type {ApiResult, PageResult} from '@/api'; import type {User, UserParam} from './model'; import {SERVER_API_URL} from "@/utils/server"; @@ -8,8 +8,8 @@ import {SERVER_API_URL} from "@/utils/server"; */ export async function pageUsers(params: UserParam) { const res = await request.get>>( - '/system/user/page', - {params} + SERVER_API_URL + '/system/user/page', + params ); if (res.code === 0) { return res.data; @@ -22,10 +22,8 @@ export async function pageUsers(params: UserParam) { */ export async function listUsers(params?: UserParam) { const res = await request.get>( - '/system/user', - { - params - } + SERVER_API_URL + '/system/user', + params ); if (res.code === 0 && res.data) { return res.data; @@ -38,7 +36,7 @@ export async function listUsers(params?: UserParam) { */ export async function getStaffs(params?: UserParam) { const res = await request.get>( - '/system/user', + SERVER_API_URL + '/system/user', { params } @@ -54,7 +52,7 @@ export async function getStaffs(params?: UserParam) { */ export async function getCompanyList(params?: UserParam) { const res = await request.get>( - '/system/user', + SERVER_API_URL + '/system/user', { params } @@ -70,7 +68,7 @@ export async function getCompanyList(params?: UserParam) { */ export async function getUser(id: number) { const res = await request.get>( - '/system/user/' + id, + SERVER_API_URL + '/system/user/' + id, {} ); if (res.code === 0 && res.data) { @@ -84,7 +82,7 @@ export async function getUser(id: number) { */ export async function addUser(data: User) { const res = await request.post>( - '/system/user', + SERVER_API_URL + '/system/user', data ); if (res.code === 0) { @@ -112,7 +110,7 @@ export async function updateUser(data: User) { */ export async function removeUser(id?: number) { const res = await request.del>( - '/system/user/' + id + SERVER_API_URL + '/system/user/' + id ); if (res.code === 0) { return res.message; @@ -125,7 +123,7 @@ export async function removeUser(id?: number) { */ export async function removeUsers(data: (number | undefined)[]) { const res = await request.del>( - '/system/user/batch', + SERVER_API_URL + '/system/user/batch', { data } @@ -141,7 +139,7 @@ export async function removeUsers(data: (number | undefined)[]) { */ export async function updateUserStatus(userId?: number, status?: number) { const res = await request.put>( - '/system/user/status', + SERVER_API_URL + '/system/user/status', { userId, status @@ -156,9 +154,9 @@ export async function updateUserStatus(userId?: number, status?: number) { /** * 修改推荐状态 */ -export async function updateUserRecommend(form) { +export async function updateUserRecommend(form:any) { const res = await request.put>( - '/system/user/recommend', + SERVER_API_URL + '/system/user/recommend', form ); if (res.code === 0) { @@ -172,7 +170,7 @@ export async function updateUserRecommend(form) { */ export async function updateUserPassword(userId?: number, password = '123456') { const res = await request.put>( - '/system/user/password', + SERVER_API_URL + '/system/user/password', { userId, password @@ -191,7 +189,7 @@ export async function importUsers(file: File) { const formData = new FormData(); formData.append('file', file); const res = await request.post>( - '/system/user/import', + SERVER_API_URL + '/system/user/import', formData ); if (res.code === 0) { @@ -209,7 +207,7 @@ export async function checkExistence( id?: number ) { const res = await request.get>( - '/system/user/existence', + SERVER_API_URL + '/system/user/existence', { params: {field, value, id} } @@ -225,7 +223,7 @@ export async function checkExistence( */ export async function countUserBalance(params?: UserParam) { const res = await request.get>( - '/system/user/countUserBalance', + SERVER_API_URL + '/system/user/countUserBalance', { params } @@ -243,7 +241,7 @@ export async function countUserBalance(params?: UserParam) { */ export async function listAdminsByPhoneAll(params?: UserParam) { const res = await request.get>( - '/system/user/listAdminsByPhoneAll', + SERVER_API_URL + '/system/user/listAdminsByPhoneAll', params ); if (res.code === 0 && res.data) { diff --git a/src/api/system/user/model/index.ts b/src/api/system/user/model/index.ts index 33c8feb..ab734c4 100644 --- a/src/api/system/user/model/index.ts +++ b/src/api/system/user/model/index.ts @@ -128,6 +128,8 @@ export interface User { certification?: boolean; // 实名认证类型 certificationType?: number; + // 推荐人ID + refereeId?: number; } /** diff --git a/src/app.config.ts b/src/app.config.ts index 88fdfb6..3f56943 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -60,6 +60,10 @@ export default { "store/verification", "theme/index", "poster/poster", + "chat/conversation/index", + "chat/message/index", + "chat/message/add", + "chat/message/detail" ] }, { diff --git a/src/dealer/apply/add.config.ts b/src/dealer/apply/add.config.ts index 8c40d08..ac37521 100644 --- a/src/dealer/apply/add.config.ts +++ b/src/dealer/apply/add.config.ts @@ -1,4 +1,4 @@ export default definePageConfig({ - navigationBarTitleText: '注册成为VIP', + navigationBarTitleText: '邀请注册', navigationBarTextStyle: 'black' }) diff --git a/src/dealer/apply/add.tsx b/src/dealer/apply/add.tsx index 08c2f15..f862bf3 100644 --- a/src/dealer/apply/add.tsx +++ b/src/dealer/apply/add.tsx @@ -1,96 +1,210 @@ import {useEffect, useState, useRef} from "react"; -import {Loading, CellGroup, Cell, Input, Form} from '@nutui/nutui-react-taro' +import {Loading, CellGroup, Input, Form, Avatar, Button, Space} from '@nutui/nutui-react-taro' import {Edit} from '@nutui/icons-react-taro' import Taro from '@tarojs/taro' import {View} from '@tarojs/components' import FixedButton from "@/components/FixedButton"; import {useUser} from "@/hooks/useUser"; -import {ShopDealerApply} from "@/api/shop/shopDealerApply/model"; -import { - addShopDealerApply, - pageShopDealerApply, - updateShopDealerApply -} from "@/api/shop/shopDealerApply"; -import {getShopDealerUser} from "@/api/shop/shopDealerUser"; +import {TenantId} from "@/config/app"; +import {updateUser} from "@/api/system/user"; +import {User} from "@/api/system/user/model"; +import {getStoredInviteParams, handleInviteRelation} from "@/utils/invite"; +import {addShopDealerUser} from "@/api/shop/shopDealerUser"; +import {listUserRole, updateUserRole} from "@/api/system/userRole"; + +// 类型定义 +interface ChooseAvatarEvent { + detail: { + avatarUrl: string; + }; +} + +interface InputEvent { + detail: { + value: string; + }; +} const AddUserAddress = () => { - const {user} = useUser() + const {user, loginUser} = useUser() const [loading, setLoading] = useState(true) - const [FormData, setFormData] = useState() + const [FormData, setFormData] = useState() const formRef = useRef(null) - const [isEditMode, setIsEditMode] = useState(false) - const [existingApply, setExistingApply] = useState(null) - - // 获取审核状态文字 - const getApplyStatusText = (status?: number) => { - switch (status) { - case 10: - return '待审核' - case 20: - return '审核通过' - case 30: - return '驳回' - default: - return '未知状态' + + const reload = async () => { + const inviteParams = getStoredInviteParams() + if (inviteParams?.inviter) { + setFormData({ + ...user, + refereeId: Number(inviteParams.inviter), + // 清空昵称,强制用户手动输入 + nickname: '', + }) + } else { + // 如果没有邀请参数,也要确保昵称为空 + setFormData({ + ...user, + nickname: '', + }) } } - const reload = async () => { - // 判断用户是否登录 - if (!user?.userId) { - return false; + + const uploadAvatar = ({detail}: ChooseAvatarEvent) => { + // 先更新本地显示的头像(临时显示) + const tempFormData = { + ...FormData, + avatar: `${detail.avatarUrl}`, } - // 查询当前用户ID是否已有申请记录 - try { - const res = await pageShopDealerApply({userId: user?.userId}); - if (res && res.count > 0) { - setIsEditMode(true); - setExistingApply(res.list[0]); - // 如果有记录,填充表单数据 - setFormData(res.list[0]); - setLoading(false) - } else { - setIsEditMode(false); - setExistingApply(null); - setLoading(false) + setFormData(tempFormData) + + Taro.uploadFile({ + url: 'https://server.websoft.top/api/oss/upload', + filePath: detail.avatarUrl, + name: 'file', + header: { + 'content-type': 'application/json', + TenantId + }, + success: async (res) => { + const data = JSON.parse(res.data); + if (data.code === 0) { + const finalAvatarUrl = `${data.data.thumbnail}` + + try { + // 使用 useUser hook 的 updateUser 方法更新头像 + await updateUser({ + avatar: finalAvatarUrl + }) + + Taro.showToast({ + title: '头像上传成功', + icon: 'success', + duration: 1500 + }) + } catch (error) { + console.error('更新用户头像失败:', error) + } + + // 无论用户信息更新是否成功,都要更新本地FormData + const finalFormData = { + ...tempFormData, + avatar: finalAvatarUrl + } + setFormData(finalFormData) + + // 同步更新表单字段 + if (formRef.current) { + formRef.current.setFieldsValue({ + avatar: finalAvatarUrl + }) + } + } else { + // 上传失败,恢复原来的头像 + setFormData({ + ...FormData, + avatar: user?.avatar || '' + }) + Taro.showToast({ + title: '上传失败', + icon: 'error' + }) + } + }, + fail: (error) => { + console.error('上传头像失败:', error) + Taro.showToast({ + title: '上传失败', + icon: 'error' + }) + // 恢复原来的头像 + setFormData({ + ...FormData, + avatar: user?.avatar || '' + }) } - } catch (error) { - setLoading(true) - console.error('查询申请记录失败:', error); - setIsEditMode(false); - setExistingApply(null); - } + }) } // 提交表单 const submitSucceed = async (values: any) => { try { + // 验证必填字段 + if (!values.phone && !FormData?.phone) { + Taro.showToast({ + title: '请先获取手机号', + icon: 'error' + }); + return; + } - // 准备提交的数据 - const submitData = { - ...values, - realName: values.realName || user?.nickname, - mobile: user?.phone, - refereeId: values.refereeId || FormData?.refereeId, - applyStatus: 10, - auditTime: undefined - }; - await getShopDealerUser(submitData.refereeId); - - // 如果是编辑模式,添加现有申请的id - if (isEditMode && existingApply?.applyId) { - submitData.applyId = existingApply.applyId; + // 验证昵称:必须填写且不能是默认的微信昵称 + const nickname = values.realName || FormData?.nickname || ''; + if (!nickname || nickname.trim() === '') { + Taro.showToast({ + title: '请填写昵称', + icon: 'error' + }); + return; + } + + // 检查是否为默认的微信昵称(常见的默认昵称) + const defaultNicknames = ['微信用户', 'WeChat User', '微信昵称']; + if (defaultNicknames.includes(nickname.trim())) { + Taro.showToast({ + title: '请填写真实昵称,不能使用默认昵称', + icon: 'error' + }); + return; + } + + // 验证昵称长度 + if (nickname.trim().length < 2) { + Taro.showToast({ + title: '昵称至少需要2个字符', + icon: 'error' + }); + return; + } + + if (!values.avatar && !FormData?.avatar) { + Taro.showToast({ + title: '请上传头像', + icon: 'error' + }); + return; } + console.log(values,FormData) + + const roles = await listUserRole({userId: user?.userId}) + console.log(roles, 'roles...') + + // 准备提交的数据 + await updateUser({ + userId: user?.userId, + nickname: values.realName || FormData?.nickname, + phone: values.phone || FormData?.phone, + avatar: values.avatar || FormData?.avatar, + refereeId: values.refereeId || FormData?.refereeId + }); - // 执行新增或更新操作 - if (isEditMode) { - await updateShopDealerApply(submitData); - } else { - await addShopDealerApply(submitData); + await addShopDealerUser({ + userId: user?.userId, + realName: values.realName || FormData?.nickname, + mobile: values.phone || FormData?.phone, + refereeId: values.refereeId || FormData?.refereeId + }) + + if (roles.length > 0) { + await updateUserRole({ + ...roles[0], + roleId: 1848 + }) } + Taro.showToast({ - title: `${isEditMode ? '提交' : '提交'}成功`, + title: `注册成功`, icon: 'success' }); @@ -100,13 +214,130 @@ const AddUserAddress = () => { } catch (error) { console.error('验证邀请人失败:', error); - return Taro.showToast({ - title: '邀请人ID不存在', - icon: 'error' - }); } } + // 获取微信昵称 + const getWxNickname = (nickname: string) => { + // 更新表单数据 + const updatedFormData = { + ...FormData, + nickname: nickname + } + setFormData(updatedFormData); + + // 同步更新表单字段 + if (formRef.current) { + formRef.current.setFieldsValue({ + realName: nickname + }) + } + } + + /* 获取用户手机号 */ + const handleGetPhoneNumber = ({detail}: { detail: { code?: string, encryptedData?: string, iv?: string } }) => { + const {code, encryptedData, iv} = detail + Taro.login({ + success: (loginRes) => { + if (code) { + Taro.request({ + url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', + method: 'POST', + data: { + authCode: loginRes.code, + code, + encryptedData, + iv, + notVerifyPhone: true, + refereeId: 0, + sceneType: 'save_referee', + tenantId: TenantId + }, + header: { + 'content-type': 'application/json', + TenantId + }, + success: async function (res) { + if (res.data.code == 1) { + Taro.showToast({ + title: res.data.message, + icon: 'error', + duration: 2000 + }) + return false; + } + // 登录成功 + const token = res.data.data.access_token; + const userData = res.data.data.user; + console.log(userData, 'userData...') + // 使用useUser Hook的loginUser方法更新状态 + loginUser(token, userData); + + if (userData.phone) { + console.log('手机号已获取', userData.phone) + const updatedFormData = { + ...FormData, + phone: userData.phone, + // 不自动填充微信昵称,保持用户已输入的昵称 + nickname: FormData?.nickname || '', + // 只在没有头像时才使用微信头像 + avatar: FormData?.avatar || userData.avatar + } + setFormData(updatedFormData) + + // 更新表单字段值 + if (formRef.current) { + formRef.current.setFieldsValue({ + phone: userData.phone, + // 不覆盖用户已输入的昵称 + realName: FormData?.nickname || '', + avatar: FormData?.avatar || userData.avatar + }) + } + + Taro.showToast({ + title: '手机号获取成功', + icon: 'success', + duration: 1500 + }) + } + + + // 处理邀请关系 + if (userData?.userId) { + try { + const inviteSuccess = await handleInviteRelation(userData.userId) + if (inviteSuccess) { + Taro.showToast({ + title: '邀请关系建立成功', + icon: 'success', + duration: 2000 + }) + } + } catch (error) { + console.error('处理邀请关系失败:', error) + } + } + + // 显示登录成功提示 + // Taro.showToast({ + // title: '注册成功', + // icon: 'success', + // duration: 1500 + // }) + + // 不需要重新启动小程序,状态已经通过useUser更新 + // 可以选择性地刷新当前页面数据 + // await reload(); + } + }) + } else { + console.log('登录失败!') + } + } + }) + } + // 处理固定按钮点击事件 const handleFixedButtonClick = () => { // 触发表单提交 @@ -123,6 +354,18 @@ const AddUserAddress = () => { }) }, [user?.userId]); // 依赖用户ID,当用户变化时重新加载 + // 当FormData变化时,同步更新表单字段值 + useEffect(() => { + if (formRef.current && FormData) { + formRef.current.setFieldsValue({ + refereeId: FormData.refereeId, + phone: FormData.phone, + avatar: FormData.avatar, + realName: FormData.nickname + }); + } + }, [FormData]); + if (loading) { return 加载中 } @@ -139,50 +382,49 @@ const AddUserAddress = () => { > - - + + - - + + + + + + + - - + { + FormData?.phone && + + + } + + getWxNickname(e.detail.value)} + /> - {/* 审核状态显示(仅在编辑模式下显示) */} - {isEditMode && ( - - - {getApplyStatusText(FormData?.applyStatus)} - - } - /> - {FormData?.applyStatus === 20 && ( - - )} - {FormData?.applyStatus === 30 && ( - - )} - - )} - {/* 底部浮动按钮 */} - {(!isEditMode || FormData?.applyStatus === 10 || FormData?.applyStatus === 30) && ( - } - text={isEditMode ? '保存修改' : '提交申请'} - disabled={FormData?.applyStatus === 10} - onClick={handleFixedButtonClick} - /> - )} + } + text={'立即注册'} + onClick={handleFixedButtonClick} + /> ); diff --git a/src/dealer/team/index.config.ts b/src/dealer/team/index.config.ts index 926f186..ddd6b66 100644 --- a/src/dealer/team/index.config.ts +++ b/src/dealer/team/index.config.ts @@ -1,3 +1,3 @@ export default definePageConfig({ - navigationBarTitleText: '我的团队' + navigationBarTitleText: '邀请推广' }) diff --git a/src/dealer/team/index.tsx b/src/dealer/team/index.tsx index 90cb9ac..af7d8e7 100644 --- a/src/dealer/team/index.tsx +++ b/src/dealer/team/index.tsx @@ -1,33 +1,139 @@ import React, {useState, useEffect, useCallback} from 'react' import {View, Text} from '@tarojs/components' -import {Space, Avatar, Loading} from '@nutui/nutui-react-taro' -import {User} from '@nutui/icons-react-taro' +import {Phone, Edit, Message} from '@nutui/icons-react-taro' +import {Space, Empty, Avatar, Button} from '@nutui/nutui-react-taro' import Taro from '@tarojs/taro' import {useDealerUser} from '@/hooks/useDealerUser' import {listShopDealerReferee} from '@/api/shop/shopDealerReferee' import {pageShopDealerOrder} from '@/api/shop/shopDealerOrder' import type {ShopDealerReferee} from '@/api/shop/shopDealerReferee/model' +import FixedButton from "@/components/FixedButton"; +import navTo from "@/utils/common"; +import {updateUser} from "@/api/system/user"; interface TeamMemberWithStats extends ShopDealerReferee { name?: string avatar?: string + nickname?: string; + alias?: string; + phone?: string; orderCount?: number commission?: string status?: 'active' | 'inactive' subMembers?: number joinTime?: string + dealerAvatar?: string; + dealerName?: string; + dealerPhone?: string; +} + +// 层级信息接口 +interface LevelInfo { + dealerId: number + dealerName?: string + level: number } const DealerTeam: React.FC = () => { const [teamMembers, setTeamMembers] = useState([]) const {dealerUser} = useDealerUser() const [dealerId, setDealerId] = useState() + // 层级栈,用于支持返回上一层 + const [levelStack, setLevelStack] = useState([]) + const [loading, setLoading] = useState(false) + // 当前查看的用户名称 + const [currentDealerName, setCurrentDealerName] = useState('') + + // 异步加载成员统计数据 + const loadMemberStats = async (members: TeamMemberWithStats[]) => { + // 分批处理,避免过多并发请求 + const batchSize = 3 + for (let i = 0; i < members.length; i += batchSize) { + const batch = members.slice(i, i + batchSize) + + const batchStats = await Promise.all( + batch.map(async (member) => { + try { + // 并行获取订单统计和下级成员数量 + const [orderResult, subMembersResult] = await Promise.all([ + pageShopDealerOrder({ + page: 1, + userId: member.userId + }), + listShopDealerReferee({ + dealerId: member.userId, + deleted: 0 + }) + ]) + + let orderCount = 0 + let commission = '0.00' + let status: 'active' | 'inactive' = 'inactive' + + if (orderResult?.list) { + const orders = orderResult.list + orderCount = orders.length + commission = orders.reduce((sum, order) => { + const levelCommission = member.level === 1 ? order.firstMoney : + member.level === 2 ? order.secondMoney : + order.thirdMoney + return sum + parseFloat(levelCommission || '0') + }, 0).toFixed(2) + + // 判断活跃状态(30天内有订单为活跃) + const thirtyDaysAgo = new Date() + thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30) + const hasRecentOrder = orders.some(order => + new Date(order.createTime || '') > thirtyDaysAgo + ) + status = hasRecentOrder ? 'active' : 'inactive' + } + + return { + ...member, + orderCount, + commission, + status, + subMembers: subMembersResult?.length || 0 + } + } catch (error) { + console.error(`获取成员${member.userId}数据失败:`, error) + return { + ...member, + orderCount: 0, + commission: '0.00', + status: 'inactive' as const, + subMembers: 0 + } + } + }) + ) + + // 更新这一批成员的数据 + setTeamMembers(prevMembers => { + const updatedMembers = [...prevMembers] + batchStats.forEach(updatedMember => { + const index = updatedMembers.findIndex(m => m.userId === updatedMember.userId) + if (index !== -1) { + updatedMembers[index] = updatedMember + } + }) + return updatedMembers + }) + + // 添加小延迟,避免请求过于密集 + if (i + batchSize < members.length) { + await new Promise(resolve => setTimeout(resolve, 100)) + } + } + } // 获取团队数据 const fetchTeamData = useCallback(async () => { if (!dealerUser?.userId && !dealerId) return try { + setLoading(true) console.log(dealerId, 'dealerId>>>>>>>>>') // 获取团队成员关系 const refereeResult = await listShopDealerReferee({ @@ -35,11 +141,11 @@ const DealerTeam: React.FC = () => { }) if (refereeResult) { + console.log('团队成员原始数据:', refereeResult) // 处理团队成员数据 const processedMembers: TeamMemberWithStats[] = refereeResult.map(member => ({ ...member, - name: `用户${member.userId}`, - avatar: '', + name: `${member.userId}`, orderCount: 0, commission: '0.00', status: 'active' as const, @@ -47,49 +153,12 @@ const DealerTeam: React.FC = () => { joinTime: member.createTime })) - // 并行获取每个成员的订单统计 - const memberStats = await Promise.all( - processedMembers.map(async (member) => { - try { - const orderResult = await pageShopDealerOrder({ - page: 1, - limit: 100, - userId: member.userId - }) - - if (orderResult?.list) { - const orders = orderResult.list - const orderCount = orders.length - const commission = orders.reduce((sum, order) => { - const levelCommission = member.level === 1 ? order.firstMoney : - member.level === 2 ? order.secondMoney : - order.thirdMoney - return sum + parseFloat(levelCommission || '0') - }, 0).toFixed(2) - - // 判断活跃状态(30天内有订单为活跃) - const thirtyDaysAgo = new Date() - thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30) - const hasRecentOrder = orders.some(order => - new Date(order.createTime || '') > thirtyDaysAgo - ) - - return { - ...member, - orderCount, - commission, - status: hasRecentOrder ? 'active' as const : 'inactive' as const - } - } - return member - } catch (error) { - console.error(`获取成员${member.userId}订单失败:`, error) - return member - } - }) - ) + // 先显示基础数据,然后异步加载详细统计 + setTeamMembers(processedMembers) + setLoading(false) - setTeamMembers(memberStats) + // 异步加载每个成员的详细统计数据 + loadMemberStats(processedMembers) } } catch (error) { @@ -98,12 +167,106 @@ const DealerTeam: React.FC = () => { title: '获取团队数据失败', icon: 'error' }) + } finally { + setLoading(false) } }, [dealerUser?.userId, dealerId]) + // 查看下级成员 const getNextUser = (item: TeamMemberWithStats) => { + // 检查层级限制:最多只能查看2层(levelStack.length >= 1 表示已经是第2层了) + if (levelStack.length >= 1) { + return + } + + // 如果没有下级成员,不允许点击 + if (!item.subMembers || item.subMembers === 0) { + return + } + console.log('点击用户:', item.userId, item.name) + + // 将当前层级信息推入栈中 + const currentLevel: LevelInfo = { + dealerId: dealerId || dealerUser?.userId || 0, + dealerName: currentDealerName || (dealerId ? '上级' : dealerUser?.realName || '我'), + level: levelStack.length + } + setLevelStack(prev => [...prev, currentLevel]) + + // 切换到下级 setDealerId(item.userId) + setCurrentDealerName(item.nickname || item.dealerName || `用户${item.userId}`) + } + + // 返回上一层 + const goBack = () => { + if (levelStack.length === 0) { + // 如果栈为空,返回首页或上一页 + Taro.navigateBack() + return + } + + // 从栈中弹出上一层信息 + const prevLevel = levelStack[levelStack.length - 1] + setLevelStack(prev => prev.slice(0, -1)) + + if (prevLevel.dealerId === (dealerUser?.userId || 0)) { + // 返回到根层级 + setDealerId(undefined) + setCurrentDealerName('') + } else { + setDealerId(prevLevel.dealerId) + setCurrentDealerName(prevLevel.dealerName || '') + } + } + + // 一键拨打 + const makePhoneCall = (phone: string) => { + Taro.makePhoneCall({ + phoneNumber: phone, + fail: () => { + Taro.showToast({ + title: '拨打取消', + icon: 'error' + }); + } + }); + }; + + // 别名备注 + const editAlias = (item: any, index: number) => { + Taro.showModal({ + title: '备注', + // @ts-ignore + editable: true, + placeholderText: '真实姓名', + content: item.alias || '', + success: async (res: any) => { + if (res.confirm && res.content !== undefined) { + try { + // 更新跟进情况 + await updateUser({ + userId: item.userId, + alias: res.content.trim() + }); + teamMembers[index].alias = res.content.trim() + setTeamMembers(teamMembers) + } catch (error) { + console.error('备注失败:', error); + Taro.showToast({ + title: '备注失败,请重试', + icon: 'error' + }); + } + } + } + }); + }; + + // 发送消息 + const sendMessage = (item: TeamMemberWithStats) => { + return navTo(`/user/chat/message/add?id=${item.userId}`, true) } // 监听数据变化,获取团队数据 @@ -113,81 +276,164 @@ const DealerTeam: React.FC = () => { } }, [fetchTeamData]) - const renderMemberItem = (member: TeamMemberWithStats) => ( - getNextUser(member)}> - - } - className="mr-3" - /> - - - - {member.name} + // 初始化当前用户名称 + useEffect(() => { + if (!dealerId && dealerUser?.realName && !currentDealerName) { + setCurrentDealerName(dealerUser.realName) + } + }, [dealerUser, dealerId, currentDealerName]) + + const renderMemberItem = (member: TeamMemberWithStats, index: number) => { + // 判断是否可以点击:有下级成员且未达到层级限制 + const canClick = member.subMembers && member.subMembers > 0 && levelStack.length < 1 + // 判断是否显示手机号:只有本级(levelStack.length === 0)才显示 + const showPhone = levelStack.length === 0 + // 判断数据是否还在加载中(初始值都是0或'0.00') + const isStatsLoading = member.orderCount === 0 && member.commission === '0.00' && member.subMembers === 0 + + return ( + getNextUser(member)} + > + + + + + + + {member.alias ? {member.alias} : + {member.nickname}} + {/*别名备注*/} + { + e.stopPropagation() + editAlias(member, index) + }}/> + {/*发送消息*/} + { + e.stopPropagation() + sendMessage(member) + }}/> + + + {/* 显示手机号(仅本级可见) */} + {showPhone && member.phone && ( + { + e.stopPropagation(); + makePhoneCall(member.phone || ''); + }}> + {member.phone} + + + )} + + + 加入时间:{member.joinTime} - {/*{getLevelIcon(Number(member.level))}*/} - {/**/} - {/* {member.level}级*/} - {/**/} - - 加入时间:{member.joinTime} - - {/**/} - {/* */} - {/* {member.status === 'active' ? '活跃' : '沉默'}*/} - {/* */} - {/**/} - - - - 订单数 - - {member.orderCount} - - - - 贡献佣金 - - ¥{member.commission} - - - - 团队成员 - - {member.subMembers} - - + + + 订单数 + + {isStatsLoading ? '-' : member.orderCount} + + + + 贡献佣金 + + {isStatsLoading ? '-' : `¥${member.commission}`} + + + + 团队成员 + + {isStatsLoading ? '-' : (member.subMembers || 0)} + + + - - ) + ) + } const renderOverview = () => ( - {teamMembers.slice(0, 3).map(renderMemberItem)} + + 我的团队成员 + 成员数:{teamMembers.length} + + {teamMembers.map(renderMemberItem)} ) - if (!dealerUser) { + // 渲染顶部导航栏 + const renderHeader = () => { + if (levelStack.length === 0) return null + return ( - - - 加载中... + + + + + {currentDealerName}的团队成员 + + + + ) } + if (!dealerUser) { + return ( + + navTo(`/dealer/apply/add`, true)}]} + /> + + ) + } + return ( - - {renderOverview()} - + <> + {renderHeader()} + + {loading ? ( + + 加载中... + + ) : teamMembers.length > 0 ? ( + renderOverview() + ) : ( + + + + )} + + navTo(`/dealer/qrcode/index`, true)}/> + ) } -export default DealerTeam +export default DealerTeam; diff --git a/src/pages/user/components/UserGrid.tsx b/src/pages/user/components/UserGrid.tsx index c9a8e3b..5c3e5da 100644 --- a/src/pages/user/components/UserGrid.tsx +++ b/src/pages/user/components/UserGrid.tsx @@ -7,7 +7,7 @@ import { Location, Tips, Ask, - Dongdong, + // Dongdong, People, // AfterSaleService, Logout, @@ -95,13 +95,13 @@ const UserCell = () => { - navTo('/dealer/qrcode/index', true)}> - - - - - - + {/* navTo('/dealer/qrcode/index', true)}>*/} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/**/} {/* navTo('/admin/index', true)}>*/} {/* */} diff --git a/src/user/chat/conversation/index.config.ts b/src/user/chat/conversation/index.config.ts new file mode 100644 index 0000000..93dd2b9 --- /dev/null +++ b/src/user/chat/conversation/index.config.ts @@ -0,0 +1,3 @@ +export default definePageConfig({ + navigationBarTitleText: '站内消息' +}) diff --git a/src/user/chat/conversation/index.tsx b/src/user/chat/conversation/index.tsx new file mode 100644 index 0000000..90b3e6f --- /dev/null +++ b/src/user/chat/conversation/index.tsx @@ -0,0 +1,167 @@ +import {useState, useCallback, useEffect} from 'react' +import {View, Text} from '@tarojs/components' +import Taro from '@tarojs/taro' +import {Loading, InfiniteLoading, Empty, Space, Tag} from '@nutui/nutui-react-taro' +import {pageShopChatConversation} from "@/api/shop/shopChatConversation"; +import FixedButton from "@/components/FixedButton"; + +const Index = () => { + const [list, setList] = useState([]) + const [loading, setLoading] = useState(false) + const [page, setPage] = useState(1) + const [hasMore, setHasMore] = useState(true) + + // 获取消息数据 + const fetchMessageData = useCallback(async (resetPage = false, targetPage?: number, searchKeyword?: string) => { + setLoading(true); + try { + const currentPage = resetPage ? 1 : (targetPage || page); + + // 构建API参数,根据状态筛选 + const params: any = { + page: currentPage + }; + + // 添加搜索关键词 + if (searchKeyword && searchKeyword.trim()) { + params.keywords = searchKeyword.trim(); + } + + const res = await pageShopChatConversation(params); + + if (res?.list && res.list.length > 0) { + // 正确映射状态 + const mappedList = res.list.map(customer => ({ + ...customer + })); + + // 如果是重置页面或第一页,直接设置新数据;否则追加数据 + if (resetPage || currentPage === 1) { + setList(mappedList); + } else { + setList(prevList => prevList.concat(mappedList)); + } + + // 正确判断是否还有更多数据 + const hasMoreData = res.list.length >= 10; // 假设每页10条数据 + setHasMore(hasMoreData); + } else { + if (resetPage || currentPage === 1) { + setList([]); + } + setHasMore(false); + } + + setPage(currentPage); + } catch (error) { + console.error('获取消息数据失败:', error); + Taro.showToast({ + title: '加载失败,请重试', + icon: 'none' + }); + } finally { + setLoading(false); + } + }, [page]); + + const reloadMore = async () => { + if (loading || !hasMore) return; // 防止重复加载 + const nextPage = page + 1; + await fetchMessageData(false, nextPage); + } + + + // 获取列表数据(现在使用服务端搜索,不需要消息端过滤) + const getFilteredList = () => { + return list; + }; + + useEffect(() => { + // 初始化时加载数据 + fetchMessageData(true, 1, ''); + }, []); + + // 渲染消息项 + const renderMessageItem = (customer: any) => ( + + + + + + 关于XXXX的通知 + + 未读 + {/*已读*/} + + + {/*统一代码:{customer.dealerCode}*/} + + 创建时间:{customer.createTime} + + + + + + ); + + // 渲染消息列表 + const renderMessageList = () => { + const filteredList = getFilteredList(); + + return ( + + { + // 滚动事件处理 + }} + onScrollToUpper={() => { + // 滚动到顶部事件处理 + }} + loadingText={ + <> + 加载中... + + } + loadMoreText={ + filteredList.length === 0 ? ( + + ) : ( + + 没有更多了 + + ) + } + > + {loading && filteredList.length === 0 ? ( + + + 加载中... + + ) : ( + filteredList.map(renderMessageItem) + )} + + + ); + }; + + return ( + + {/* 消息列表 */} + {renderMessageList()} + + + ); +}; + +export default Index; diff --git a/src/user/chat/message/add.config.ts b/src/user/chat/message/add.config.ts new file mode 100644 index 0000000..f59b48a --- /dev/null +++ b/src/user/chat/message/add.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '发送消息', + navigationBarTextStyle: 'black' +}) diff --git a/src/user/chat/message/add.tsx b/src/user/chat/message/add.tsx new file mode 100644 index 0000000..a455fd0 --- /dev/null +++ b/src/user/chat/message/add.tsx @@ -0,0 +1,135 @@ +import {useEffect, useState, useRef} from "react"; +import {useRouter} from '@tarojs/taro' +import {Loading, CellGroup, Input, Form, Cell, Avatar} from '@nutui/nutui-react-taro' +import {ArrowRight} from '@nutui/icons-react-taro' +import {View, Text} from '@tarojs/components' +import Taro from '@tarojs/taro' +import FixedButton from "@/components/FixedButton"; +import {addShopChatMessage} from "@/api/shop/shopChatMessage"; +import {ShopChatMessage} from "@/api/shop/shopChatMessage/model"; +import navTo from "@/utils/common"; +import {getUser} from "@/api/system/user"; +import {User} from "@/api/system/user/model"; + +const AddMessage = () => { + const {params} = useRouter(); + const [toUser, setToUser] = useState() + const [loading, setLoading] = useState(true) + const [FormData, _] = useState() + const formRef = useRef(null) + + // 判断是编辑还是新增模式 + const isEditMode = !!params.id + const toUserId = params.id ? Number(params.id) : undefined + + const reload = async () => { + if(toUserId){ + getUser(Number(toUserId)).then(data => { + setToUser(data) + }) + } + } + + // 提交表单 + const submitSucceed = async (values: any) => { + try { + // 准备提交的数据 + const submitData = { + ...values + }; + + console.log('提交数据:', submitData) + + // 参数校验 + if(!toUser){ + Taro.showToast({ + title: `请选择发送对象`, + icon: 'error' + }); + return false; + } + + // 判断内容是否为空 + if (!values.content) { + Taro.showToast({ + title: `请输入内容`, + icon: 'error' + }); + return false; + } + // 执行新增或更新操作 + await addShopChatMessage({ + toUserId: toUserId, + formUserId: Taro.getStorageSync('UserId'), + type: 'text', + content: values.content + }); + + Taro.showToast({ + title: `发送成功`, + icon: 'success' + }); + + setTimeout(() => { + Taro.navigateBack(); + }, 1000); + + } catch (error) { + console.error('发送失败:', error); + Taro.showToast({ + title: `发送失败`, + icon: 'error' + }); + } + } + + const submitFailed = (error: any) => { + console.log(error, 'err...') + } + + useEffect(() => { + reload().then(() => { + setLoading(false) + }) + }, [isEditMode]); + + if (loading) { + return 加载中 + } + + return ( + <> + + + + {toUser.alias || toUser.nickname} + {toUser.mobile} + + + ) : '选择发送对象'} extra={( + + )} + onClick={() => navTo(`/dealer/team/index`, true)}/> +
submitSucceed(values)} + onFinishFailed={(errors) => submitFailed(errors)} + > + + + + + +
+ + {/* 底部浮动按钮 */} + formRef.current?.submit()}/> + + ); +}; + +export default AddMessage; diff --git a/src/user/chat/message/detail.config.ts b/src/user/chat/message/detail.config.ts new file mode 100644 index 0000000..5072884 --- /dev/null +++ b/src/user/chat/message/detail.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '查看消息', + navigationBarTextStyle: 'black' +}) diff --git a/src/user/chat/message/detail.tsx b/src/user/chat/message/detail.tsx new file mode 100644 index 0000000..a7b9c78 --- /dev/null +++ b/src/user/chat/message/detail.tsx @@ -0,0 +1,77 @@ +import {useEffect, useState} from "react"; +import {useRouter} from '@tarojs/taro' +import {CellGroup, Cell, Loading, Avatar} from '@nutui/nutui-react-taro' +import {View,Text} from '@tarojs/components' +import {ArrowRight} from '@nutui/icons-react-taro' +import {getShopChatMessage, updateShopChatMessage} from "@/api/shop/shopChatMessage"; +import {ShopChatMessage} from "@/api/shop/shopChatMessage/model"; +import navTo from "@/utils/common"; + +const AddMessageDetail = () => { + const {params} = useRouter(); + const [loading, setLoading] = useState(true) + const [item, setItem] = useState() + + const reload = () => { + const id = params.id ? Number(params.id) : undefined + if (id) { + getShopChatMessage(id).then(data => { + setItem(data) + setLoading(false) + updateShopChatMessage({ + ...data, + status: 1 + }).then(() => { + console.log('设为已读') + }) + }) + } + } + + useEffect(() => { + reload() + }, []); + + if (loading) { + return 加载中 + } + + return ( + <> + + + + {item.formUserAlias || item.formUserName} + {item.formUserPhone} + +
+ ) : '选择发送对象'} extra={( + + )} + onClick={() => navTo(`/dealer/team/index`, true)}/> + + + + + {/**/} + {/* {'消息内容:'}*/} + {/* {item?.content}*/} + {/* */} + {/*)} />*/} + + + {item?.content} + )} /> + + + ); +}; + +export default AddMessageDetail; diff --git a/src/user/chat/message/index.config.ts b/src/user/chat/message/index.config.ts new file mode 100644 index 0000000..8c6bf6a --- /dev/null +++ b/src/user/chat/message/index.config.ts @@ -0,0 +1,3 @@ +export default definePageConfig({ + navigationBarTitleText: '我的消息' +}) diff --git a/src/user/chat/message/index.tsx b/src/user/chat/message/index.tsx new file mode 100644 index 0000000..479e7a5 --- /dev/null +++ b/src/user/chat/message/index.tsx @@ -0,0 +1,179 @@ +import {useState, useCallback, useEffect} from 'react' +import {View, Text} from '@tarojs/components' +import Taro from '@tarojs/taro' +import {Loading, InfiniteLoading, Empty, Avatar, Badge} from '@nutui/nutui-react-taro' +import FixedButton from "@/components/FixedButton"; +import {ShopChatMessage} from "@/api/shop/shopChatMessage/model"; +import {pageShopChatMessage} from "@/api/shop/shopChatMessage"; +import navTo from "@/utils/common"; + +const MessageIndex = () => { + const [list, setList] = useState([]) + const [loading, setLoading] = useState(false) + const [page, setPage] = useState(1) + const [hasMore, setHasMore] = useState(true) + + // 获取消息数据 + const fetchMessageData = useCallback(async (resetPage = false, targetPage?: number, searchKeyword?: string) => { + setLoading(true); + try { + const currentPage = resetPage ? 1 : (targetPage || page); + + // 构建API参数,根据状态筛选 + const params: any = { + type: 'text', + page: currentPage, + toUserId: Taro.getStorageSync('UserId') + }; + + // 添加搜索关键词 + if (searchKeyword && searchKeyword.trim()) { + params.keywords = searchKeyword.trim(); + } + + const res = await pageShopChatMessage(params); + + if (res?.list && res.list.length > 0) { + // 正确映射状态 + const mappedList = res.list.map(customer => ({ + ...customer + })); + + // 如果是重置页面或第一页,直接设置新数据;否则追加数据 + if (resetPage || currentPage === 1) { + setList(mappedList); + } else { + setList(prevList => prevList.concat(mappedList)); + } + + // 正确判断是否还有更多数据 + const hasMoreData = res.list.length >= 10; // 假设每页10条数据 + setHasMore(hasMoreData); + } else { + if (resetPage || currentPage === 1) { + setList([]); + } + setHasMore(false); + } + + setPage(currentPage); + } catch (error) { + console.error('获取消息数据失败:', error); + Taro.showToast({ + title: '加载失败,请重试', + icon: 'none' + }); + } finally { + setLoading(false); + } + }, [page]); + + const reloadMore = async () => { + if (loading || !hasMore) return; // 防止重复加载 + const nextPage = page + 1; + await fetchMessageData(false, nextPage); + } + + + // 获取列表数据(现在使用服务端搜索,不需要消息端过滤) + const getFilteredList = () => { + return list; + }; + + useEffect(() => { + // 初始化时加载数据 + fetchMessageData(true, 1, ''); + }, []); + + // 渲染消息项 + const renderMessageItem = (item: any) => ( + + navTo(`/user/chat/message/detail?id=${item.id}`,true)}> + + + + + + + + + {item.formUserAlias || item.formUserName} + + {item.createTime} + + + + {item.content} + + + + + + + + ); + + // 渲染消息列表 + const renderMessageList = () => { + const filteredList = getFilteredList(); + + return ( + + { + // 滚动事件处理 + }} + onScrollToUpper={() => { + // 滚动到顶部事件处理 + }} + loadingText={ + <> + 加载中... + + } + loadMoreText={ + filteredList.length === 0 ? ( + + ) : ( + + 没有更多了 + + ) + } + > + {loading && filteredList.length === 0 ? ( + + + 加载中... + + ) : ( + filteredList.map(renderMessageItem) + )} + + + ); + }; + + return ( + + {/* 消息列表 */} + {renderMessageList()} + navTo(`/user/chat/message/add`,true)}/> + + ); +}; + +export default MessageIndex;