Skip to content

Commit

Permalink
Merge pull request #62 from MaggieMii/main
Browse files Browse the repository at this point in the history
添加 发布课评功能
  • Loading branch information
MaggieMii authored Aug 25, 2024
2 parents b2a8b6c + 733b003 commit e5dc0b7
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const CommentComponent: React.FC<CommentProps> = ({ comments, onCommentClick })
};

void fetchAllReplies();
}, [allComments]);
}, []);

const ctimeToString = (ctime: number) => {
const ctimeDate = new Date(ctime);
Expand Down
12 changes: 10 additions & 2 deletions src/common/components/star/star.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { useState } from 'react';

import './star.scss';

export default function Star() {
interface Props {
onStarClick: (index: number) => void;
// ...其他属性...
}

const Star: React.FC<Props> = ({ onStarClick }) => {
const star0 = 'https://s2.loli.net/2023/08/29/NRLD54kzG9nEOHW.png';
const star1 = 'https://s2.loli.net/2023/08/29/rENVFz7xU9n2bd6.png';

Expand All @@ -17,6 +22,7 @@ export default function Star() {
newStars[i] = star1;
}
setStars(newStars);
onStarClick(index); // 安全调用
};

return (
Expand All @@ -34,4 +40,6 @@ export default function Star() {
})}
</View>
);
}
};

export default Star;
234 changes: 169 additions & 65 deletions src/pages/evaluate/evaluate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,108 +4,212 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable react-hooks/rules-of-hooks */
/* eslint-disable import/first */
import {
Button,
Form,
Radio,
RadioGroup,
Text,
Textarea,
View,
} from '@tarojs/components';
import { useState } from 'react';
import { Button, Form, Radio, Text, Textarea, View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useEffect, useState } from 'react';

import './evaluate.scss';

import Label3 from '@/common/components/label3/label3';
import Star from '@/common/components/star/star';
import { post } from '@/common/utils/fetch';

export default function evaluate() {
function generateUniqueID() {
const timestamp = Date.now().toString(36); // 时间戳转换为36进制
const randomString = Math.random().toString(36).substr(2, 5); // 随机数转换为36进制并截取部分字符
// function generateUniqueID() {
// const timestamp = Date.now().toString(36); // 时间戳转换为36进制
// const randomString = Math.random().toString(36).substr(2, 5); // 随机数转换为36进制并截取部分字符

const uniqueID = timestamp + randomString;
return uniqueID;
}
// const uniqueID = timestamp + randomString;
// return uniqueID;
// }

// 示例用法
//const uniqueID = generateUniqueID();

const [testways] = useState([
{ value: '开卷考试', text: '开卷考试', checked: false },
{ value: '闭卷考试', text: '闭卷考试', checked: false },
{ value: '论文考核', text: '论文考核', checked: false },
{ value: '小组汇报', text: '小组汇报', checked: false },
{ value: '无考核', text: '无考核', checked: false },
]);

const [myclass] = useState([{ content: '只能评价自己学过的课程哦' }]);

const [features, setFeatures] = useState([
{ id: generateUniqueID(), content: '老师风趣幽默', checked: false },
{ id: generateUniqueID(), content: '课程干货满满', checked: false },
{ id: generateUniqueID(), content: '老师严谨负责', checked: false },
{ id: generateUniqueID(), content: '课程很有挑战', checked: false },
{ id: generateUniqueID(), content: '课程简单易学', checked: false },
{ id: generateUniqueID(), content: '老师温柔随和', checked: false },
{ id: generateUniqueID(), content: '平时作业少', checked: false },
{ id: generateUniqueID(), content: '期末划重点', checked: false },
{ id: generateUniqueID(), content: '云课堂资料全', checked: false },
]);
// 初始化状态,存储所有选中的 Radio 项的值
const [selectedValues, setSelectedValues] = useState<string[]>([]);

const [textLength, setLength] = useState(0);
// 处理 Radio 变化的函数
const handleRadioChange = (value: string) => {
const currentIndex = selectedValues.indexOf(value);
console.log(currentIndex);
if (currentIndex > -1) {
// 如果值已选中,移除它
const newSelectedValues = selectedValues.filter((v, i) => i !== currentIndex);
setSelectedValues(newSelectedValues);
} else {
// 否则,添加这个值
setSelectedValues([...selectedValues, value]);
}
};

// 测试方式的数据
const testways = [
{ value: 'OpenBookExamination', text: '开卷考试' },
{ value: 'ClosedBookExamination', text: '闭卷考试' },
{ value: 'ThesisExamination', text: '论文考核' },
{ value: 'GroupReporting', text: '小组汇报' },
{ value: 'NoAssessment', text: '无考核' },
];

// const [checkedClass,setCheckedClass] = useState([{ content: '只能评价自己学过的课程哦' }]);

// enum FeatureTag {
// EasyToLearn = '课程简单易学',
// RichInContent = '课程干货满满',
// Challenging = '课程很有挑战',
// RigorousAndResponsible = '老师严谨负责',
// KindAndEasygoing = '老师温柔随和',
// Humorous = '老师风趣幽默',
// LessHomework = '平时作业少',
// KeyPointsForFinal = '期末划重点',
// ComprehensiveOnlineMaterials = '云课堂资料全',
// }

const features = [
{ value: 'EasyToLearn', content: '课程简单易学' },
{ value: 'RichInContent', content: '课程干货满满' },
{ value: 'Challenging', content: '课程很有挑战' },
{ value: 'RigorousAndResponsible', content: '老师严谨负责' },
{ value: 'KindAndEasygoing', content: '老师温柔随和' },
{ value: 'Humorous', content: '老师风趣幽默' },
{ value: 'LessHomework', content: '平时作业少' },
{ value: 'KeyPointsForFinal', content: '期末划重点' },
{ value: 'ComprehensiveOnlineMaterials', content: '云课堂资料全' },
];

const handleChecked = (id) => {
const newFeatures = features.map((e) => {
if (e.id === id) return { ...e, checked: !e.checked };
else return e;
});
setFeatures(newFeatures);
const [selectedFeatureValues, setSelectedFeatureValues] = useState<string[]>([]);

const handleFeaturesChecked = (value: string) => {
const currentIndex = selectedFeatureValues.indexOf(value);
if (currentIndex > -1) {
// 如果 id 已选中,移除它
const newSelectedFeatureValues = selectedFeatureValues.filter(
(v, i) => i !== currentIndex
);
setSelectedFeatureValues(newSelectedFeatureValues);
} else {
// 否则,添加这个 id
setSelectedFeatureValues([...selectedFeatureValues, value]);
}
};

const [textLength, setLength] = useState(0);
const [comment, setComment] = useState('');

const countContent = (e) => {
const { value } = e.detail;
setComment(value); // 更新状态为当前输入框的值
const length = value.length;
setLength(length);
};

// const course_id = 1; //暂时先指定一个courseId来测试使用

// 更新 id 状态为 number 类型
const [courseId, setId] = useState<number | null>(null);
const [courseName, setName] = useState<string | null>('只能评价自己学过的课程哦');

useEffect(() => {
const getParams = () => {
const instance = Taro.getCurrentInstance();
// 使用可选链操作符安全访问 router 和 params
const params = instance?.router?.params || {};

// 确保 id 是 number 类型
setId(params.id ? Number(params.id) : null);
// 解码 name 参数
setName(params.name ? decodeURIComponent(params.name) : '只能评价自己学过的课程哦');

console.log(params.id);
};

getParams();
}, []); // 这个 effect 仅在组件挂载时运行一次

const postEvaluation = () => {
const evaluationobj = {
star_rating: selectedStarIndex,
content: comment,
course_id: courseId,
assessments: selectedValues,
features: selectedFeatureValues,
id: 0,
status: 'Public',
};
console.log(evaluationobj);
post(`/evaluations/save`, evaluationobj)
.then((res) => {
if (res.code === 0) {
// 打印成功信息,但最好使用其他日志记录方式,而不是 console.log
// 例如:this.setState({ message: '发布课评成功' });
// 或者使用 Taro 的日志记录方式:Taro.showToast({ title: '发布课评成功', icon: 'success' });
// console.log('发布课评成功');
// 使用 redirectTo 跳转
void Taro.redirectTo({
url: '/pages/main/index', // 页面路径
});
} else {
// 处理其他响应代码,可能需要给用户一些反馈
// 例如:Taro.showToast({ title: '发布课评失败', icon: 'none' });
}
})
.catch((error) => {
// 处理可能出现的错误情况
// 例如:Taro.showToast({ title: '发布失败,请稍后重试', icon: 'none' });
console.error('发布课评请求失败:', error);
});
};

//星级部分的代码
const [selectedStarIndex, setSelectedStarIndex] = useState(-1);

const onStarClick = (index) => {
console.log('选中的星级索引:', index);
setSelectedStarIndex(index + 1);
// 执行其他需要的逻辑
};

return (
<Form className="view">
<View className="p">
<Text> 选择课程 : </Text>
{myclass.map((each) => {
return <Label3 {...each} />;
})}
<Label3 content={courseName}></Label3>
</View>
<View className="p">
<Text>评价星级 :</Text>
<Star></Star>
<Star onStarClick={onStarClick} />
</View>
<View className="p">
<Text>考核方式 :</Text>
<View className="ways">
<RadioGroup>
{testways.map((item) => {
return (
<Radio
className="myradio"
checked={item.checked}
value={item.value}
color="transparent"
>
{item.text}
</Radio>
);
})}
</RadioGroup>
{testways.map((item) => (
<Radio
key={item.value}
className="myradio"
checked={selectedValues.includes(item.value)} // 判断是否包含该项的 value
value={item.value}
color="transparent"
onClick={() => handleRadioChange(item.value)}
>
{item.text}
</Radio>
))}
</View>
</View>
<View className="p">
<Text>评价星级 :</Text>
<Text>课程特点</Text>
<View className="fea">
{features.map((item) => {
return <Label3 handleChecked={handleChecked} {...item} />;
return (
<Label3
key={item.value}
id={item.value} // 确保 Label3 组件可以访问到 id
content={item.content}
checked={selectedFeatureValues.includes(item.value)} // 判断是否包含该项的 id
handleChecked={() => handleFeaturesChecked(item.value)} // 传递 handleChecked 函数
/>
);
})}
</View>
</View>
Expand All @@ -117,7 +221,7 @@ export default function evaluate() {
className="myComment"
></Textarea>
<Text className="zsxz">字数限制{textLength}/450</Text>
<Button>发布</Button>
<Button onClick={postEvaluation}>发布</Button>
</Form>
);
}
16 changes: 15 additions & 1 deletion src/pages/myclass/myclass.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */

import { Picker, Text, View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useEffect, useState } from 'react';

import './myclass.scss';
Expand Down Expand Up @@ -59,6 +60,15 @@ export default function Myclass() {
void fetchClasses();
}, [year, sem]);

const handleClassClick = (id: number, name: string) => {
// 拼接查询字符串参数
const query = `?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
// 使用 navigateTo 跳转到 evaluate 页面,并传递参数
void Taro.navigateTo({
url: `/pages/evaluate/evaluate${query}`,
});
};

return (
<View>
<View className="select">
Expand All @@ -78,7 +88,11 @@ export default function Myclass() {
</View>
<View className="classes">
{myclasses.map((each, index) => (
<View key={index} className="eachClass">
<View
key={index}
className="eachClass"
onClick={() => handleClassClick(each.id, each.name)}
>
<Text className="classname">{each.name}</Text>
<Text className="classteacher">{each.teacher}</Text>
<Text className="classstatus">{each.evaluated ? '已评课' : '未评课'}</Text>
Expand Down

0 comments on commit e5dc0b7

Please sign in to comment.