Skip to content

Commit

Permalink
Merge branch 'feat-cache' of github.com:eleliauk/muxiK-StackFrontend2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
eleliauk committed Dec 18, 2024
2 parents add1e65 + 94b3de7 commit 04e79fc
Show file tree
Hide file tree
Showing 43 changed files with 840 additions and 495 deletions.
4 changes: 2 additions & 2 deletions .lintstagedrc.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const path = require('path');

const buildEslintCommand = (filenames) =>
`eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 90 --fix ${filenames
`eslint ${filenames
.map((f) => path.relative(process.cwd(), f))
.join(' --file ')}`;
.join(' ')} --ext ts,tsx --report-unused-disable-directives --max-warnings 90 --fix`;

module.exports = {
'*.{js,jsx,ts,tsx}': [buildEslintCommand],
Expand Down
20 changes: 20 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
/* eslint-disable */

import Taro from '@tarojs/taro';
import { Component, PropsWithChildren } from 'react';

import '@/common/styles/globals.scss';

import { checkToken } from '@/common/utils';

const interceptor: Taro.interceptor = function (chain: Taro.Chain) {
const requestParams = chain.requestParams;

return chain.proceed(requestParams).then((res) => {
console.log(Taro.getStorageSync('shortToken'));

if (res.statusCode === 401 && Taro.getStorageSync('visitor') !== false) {
void Taro.reLaunch({ url: '/pages/login/index' });
Taro.showToast({
title: '登录过期,请重新登录',
icon: 'none',
});
}
return res;
}) as Taro.Chain;
};
Taro.addInterceptor(interceptor);
class App extends Component<PropsWithChildren> {
//TODO 写成加interceptor 但是我还没写明白 别急
componentDidMount() {
Expand Down
2 changes: 0 additions & 2 deletions src/common/api/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export async function get(url: string) {
if (response.data.code !== 0) {
console.log('code不为0');
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.log(response.data.data);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return response.data;
} catch (error) {
Expand Down
2 changes: 0 additions & 2 deletions src/common/api/getUserCourses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export async function getUserCourses(year: string, term: string) {
if (response.data.code !== 0) {
console.log('code不为0');
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.log(response.data.data);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access
return response.data.data;
} catch (error) {
Expand Down
6 changes: 5 additions & 1 deletion src/common/api/handleLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ const handleLogin = async (data: Record<string, unknown> = {}) => {
};

try {
void Taro.showLoading({
title: '登录中...',
mask: true,
});
const response = await Taro.request({
method: 'POST',
url: `${preUrl}/users/login_ccnu`,
header,
data: JSON.stringify(data),
});

Taro.hideLoading();
const headers: LoginResponseHeaders = response.header || {};
const shortToken = headers['X-Jwt-Token'];
const longToken = headers['X-Refresh-Token'];
Expand Down
12 changes: 5 additions & 7 deletions src/common/components/AnswerToStudent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ interface Question {
const AnswerToStudent: React.FC<Question> = (props) => {
const { content, preview_answers } = props;
return (
<View className="flex min-h-[2vh] w-[80vw] items-center justify-start rounded-lg bg-white p-3 hover:bg-gray-50">
<Image src={Ask as string} className="h-5 w-5 flex-shrink-0" />
<View className="mx-3 line-clamp-2 flex-1 text-base font-medium text-gray-800">
{content}
</View>
<View className="flex-shrink-0 text-sm font-medium text-gray-500">
{preview_answers.length} 个回答
<View className="m-auto flex h-[4vh] w-[80vw] items-center justify-center gap-2">
<Image src={Ask as string} className="h-6 w-6" />
<View className="text-base font-medium text-gray-800">{content}</View>
<View className="ml-auto text-sm text-gray-500">
{preview_answers?.length ?? 0} 个回答
</View>
</View>
);
Expand Down
95 changes: 67 additions & 28 deletions src/common/components/Comment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,26 @@ import './style.scss';
import { useCourseStore } from '@/pages/main/store/store';

import IconFont from '@/common/components/iconfont';
import { formatIsoDate, post } from '@/common/utils';
import { CourseDetailsType, PublisherDetailsType } from '@/pages/main/store/types';
import { formatIsoDate } from '@/common/utils';
import { features as featureMap } from '@/pages/evaluate/const';

import {
COMMENT_ACTIONS,
CourseDetailsType,
PublisherDetailsType,
} from '@/pages/main/store/types';
import Label3 from '../label3/label3';
import ShowStar from '../showStar/showStar';

interface CommentProps extends CommentInfo {
type?: string;
isHot?: boolean;
showTag?: boolean;
showAll?: boolean;
onClick?: (comment: CommentInfo) => void;
onCommentClick?: (comment: CommentInfo) => void;
onLikeClick?: (comment: CommentProps) => void;
classNames?: string;
}

const CommentHeader: React.FC<CommentProps> = memo((props) => {
Expand Down Expand Up @@ -92,44 +103,78 @@ const CommentHeader: React.FC<CommentProps> = memo((props) => {
);
});
const Comment: React.FC<CommentProps> = memo((props) => {
const { showAll, type, content, id, onClick } = props;
const getComment = useCourseStore((state) => state.getComment);
const {
showAll,
type,
content,
id,
onClick,
stance,
onCommentClick,
onLikeClick,
features,
} = props;
const [shouldSupport, setShouldSupport] = useState(stance === 1);
const { getComment, enrose } = useCourseStore((state) => ({
getComment: state.getComment,
enrose: state.enrose,
}));
useEffect(() => {
setShouldSupport(stance === 1);
}, [stance]);
const father_record = getComment(id ?? 0);
const handleClick = useCallback(() => {
onClick && onClick(props);
}, [onClick]);

const handlEndorse = (a: number) => {
void post(`/evaluations/${id}/endorse`, { stance: a }).then((res) => {
console.log(res);
});
const handlEndorse = async () => {
setShouldSupport(!shouldSupport);
const res = await enrose(
id ?? 0,
shouldSupport ? COMMENT_ACTIONS.DISLIKE : COMMENT_ACTIONS.LIKE
);
onLikeClick && onLikeClick(res);
};

return (
<View className="bigcomment" onClick={handleClick}>
<View
className={`bigcomment ${props.classNames}`}
onClick={(e) => {
e.stopPropagation();
handleClick();
}}
>
<View className="commentplus">
<CommentHeader {...props}></CommentHeader>
<View className="mt-3 flex w-full flex-wrap">
{props.showTag &&
features?.map((item, index) => {
const feature = featureMap.find((feat) => feat.value === item);
return feature && <Label3 key={index} content={feature.content}></Label3>;
})}
</View>
<View className={`content ${!showAll ? 'text-overflow' : 'text-showAll'}`}>
{content}
{/* {!showAll && <Text>...</Text>} */}
</View>

{type === 'inner' && (
<View className="likes">
<View className="icon" onClick={() => handlEndorse(1)}>
<View className="likes" onClick={(e) => e.stopPropagation()}>
<View
className={`icon ${shouldSupport && 'bg-orange-200'}`}
onClick={() => void handlEndorse()}
>
<IconFont name="like" />
{/* <Navigator className="iconfont">&#xe786;</Navigator> */}
</View>
<Text className="text1">
{father_record?.total_support_count ?? props.total_support_count}
</Text>
<View className="icon">
<Text className="text1">{props.total_support_count}</Text>
<View
className="icon"
onClick={() => onCommentClick && father_record && onCommentClick(props)}
>
<IconFont name="comment" />
{/* <Navigator className="iconfont">&#xe769;</Navigator> */}
</View>
<Text className="text1">
{father_record?.total_comment_count ?? props.total_comment_count}
</Text>
<Text className="text1">{props.total_comment_count}</Text>
</View>
)}
</View>
Expand All @@ -138,21 +183,15 @@ const Comment: React.FC<CommentProps> = memo((props) => {
<View className="icon">
<Navigator className="iconfont">&#xe786;</Navigator>
</View>
<Text className="text1">
{father_record?.total_support_count ?? props.total_support_count}
</Text>
<Text className="text1">{props.total_support_count}</Text>
<View className="icon">
<Navigator className="iconfont">&#xe769;</Navigator>
</View>
<Text className="text1">
{father_record?.total_comment_count ?? props.total_comment_count}
</Text>
<Text className="text1">{props.total_comment_count}</Text>
<View className="icon">
<Navigator className="iconfont">&#xe785;</Navigator>
</View>
<Text className="text1">
{father_record?.total_oppose_count ?? props.total_oppose_count}
</Text>
<Text className="text1">{props.total_oppose_count}</Text>
</View>
)}
</View>
Expand Down
9 changes: 1 addition & 8 deletions src/common/components/CommentComponent/CommentComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ interface CommentProps {
}

const CommentComponent: React.FC<CommentProps> = ({ comments, onCommentClick }) => {
// console.log(comments);
const [allComments, setAllComments] = useState<CommentType[]>(comments);
const dispatch = useCourseStore(({ getPublishers }) => ({ getPublishers }));
useEffect(() => {
Expand Down Expand Up @@ -74,12 +73,6 @@ const CommentComponent: React.FC<CommentProps> = ({ comments, onCommentClick })
void fetchAllReplies();
}, []);

// const ctimeToString = (ctime: number) => {
// return (
// <Text className="time">formatIsoDate(new Date(ctime as number).toISOString())</Text>
// );
// };

// 辅助函数:获取回复者的昵称
const getReplyToNickname = (replyToUid: number): string => {
// 遍历所有评论的回复
Expand All @@ -99,8 +92,8 @@ const CommentComponent: React.FC<CommentProps> = ({ comments, onCommentClick })
key={comment.id}
className="acomment"
onClick={(e) => {
onCommentClick(comment);
e.stopPropagation();
onCommentClick(comment);
}}
>
<View className="comment-header">
Expand Down
1 change: 1 addition & 0 deletions src/common/components/PublishHeader/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
.publish-header {
display: flex;
align-items: center;
flex: 1;
}
11 changes: 9 additions & 2 deletions src/common/components/SearchInput/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable no-console */

/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import { Image, Input, View } from '@tarojs/components';
Expand All @@ -14,6 +14,8 @@ type SearchInputProps = {
searchPlaceholder: string;
searchPlaceholderStyle: string;
searchIconSrc: string;
autoFocus?: boolean;
disabled?: boolean;
};

const SearchInput: React.FC<SearchInputProps> = ({
Expand All @@ -22,6 +24,8 @@ const SearchInput: React.FC<SearchInputProps> = ({
searchPlaceholder,
searchPlaceholderStyle,
searchIconSrc,
autoFocus,
disabled,
}) => {
// const [isSearchActive, setIsSearchActive] = useState(true);
const [searchText, setSearchText] = useState(''); // 添加状态来存储搜索文本
Expand All @@ -30,7 +34,6 @@ const SearchInput: React.FC<SearchInputProps> = ({
const handleImageClick = (e: any) => {
// 阻止事件冒泡
e.stopPropagation();
console.log(2);
onSearch(searchText); // 发送搜索请求
};

Expand Down Expand Up @@ -61,6 +64,10 @@ const SearchInput: React.FC<SearchInputProps> = ({
placeholder={searchPlaceholder}
placeholderStyle={searchPlaceholderStyle}
ref={inputRef}
onConfirm={handleImageClick} // 绑定回车事件
autoFocus={autoFocus}
disabled={disabled}
confirmType="search"
/>
<Image
style={{ width: '34.09rpx', height: '34.09rpx' }}
Expand Down
54 changes: 40 additions & 14 deletions src/common/components/VirtualList.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
import { ScrollView } from '@tarojs/components';
import type { VirtualListProps as TaroVirtualListProps } from '@tarojs/components-advanced/dist/components/virtual-list';
import TaroVirtualList from '@tarojs/components-advanced/dist/components/virtual-list';
import { memo } from 'react';
import { memo, useCallback, useRef } from 'react';

interface VirtualListProps extends TaroVirtualListProps {}
interface VirtualListProps extends TaroVirtualListProps {
item: React.FC<{ data: any; index: number }>;
itemSize: number;
}

const VirtualList: React.FC<VirtualListProps> = memo(
({ height, width, item, itemData, itemCount, itemSize, onScroll }) => (
<TaroVirtualList
height={height}
width={width}
item={item}
itemData={itemData}
itemCount={itemCount}
itemSize={itemSize}
onScroll={onScroll}
/>
)
({ height, width, item: Item, itemData, itemSize, onScroll }) => {
const scrollTop = useRef<number>(0);
const throttle = useCallback((fn, delay) => {
let timer: NodeJS.Timeout | null = null;
return (...args) => {
if (timer) return;
timer = setTimeout(() => {
fn(...args);
timer = null;
}, delay);
};
}, []);
const handleScroll = throttle((event) => {
console.log('fetching');
onScroll && onScroll(event);
}, 1000);
return (
<ScrollView
scrollY
lowerThreshold={100}
style={{ height: height, width: width }}
onScrollToLower={handleScroll}
onScroll={(event) => {
scrollTop.current = event.detail.scrollTop;
}}
scrollTop={scrollTop.current}
>
{itemData.length > 0 &&
itemData.map((_, index) => (
<Item key={index} data={itemData} index={index}></Item>
))}
</ScrollView>
);
}
);

export default VirtualList;
Loading

0 comments on commit 04e79fc

Please sign in to comment.