Преглед на файлове

:sparkles: 新建channel

visuddhinanda преди 3 години
родител
ревизия
168a4b8dc6
променени са 2 файла, в които са добавени 255 реда и са изтрити 13 реда
  1. 59 0
      dashboard/src/components/studio/channel/ChannelCreate.tsx
  2. 196 13
      dashboard/src/pages/studio/channel/index.tsx

+ 59 - 0
dashboard/src/components/studio/channel/ChannelCreate.tsx

@@ -0,0 +1,59 @@
+import { ProForm, ProFormText, ProFormSelect } from "@ant-design/pro-components";
+import { useIntl } from "react-intl";
+import { message } from "antd";
+
+interface IFormData {
+	name: string;
+	type: string;
+}
+
+type IWidgetChannelCreate = {
+	studio: string | undefined;
+};
+const Widget = (param: IWidgetChannelCreate) => {
+	const intl = useIntl();
+
+	return (
+		<ProForm<IFormData>
+			onFinish={async (values: IFormData) => {
+				// TODO
+				console.log(values);
+				message.success(intl.formatMessage({ id: "flashes.success" }));
+			}}
+		>
+			<ProForm.Group>
+				<ProFormText
+					width="md"
+					name="name"
+					required
+					label={intl.formatMessage({ id: "channel.name" })}
+					rules={[
+						{
+							required: true,
+							message: intl.formatMessage({ id: "channel.create.message.noname" }),
+						},
+					]}
+				/>
+			</ProForm.Group>
+			<ProForm.Group>
+				<ProFormSelect
+					options={[
+						{
+							value: "translation",
+							label: intl.formatMessage({ id: "channel.type.translation.title" }),
+						},
+						{
+							value: "nissaya",
+							label: intl.formatMessage({ id: "channel.type.nissaya.title" }),
+						},
+					]}
+					width="md"
+					name="type"
+					label={intl.formatMessage({ id: "channel.type" })}
+				/>
+			</ProForm.Group>
+		</ProForm>
+	);
+};
+
+export default Widget;

+ 196 - 13
dashboard/src/pages/studio/channel/index.tsx

@@ -1,30 +1,213 @@
-import { useParams, Link } from "react-router-dom";
+import { useParams } from "react-router-dom";
+import { ProTable } from "@ant-design/pro-components";
 import { useIntl } from "react-intl";
-import { Space, Layout } from "antd";
+import { Link } from "react-router-dom";
+import { Layout, Space, Table } from "antd";
+import { PlusOutlined } from "@ant-design/icons";
+import type { MenuProps } from "antd";
+import { Button, Dropdown, Menu, Popover } from "antd";
+import { SearchOutlined } from "@ant-design/icons";
+
 import HeadBar from "../../../components/studio/HeadBar";
 import LeftSider from "../../../components/studio/LeftSider";
 import Footer from "../../../components/studio/Footer";
+import ChannelCreate from "../../../components/studio/channel/ChannelCreate";
 
 const { Content } = Layout;
 
+const onMenuClick: MenuProps["onClick"] = (e) => {
+	console.log("click", e);
+};
+
+const menu = (
+	<Menu
+		onClick={onMenuClick}
+		items={[
+			{
+				key: "1",
+				label: "在藏经阁中打开",
+				icon: <SearchOutlined />,
+			},
+			{
+				key: "2",
+				label: "分享",
+				icon: <SearchOutlined />,
+			},
+			{
+				key: "3",
+				label: "删除",
+				icon: <SearchOutlined />,
+			},
+		]}
+	/>
+);
+
+const EType = ["translation", "nissaya", "commentray", "original", "general"];
+
+interface IItem {
+	id: number;
+	title: string;
+	subtitle: string;
+	type: string;
+	publicity: number;
+	createdAt: number;
+}
+
 const Widget = () => {
-	const intl = useIntl(); //i18n
-	const { studioname } = useParams(); //url 参数
-	const linkEdit = `/studio/${studioname}/channel/edit/12345`;
+	const intl = useIntl();
+	const { studioname } = useParams();
+	const channelCreate = <ChannelCreate studio={studioname} />;
 	return (
 		<Layout>
 			<HeadBar />
 			<Layout>
 				<LeftSider selectedKeys="channel" />
 				<Content>
-					<h2>
-						studio/{studioname}/{intl.formatMessage({ id: "columns.studio.channel.title" })}/版本列表
-					</h2>
-					<div>
-						<Space>
-							<Link to={linkEdit}> channel1 edit </Link>
-						</Space>
-					</div>
+					<Layout>{studioname}</Layout>
+					<ProTable<IItem>
+						columns={[
+							{
+								title: intl.formatMessage({ id: "dict.fields.sn.label" }),
+								dataIndex: "id",
+								key: "id",
+								width: 50,
+								search: false,
+							},
+							{
+								title: intl.formatMessage({ id: "forms.fields.title.label" }),
+								dataIndex: "title",
+								key: "title",
+								tip: "过长会自动收缩",
+								ellipsis: true,
+								render: (text, row, index, action) => {
+									return (
+										<div>
+											<div>
+												<Link to="edit/12345">{row.title}</Link>
+											</div>
+											<div>{row.subtitle}</div>
+										</div>
+									);
+								},
+							},
+							{
+								title: intl.formatMessage({ id: "forms.fields.type.label" }),
+								dataIndex: "type",
+								key: "type",
+								width: 100,
+								search: false,
+								filters: true,
+								onFilter: true,
+								valueEnum: {
+									all: { text: "全部", status: "Default" },
+									translation: { text: "译文", status: "Success" },
+									nissaya: { text: "逐词解析", status: "Processing" },
+									commentray: { text: "注疏", status: "Default" },
+									original: { text: "原文", status: "Default" },
+									general: { text: "通用", status: "Default" },
+								},
+							},
+							{
+								title: intl.formatMessage({ id: "forms.fields.publicity.label" }),
+								dataIndex: "publicity",
+								key: "publicity",
+								width: 100,
+								search: false,
+								filters: true,
+								onFilter: true,
+								valueEnum: {
+									all: { text: "全部", status: "Default" },
+									0: { text: "禁用", status: "Success" },
+									10: { text: "私有", status: "Processing" },
+									20: { text: "链接阅读", status: "Default" },
+									30: { text: "公开阅读", status: "Default" },
+									40: { text: "公开可编辑", status: "Default" },
+								},
+							},
+							{
+								title: intl.formatMessage({ id: "forms.fields.created-at.label" }),
+								key: "created-at",
+								width: 100,
+								search: false,
+								dataIndex: "createdAt",
+								valueType: "date",
+								sorter: (a, b) => a.createdAt - b.createdAt,
+							},
+							{
+								title: "操作",
+								key: "option",
+								width: 120,
+								valueType: "option",
+								render: () => [
+									<Dropdown.Button type="link" overlay={menu}>
+										编辑
+									</Dropdown.Button>,
+								],
+							},
+						]}
+						rowSelection={{
+							// 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+							// 注释该行则默认不显示下拉选项
+							selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+						}}
+						tableAlertRender={({ selectedRowKeys, selectedRows, onCleanSelected }) => (
+							<Space size={24}>
+								<span>
+									已选 {selectedRowKeys.length} 项
+									<Button type="link" style={{ marginInlineStart: 8 }} onClick={onCleanSelected}>
+										取消选择
+									</Button>
+								</span>
+							</Space>
+						)}
+						tableAlertOptionRender={() => {
+							return (
+								<Space size={16}>
+									<Button type="link">批量删除</Button>
+								</Space>
+							);
+						}}
+						request={async (params = {}, sorter, filter) => {
+							// TODO
+							console.log(params, sorter, filter);
+
+							const size = params.pageSize || 20;
+							return {
+								total: 1 << 12,
+								success: true,
+								data: Array.from(Array(size).keys()).map((x) => {
+									const id = ((params.current || 1) - 1) * size + x + 1;
+
+									var it: IItem = {
+										id,
+										title: `title ${id}`,
+										subtitle: `subtitle ${id}`,
+										type: EType[Math.floor(Math.random() * 4)],
+										publicity: (Math.floor(Math.random() * 3) + 1) * 10,
+										createdAt: Date.now() - Math.floor(Math.random() * 2000000000),
+									};
+									return it;
+								}),
+							};
+						}}
+						rowKey="id"
+						bordered
+						pagination={{
+							showQuickJumper: true,
+							showSizeChanger: true,
+						}}
+						search={false}
+						options={{
+							search: true,
+						}}
+						toolBarRender={() => [
+							<Popover content={channelCreate} title="new channel" placement="bottomRight">
+								<Button key="button" icon={<PlusOutlined />} type="primary">
+									{intl.formatMessage({ id: "buttons.create" })}
+								</Button>
+							</Popover>,
+						]}
+					/>
 				</Content>
 			</Layout>
 			<Footer />