2
0

SentWbw.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { Button, List, Select, Space, message } from "antd";
  2. import { useCallback, useEffect, useState } from "react";
  3. import { ReloadOutlined } from "@ant-design/icons";
  4. import { get } from "../../../request";
  5. import type { ISentenceWbwListResponse } from "../../../api/Corpus";
  6. import {
  7. type ISentence,
  8. type IWidgetSentEditInner,
  9. SentEditInner,
  10. } from "../SentEdit";
  11. import { useAppSelector } from "../../../hooks";
  12. import { courseInfo, memberInfo } from "../../../reducers/current-course";
  13. import { courseUser } from "../../../reducers/course-user";
  14. import User, { type IUser } from "../../auth/User";
  15. import { getWbwProgress } from "../WbwSent";
  16. import moment from "moment";
  17. interface IWidget {
  18. book: number;
  19. para: number;
  20. wordStart: number;
  21. wordEnd: number;
  22. channelsId?: string[];
  23. reload?: boolean;
  24. wbwProgress?: boolean;
  25. }
  26. const SentWbwWidget = ({
  27. book,
  28. para,
  29. wordStart,
  30. wordEnd,
  31. channelsId,
  32. wbwProgress = false,
  33. }: IWidget) => {
  34. const [sentData, setSentData] = useState<IWidgetSentEditInner[]>([]);
  35. const [answer, setAnswer] = useState<ISentence>();
  36. const [loading, setLoading] = useState<boolean>(false);
  37. const [order, setOrder] = useState("progress");
  38. const course = useAppSelector(courseInfo);
  39. const courseMember = useAppSelector(memberInfo);
  40. const myCourse = useAppSelector(courseUser);
  41. let isCourse: boolean = false;
  42. if (myCourse && course) {
  43. isCourse = true;
  44. }
  45. const load = useCallback(async () => {
  46. let url = `/v2/wbw-sentence?view=sent-can-read`;
  47. url += `&book=${book}&para=${para}&wordStart=${wordStart}&wordEnd=${wordEnd}`;
  48. if (myCourse && course) {
  49. url += `&course=${course.courseId}`;
  50. if (myCourse.role === "student") {
  51. url += `&channels=${course.channelId}`;
  52. }
  53. } else {
  54. if (channelsId?.length && channelsId?.length > 0) {
  55. url += `&exclude=${channelsId[0]}`;
  56. }
  57. }
  58. setLoading(true);
  59. try {
  60. const json = await get<ISentenceWbwListResponse>(url);
  61. if (!json.ok) {
  62. message.error(json.message);
  63. return;
  64. }
  65. let response = json.data.rows;
  66. if (course && myCourse && myCourse.role !== "student") {
  67. response = response.filter((v) =>
  68. v.translation
  69. ? v.translation[0].channel.id !== course.channelId
  70. : true
  71. );
  72. }
  73. response.forEach((value, index, array) => {
  74. if (value.origin?.[0]?.content) {
  75. const parsed = JSON.parse(value.origin[0].content);
  76. array[index].wbwProgress = getWbwProgress(parsed);
  77. }
  78. });
  79. setSentData(response);
  80. if (myCourse && course) {
  81. const answerData = json.data.rows.find(
  82. (v) => v.origin?.[0].channel.id === course.channelId
  83. );
  84. if (answerData?.origin) {
  85. setAnswer(answerData.origin[0]);
  86. }
  87. }
  88. } finally {
  89. setLoading(false);
  90. }
  91. }, [book, para, wordStart, wordEnd, myCourse, course, channelsId]);
  92. useEffect(() => {
  93. load();
  94. }, [load]);
  95. //没交作业的人
  96. const nonWbwUser: IUser[] = [];
  97. const isCourseAnswer = myCourse && course && myCourse.role !== "student";
  98. if (isCourseAnswer && courseMember) {
  99. const hasWbwUsers = sentData.map((item) =>
  100. item.translation ? item.translation[0].studio : undefined
  101. );
  102. courseMember
  103. .filter(
  104. (value) =>
  105. value.role === "student" &&
  106. (value.status === "joined" ||
  107. value.status === "accepted" ||
  108. value.status === "agreed")
  109. )
  110. .forEach((value) => {
  111. const curr = hasWbwUsers.find((value1) => value1?.id === value.user_id);
  112. if (!curr && value.user) {
  113. nonWbwUser.push(value.user);
  114. }
  115. });
  116. }
  117. console.debug("没交作业", courseMember, sentData, nonWbwUser);
  118. const aaa = [...sentData].sort(
  119. (a: IWidgetSentEditInner, b: IWidgetSentEditInner) => {
  120. switch (order) {
  121. case "progress":
  122. if (a.wbwProgress && b.wbwProgress) {
  123. return b.wbwProgress - a.wbwProgress;
  124. } else {
  125. return 0;
  126. }
  127. break;
  128. case "updated":
  129. if (a.origin && b.origin) {
  130. if (
  131. moment(b.origin[0].updateAt).isBefore(
  132. moment(a.origin[0].updateAt)
  133. )
  134. ) {
  135. return 1;
  136. } else {
  137. return -1;
  138. }
  139. } else {
  140. return 0;
  141. }
  142. break;
  143. }
  144. if (a.wbwProgress && b.wbwProgress) {
  145. return b.wbwProgress - a.wbwProgress;
  146. } else {
  147. return 0;
  148. }
  149. }
  150. );
  151. return (
  152. <>
  153. <List
  154. loading={loading}
  155. header={
  156. <div style={{ display: "flex", justifyContent: "space-between" }}>
  157. <span></span>
  158. <Space>
  159. <Select
  160. disabled
  161. defaultValue={"progress"}
  162. options={[
  163. { value: "progress", label: "完成度" },
  164. { value: "updated", label: "更新时间" },
  165. ]}
  166. onChange={(value: string) => setOrder(value)}
  167. />
  168. <Button
  169. type="link"
  170. shape="round"
  171. icon={<ReloadOutlined />}
  172. onClick={load}
  173. />
  174. </Space>
  175. </div>
  176. }
  177. itemLayout="horizontal"
  178. split={false}
  179. dataSource={aaa}
  180. renderItem={(item, index) => (
  181. <List.Item key={index}>
  182. <SentEditInner
  183. {...item}
  184. readonly={isCourse}
  185. answer={answer}
  186. showWbwProgress={isCourse ?? wbwProgress}
  187. />
  188. </List.Item>
  189. )}
  190. />
  191. <div>
  192. {isCourseAnswer ? (
  193. <Space style={{ flexWrap: "wrap" }}>
  194. {"无作业:"}
  195. {nonWbwUser.length > 0
  196. ? nonWbwUser.map((item, id) => {
  197. return <User key={id} {...item} />;
  198. })
  199. : "无"}
  200. </Space>
  201. ) : undefined}
  202. </div>
  203. </>
  204. );
  205. };
  206. export default SentWbwWidget;