TransferList.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import { useRef, useState } from "react";
  2. import { Button, Space, Tag, Typography, message, notification } from "antd";
  3. import { get, put } from "../../request";
  4. import { type ActionType, ProList } from "@ant-design/pro-components";
  5. import { renderBadge } from "../channel/ChannelTable";
  6. import User, { type IUser } from "../auth/User";
  7. import type { IChannel } from "../channel/Channel";
  8. import type { IStudio } from "../auth/Studio";
  9. import TimeShow from "../general/TimeShow";
  10. import type {
  11. ITransferRequest,
  12. ITransferResponse,
  13. ITransferResponseList,
  14. ITransferStatus,
  15. } from "../../api/Transfer";
  16. import { useIntl } from "react-intl";
  17. import type { BaseType } from "antd/lib/typography/Base";
  18. import type { TResType } from "../discussion/DiscussionListCard";
  19. const { Text } = Typography;
  20. interface ITransfer {
  21. id: string;
  22. origin_owner: IStudio;
  23. res_type: TResType;
  24. res_id: string;
  25. channel?: IChannel;
  26. transferor: IUser;
  27. new_owner: IStudio;
  28. status: ITransferStatus;
  29. editor?: IUser | null;
  30. created_at: string;
  31. updated_at: string;
  32. }
  33. interface IWidget {
  34. studioName?: string;
  35. }
  36. const TransferListWidget = ({ studioName }: IWidget) => {
  37. const ref = useRef<ActionType | null>(null);
  38. const [activeKey, setActiveKey] = useState<React.Key | undefined>("in");
  39. const [activeNumber, setActiveNumber] = useState<number>(0);
  40. const [closeNumber, setCloseNumber] = useState<number>(0);
  41. const intl = useIntl();
  42. const openNotification = (description: string) => {
  43. const args = {
  44. message: intl.formatMessage({
  45. id: `columns.studio.transfer.title`,
  46. }),
  47. description: description,
  48. duration: 0,
  49. };
  50. notification.open(args);
  51. };
  52. const setStatus = (status: ITransferStatus, id: string) => {
  53. const data: ITransferRequest = {
  54. status: status,
  55. };
  56. put<ITransferRequest, ITransferResponse>(`/v2/transfer/${id}`, data)
  57. .then((json) => {
  58. if (json.ok) {
  59. ref.current?.reload();
  60. openNotification(
  61. `已经` + intl.formatMessage({ id: `forms.status.${status}.label` })
  62. );
  63. } else {
  64. message.error(json.message);
  65. }
  66. })
  67. .catch((e) => {
  68. console.error(e);
  69. });
  70. };
  71. return (
  72. <>
  73. <ProList<ITransfer>
  74. rowKey="id"
  75. actionRef={ref}
  76. metas={{
  77. avatar: {
  78. render(_dom, entity, _index, _action, _schema) {
  79. return (
  80. <>
  81. <User {...entity.transferor} showName={false} />
  82. </>
  83. );
  84. },
  85. },
  86. title: {
  87. render(_dom, entity, _index, _action, _schema) {
  88. return (
  89. <>
  90. {entity.origin_owner.studioName}/{entity.channel?.name}
  91. </>
  92. );
  93. },
  94. },
  95. subTitle: {
  96. render(_dom, entity, _index, _action, _schema) {
  97. return <Tag>{entity.res_type}</Tag>;
  98. },
  99. },
  100. description: {
  101. search: false,
  102. render(_dom, entity, _index, _action, _schema) {
  103. return (
  104. <Space>
  105. <User
  106. key={"user"}
  107. {...entity.transferor}
  108. showAvatar={false}
  109. />
  110. <span key="text">{"transfer at"}</span>
  111. <TimeShow key={"time"} createdAt={entity.created_at} />
  112. </Space>
  113. );
  114. },
  115. },
  116. content: {
  117. render(_dom, entity, _index, _action, _schema) {
  118. let style: BaseType | undefined;
  119. switch (entity.status) {
  120. case "accept":
  121. style = "success";
  122. break;
  123. case "refuse":
  124. style = "warning";
  125. break;
  126. case "cancel":
  127. style = "danger";
  128. break;
  129. default:
  130. style = undefined;
  131. break;
  132. }
  133. return (
  134. <Text type={style}>
  135. {intl.formatMessage({
  136. id: `forms.status.${entity.status}.label`,
  137. })}
  138. </Text>
  139. );
  140. },
  141. },
  142. actions: {
  143. render: (_text, row, _index, _action) => [
  144. activeKey === "in" ? (
  145. <>
  146. <Button
  147. type="text"
  148. disabled={row.status !== "transferred"}
  149. onClick={() => setStatus("accept", row.id)}
  150. >
  151. {intl.formatMessage({
  152. id: `buttons.accept`,
  153. })}
  154. </Button>
  155. <Button
  156. disabled={row.status !== "transferred"}
  157. danger
  158. type="text"
  159. onClick={() => setStatus("refuse", row.id)}
  160. >
  161. {intl.formatMessage({
  162. id: `buttons.refuse`,
  163. })}
  164. </Button>
  165. </>
  166. ) : (
  167. <>
  168. <Button
  169. type="text"
  170. disabled={row.status !== "transferred"}
  171. onClick={() => setStatus("cancel", row.id)}
  172. >
  173. {intl.formatMessage({
  174. id: `buttons.cancel`,
  175. })}
  176. </Button>
  177. </>
  178. ),
  179. ],
  180. },
  181. }}
  182. request={async (params = {}, _sorter, _filter) => {
  183. let url = `/v2/transfer?view=studio&name=${studioName}&view2=${activeKey}`;
  184. const offset =
  185. ((params.current ? params.current : 1) - 1) *
  186. (params.pageSize ? params.pageSize : 20);
  187. url += `&limit=${params.pageSize}&offset=${offset}`;
  188. url += params.keyword ? "&search=" + params.keyword : "";
  189. console.log("url", url);
  190. const res = await get<ITransferResponseList>(url);
  191. const items: ITransfer[] = res.data.rows.map((item, _id) => {
  192. return item;
  193. });
  194. setActiveNumber(res.data.in);
  195. setCloseNumber(res.data.out);
  196. return {
  197. total: res.data.count,
  198. succcess: true,
  199. data: items,
  200. };
  201. }}
  202. bordered
  203. pagination={{
  204. showQuickJumper: true,
  205. showSizeChanger: true,
  206. pageSize: 10,
  207. }}
  208. search={false}
  209. options={{
  210. search: false,
  211. }}
  212. toolbar={{
  213. menu: {
  214. activeKey,
  215. items: [
  216. {
  217. key: "in",
  218. label: (
  219. <span>
  220. 转入
  221. {renderBadge(activeNumber, activeKey === "in")}
  222. </span>
  223. ),
  224. },
  225. {
  226. key: "out",
  227. label: (
  228. <span>
  229. 转出
  230. {renderBadge(closeNumber, activeKey === "out")}
  231. </span>
  232. ),
  233. },
  234. ],
  235. onChange(key) {
  236. setActiveKey(key);
  237. ref.current?.reload();
  238. },
  239. },
  240. }}
  241. />
  242. </>
  243. );
  244. };
  245. export default TransferListWidget;