Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加 发布课评功能 #62

Merged
merged 4 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading