CourseMember.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import { useIntl } from "react-intl";
  2. import { useRef, useState } from "react";
  3. import { ActionType, ProList } from "@ant-design/pro-components";
  4. import { Space, Tag, Button, Layout, Popconfirm } from "antd";
  5. import CourseAddMember from "./AddMember";
  6. import { delete_, get } from "../../request";
  7. import {
  8. ICourseMemberDeleteResponse,
  9. ICourseMemberListResponse,
  10. TCourseMemberStatus,
  11. } from "../api/Course";
  12. const { Content } = Layout;
  13. interface IRoleTag {
  14. title: string;
  15. color: string;
  16. }
  17. export interface ICourseMember {
  18. sn?: number;
  19. id?: string;
  20. userId: string;
  21. name?: string;
  22. tag: IRoleTag[];
  23. image: string;
  24. role?: string;
  25. startExp?: number;
  26. endExp?: number;
  27. currentExp?: number;
  28. expByDay?: number;
  29. status?: TCourseMemberStatus;
  30. }
  31. interface IWidget {
  32. courseId?: string;
  33. }
  34. const Widget = ({ courseId }: IWidget) => {
  35. const intl = useIntl(); //i18n
  36. const [canDelete, setCanDelete] = useState(false);
  37. const [memberCount, setMemberCount] = useState<number>();
  38. const ref = useRef<ActionType>();
  39. return (
  40. <Content>
  41. <ProList<ICourseMember>
  42. rowKey="id"
  43. actionRef={ref}
  44. headerTitle={
  45. intl.formatMessage({ id: "group.member" }) +
  46. "-" +
  47. memberCount?.toString()
  48. }
  49. toolBarRender={() => {
  50. return [
  51. canDelete ? (
  52. <CourseAddMember
  53. courseId={courseId}
  54. onCreated={() => {
  55. ref.current?.reload();
  56. }}
  57. />
  58. ) : (
  59. <></>
  60. ),
  61. ];
  62. }}
  63. showActions="hover"
  64. request={async (params = {}, sorter, filter) => {
  65. // TODO
  66. console.log(params, sorter, filter);
  67. let url = `/v2/course-member?view=course&id=${courseId}`;
  68. const offset =
  69. ((params.current ? params.current : 1) - 1) *
  70. (params.pageSize ? params.pageSize : 20);
  71. url += `&limit=${params.pageSize}&offset=${offset}`;
  72. if (typeof params.keyword !== "undefined") {
  73. url += "&search=" + (params.keyword ? params.keyword : "");
  74. }
  75. const res = await get<ICourseMemberListResponse>(url);
  76. if (res.ok) {
  77. console.log(res.data);
  78. setMemberCount(res.data.count);
  79. switch (res.data.role) {
  80. case "owner":
  81. setCanDelete(true);
  82. break;
  83. case "manager":
  84. setCanDelete(true);
  85. break;
  86. }
  87. const items: ICourseMember[] = res.data.rows.map((item, id) => {
  88. let member: ICourseMember = {
  89. id: item.id ? item.id : "",
  90. userId: item.user_id,
  91. name: item.user?.nickName,
  92. tag: [],
  93. image: "",
  94. };
  95. member.tag.push({
  96. title: intl.formatMessage({
  97. id: "forms.fields." + item.role + ".label",
  98. }),
  99. color: "default",
  100. });
  101. return member;
  102. });
  103. console.log(items);
  104. return {
  105. total: res.data.count,
  106. succcess: true,
  107. data: items,
  108. };
  109. } else {
  110. console.error(res.message);
  111. return {
  112. total: 0,
  113. succcess: false,
  114. data: [],
  115. };
  116. }
  117. }}
  118. pagination={{
  119. showQuickJumper: true,
  120. showSizeChanger: true,
  121. }}
  122. metas={{
  123. title: {
  124. dataIndex: "name",
  125. },
  126. avatar: {
  127. dataIndex: "image",
  128. editable: false,
  129. },
  130. subTitle: {
  131. render: (text, row, index, action) => {
  132. const showtag = row.tag.map((item, id) => {
  133. return (
  134. <Tag color={item.color} key={id}>
  135. {item.title}
  136. </Tag>
  137. );
  138. });
  139. return <Space size={0}>{showtag}</Space>;
  140. },
  141. },
  142. actions: {
  143. render: (text, row, index, action) => [
  144. canDelete ? (
  145. <Popconfirm
  146. placement="bottomLeft"
  147. title={intl.formatMessage({
  148. id: "forms.message.member.delete",
  149. })}
  150. onConfirm={(
  151. e?: React.MouseEvent<HTMLElement, MouseEvent>
  152. ) => {
  153. console.log("delete", row.id);
  154. delete_<ICourseMemberDeleteResponse>(
  155. "/v2/course-member/" + row.id
  156. ).then((json) => {
  157. if (json.ok) {
  158. console.log("delete ok");
  159. ref.current?.reload();
  160. }
  161. });
  162. }}
  163. okText={intl.formatMessage({ id: "buttons.ok" })}
  164. cancelText={intl.formatMessage({ id: "buttons.cancel" })}
  165. >
  166. <Button size="small" type="link" danger key="link">
  167. {intl.formatMessage({ id: "buttons.remove" })}
  168. </Button>
  169. </Popconfirm>
  170. ) : (
  171. <></>
  172. ),
  173. ],
  174. },
  175. }}
  176. />
  177. </Content>
  178. );
  179. };
  180. export default Widget;