feat(add): 新增多页面新增和编辑表单功能
- 添加编辑和新增收货地址页面,支持表单数据加载和提交 - 新增应用密钥凭证、新增应用操作动态、新增应用成员、新增应用版本页面配置 - 实现文章新增及编辑页面,包含图片上传及多种文章属性配置 - 增加注册会员页面,支持头像上传、手机号获取和邀请人关系处理 - 引入统一表单提交成功和失败处理,支持编辑模式数据回显 - 配置统一eslint和editorconfig规则,增强代码规范和编辑体验 - 新增.gitignore规则,屏蔽无关文件和目录,优化版本管理
This commit is contained in:
179
src/user/chat/message/index.tsx
Normal file
179
src/user/chat/message/index.tsx
Normal file
@@ -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<ShopChatMessage[]>([])
|
||||
const [loading, setLoading] = useState<boolean>(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) => (
|
||||
<View key={item.userId} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
|
||||
<View className="flex items-center" onClick={() => navTo(`/user/chat/message/detail?id=${item.id}`,true)}>
|
||||
<View className="flex-1">
|
||||
<View className="flex items-center justify-between mb-1">
|
||||
<View className={'flex w-full'}>
|
||||
<Badge style={{marginInlineEnd: '10px'}} dot={item.status === 0} top="2" right="4">
|
||||
<Avatar
|
||||
size="40"
|
||||
src={item.formUserAvatar}
|
||||
/>
|
||||
</Badge>
|
||||
<View className="flex flex-col w-full">
|
||||
<View className="flex items-center w-full justify-between">
|
||||
<Text className="font-semibold text-gray-800 mr-2">{item.formUserAlias || item.formUserName}</Text>
|
||||
<Text className="text-xs text-gray-500">
|
||||
{item.createTime}
|
||||
</Text>
|
||||
</View>
|
||||
<Text className="text-gray-500 mt-2 mr-2">
|
||||
{item.content}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
// 渲染消息列表
|
||||
const renderMessageList = () => {
|
||||
const filteredList = getFilteredList();
|
||||
|
||||
return (
|
||||
<View className="p-4" style={{
|
||||
height: '90vh',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden'
|
||||
}}>
|
||||
<InfiniteLoading
|
||||
target="scroll"
|
||||
hasMore={hasMore}
|
||||
onLoadMore={reloadMore}
|
||||
onScroll={() => {
|
||||
// 滚动事件处理
|
||||
}}
|
||||
onScrollToUpper={() => {
|
||||
// 滚动到顶部事件处理
|
||||
}}
|
||||
loadingText={
|
||||
<>
|
||||
加载中...
|
||||
</>
|
||||
}
|
||||
loadMoreText={
|
||||
filteredList.length === 0 ? (
|
||||
<Empty
|
||||
style={{backgroundColor: 'transparent'}}
|
||||
description={loading ? "加载中..." : "暂无消息数据"}
|
||||
/>
|
||||
) : (
|
||||
<View className={'h-12 flex items-center justify-center'}>
|
||||
<Text className="text-gray-500 text-sm">没有更多了</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
>
|
||||
{loading && filteredList.length === 0 ? (
|
||||
<View className="flex items-center justify-center py-8">
|
||||
<Loading/>
|
||||
<Text className="text-gray-500 mt-2 ml-2">加载中...</Text>
|
||||
</View>
|
||||
) : (
|
||||
filteredList.map(renderMessageItem)
|
||||
)}
|
||||
</InfiniteLoading>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="min-h-screen bg-gray-50">
|
||||
{/* 消息列表 */}
|
||||
{renderMessageList()}
|
||||
<FixedButton text={'发送消息'} onClick={() => navTo(`/user/chat/message/add`,true)}/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default MessageIndex;
|
||||
Reference in New Issue
Block a user