- 新增家庭共享订阅管理 - 新增用户邀请统计 - 新增签名和订阅模式设置表单 - 更新 API 服务层和国际化文件 - UI 组件优化(enhanced-input、pro-table)
This commit is contained in:
@@ -26,7 +26,7 @@ export default function Announcement({ type }: { type: "popup" | "pinned" }) {
|
||||
const result = await queryAnnouncement(
|
||||
{
|
||||
page: 1,
|
||||
size: 10,
|
||||
size: 200,
|
||||
pinned: type === "pinned",
|
||||
popup: type === "popup",
|
||||
},
|
||||
@@ -52,7 +52,7 @@ export default function Announcement({ type }: { type: "popup" | "pinned" }) {
|
||||
<DialogHeader>
|
||||
<DialogTitle>{data.title}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="prose prose-sm max-w-none dark:prose-invert">
|
||||
<div className="prose prose-sm dark:prose-invert max-w-none">
|
||||
<Markdown>{data.content}</Markdown>
|
||||
</div>
|
||||
</DialogContent>
|
||||
@@ -69,7 +69,7 @@ export default function Announcement({ type }: { type: "popup" | "pinned" }) {
|
||||
</h2>
|
||||
<Card className="p-6">
|
||||
{data.content ? (
|
||||
<div className="prose prose-sm max-w-none dark:prose-invert">
|
||||
<div className="prose prose-sm dark:prose-invert max-w-none">
|
||||
<Markdown>{data.content}</Markdown>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -13,12 +13,12 @@ import {
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@workspace/ui/components/tabs";
|
||||
import { Icon } from "@workspace/ui/composed/icon";
|
||||
import { Markdown } from "@workspace/ui/composed/markdown";
|
||||
import {
|
||||
ProList,
|
||||
type ProListActions,
|
||||
} from "@workspace/ui/composed/pro-list/pro-list";
|
||||
import { Icon } from "@workspace/ui/composed/icon";
|
||||
import { Markdown } from "@workspace/ui/composed/markdown";
|
||||
import { queryAnnouncement } from "@workspace/ui/services/user/announcement";
|
||||
import { formatDate } from "@workspace/ui/utils/formatting";
|
||||
import { useRef, useState } from "react";
|
||||
@@ -60,13 +60,13 @@ export default function Announcement() {
|
||||
<div className="flex items-center gap-2">
|
||||
<CardTitle className="text-lg">{item.title}</CardTitle>
|
||||
{item.pinned && (
|
||||
<span className="flex items-center gap-1 rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary">
|
||||
<span className="flex items-center gap-1 rounded-full bg-primary/10 px-2 py-0.5 font-medium text-primary text-xs">
|
||||
<Icon className="size-3" icon="uil:pin" />
|
||||
{t("pinned", "Pinned")}
|
||||
</span>
|
||||
)}
|
||||
{item.popup && (
|
||||
<span className="flex items-center gap-1 rounded-full bg-orange-500/10 px-2 py-0.5 text-xs font-medium text-orange-500">
|
||||
<span className="flex items-center gap-1 rounded-full bg-orange-500/10 px-2 py-0.5 font-medium text-orange-500 text-xs">
|
||||
<Icon className="size-3" icon="uil:popcorn" />
|
||||
{t("popup", "Popup")}
|
||||
</span>
|
||||
@@ -80,7 +80,7 @@ export default function Announcement() {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="prose prose-sm max-w-none dark:prose-invert">
|
||||
<div className="prose prose-sm dark:prose-invert max-w-none">
|
||||
<Markdown>{item.content}</Markdown>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -95,9 +95,7 @@ export default function Announcement() {
|
||||
</h2>
|
||||
<Tabs defaultValue="all" onValueChange={setActiveTab}>
|
||||
<TabsList>
|
||||
<TabsTrigger value="all">
|
||||
{t("all", "All")}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="all">{t("all", "All")}</TabsTrigger>
|
||||
<TabsTrigger value="pinned">
|
||||
{t("pinnedOnly", "Pinned Only")}
|
||||
</TabsTrigger>
|
||||
@@ -110,9 +108,7 @@ export default function Announcement() {
|
||||
<ProList
|
||||
action={normalRef}
|
||||
renderItem={renderAnnouncement}
|
||||
request={async (pagination) => {
|
||||
return requestAnnouncements(pagination, {});
|
||||
}}
|
||||
request={async (pagination) => requestAnnouncements(pagination, {})}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
@@ -120,9 +116,9 @@ export default function Announcement() {
|
||||
<ProList
|
||||
action={pinnedRef}
|
||||
renderItem={renderAnnouncement}
|
||||
request={async (pagination) => {
|
||||
return requestAnnouncements(pagination, { pinned: true });
|
||||
}}
|
||||
request={async (pagination) =>
|
||||
requestAnnouncements(pagination, { pinned: true })
|
||||
}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
@@ -130,9 +126,9 @@ export default function Announcement() {
|
||||
<ProList
|
||||
action={normalRef}
|
||||
renderItem={renderAnnouncement}
|
||||
request={async (pagination) => {
|
||||
return requestAnnouncements(pagination, { popup: true });
|
||||
}}
|
||||
request={async (pagination) =>
|
||||
requestAnnouncements(pagination, { popup: true })
|
||||
}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -25,7 +25,9 @@ export default function RedeemCode({ onSuccess }: RedeemCodeProps) {
|
||||
const redeemMutation = useMutation({
|
||||
mutationFn: (code: string) => redeemCode({ code }),
|
||||
onSuccess: (response) => {
|
||||
const message = (response.data as { message?: string })?.message || t("redeemSuccess", "兑换成功");
|
||||
const message =
|
||||
(response.data as { message?: string })?.message ||
|
||||
t("redeemSuccess", "兑换成功");
|
||||
toast.success(message);
|
||||
setCode("");
|
||||
onSuccess?.();
|
||||
@@ -64,10 +66,7 @@ export default function RedeemCode({ onSuccess }: RedeemCodeProps) {
|
||||
<Input
|
||||
id="redemption-code"
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
placeholder={t(
|
||||
"enterRedemptionCode",
|
||||
"请输入兑换码"
|
||||
)}
|
||||
placeholder={t("enterRedemptionCode", "请输入兑换码")}
|
||||
value={code}
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -65,7 +65,11 @@ export default function Page() {
|
||||
orderNo: order_no!,
|
||||
returnUrl: window.location.href,
|
||||
});
|
||||
if (data.data?.type === "url" && data.data.checkout_url && !paymentOpened) {
|
||||
if (
|
||||
data.data?.type === "url" &&
|
||||
data.data.checkout_url &&
|
||||
!paymentOpened
|
||||
) {
|
||||
window.open(data.data.checkout_url, "_blank");
|
||||
setPaymentOpened(true);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
updateBindEmail,
|
||||
updateBindMobile,
|
||||
} from "@workspace/ui/services/user/user";
|
||||
import { shortenDeviceIdentifier } from "@workspace/ui/utils/device";
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -287,6 +288,14 @@ export default function ThirdPartyAccounts() {
|
||||
? currentValue
|
||||
: method?.auth_identifier || "";
|
||||
break;
|
||||
case "device":
|
||||
displayValue = method?.auth_identifier
|
||||
? shortenDeviceIdentifier(method.auth_identifier)
|
||||
: t(
|
||||
`thirdParty.${account.id}.description`,
|
||||
account.descriptionDefault
|
||||
);
|
||||
break;
|
||||
default:
|
||||
displayValue =
|
||||
method?.auth_identifier ||
|
||||
|
||||
Reference in New Issue
Block a user