增加备注功能
This commit is contained in:
@@ -31,6 +31,13 @@ import {
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from "@workspace/ui/components/sheet";
|
||||
import { FilePenLine } from 'lucide-react';
|
||||
import {
|
||||
Popover,
|
||||
PopoverClose,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@workspace/ui/components/popover';
|
||||
import { Switch } from "@workspace/ui/components/switch";
|
||||
import {
|
||||
Tabs,
|
||||
@@ -39,7 +46,7 @@ import {
|
||||
TabsTrigger,
|
||||
} from "@workspace/ui/components/tabs";
|
||||
import { Combobox } from "@workspace/ui/composed/combobox";
|
||||
import { ConfirmButton } from "@workspace/ui/composed/confirm-button";
|
||||
// import { ConfirmButton } from "@workspace/ui/composed/confirm-button";
|
||||
import {
|
||||
ProTable,
|
||||
type ProTableActions,
|
||||
@@ -50,13 +57,13 @@ import {
|
||||
} from "@workspace/ui/services/admin/group";
|
||||
import {
|
||||
createUser,
|
||||
deleteUser,
|
||||
// deleteUser,
|
||||
getUserDetail,
|
||||
getUserList,
|
||||
updateUserBasicInfo,
|
||||
} from "@workspace/ui/services/admin/user";
|
||||
import { parseDeviceType } from "@workspace/ui/utils/device";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import React, { useRef, useState, useCallback } from 'react';
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import { Display } from "@/components/display";
|
||||
@@ -72,6 +79,44 @@ import { NotifySettingsForm } from "./user-profile/notify-settings-form";
|
||||
import UserSubscription from "./user-subscription";
|
||||
// import EditUserGroupDialog from "./edit-user-group-dialog";
|
||||
|
||||
|
||||
// 为 RemarkForm 组件定义 props 类型
|
||||
interface RemarkFormProps {
|
||||
initialRemark?: string | null;
|
||||
onSave: (remark: string) => void;
|
||||
CloseComponent: React.ComponentType<{ asChild?: boolean; children: React.ReactNode }>;
|
||||
}
|
||||
// 新的子组件,在管理它自己的备注状态
|
||||
const RemarkForm: React.FC<RemarkFormProps> = ({ onSave, initialRemark, CloseComponent }) => {
|
||||
const [remark, setRemark] = useState<string>(initialRemark ?? '');
|
||||
|
||||
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setRemark(event.target.value);
|
||||
};
|
||||
|
||||
const handleSaveClick = () => {
|
||||
onSave(remark);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='mb-2 text-sm font-semibold'>备注</div>
|
||||
<Input
|
||||
type='text'
|
||||
value={remark}
|
||||
onChange={handleInputChange}
|
||||
placeholder='在此输入备注...'
|
||||
className='w-full'
|
||||
/>
|
||||
<CloseComponent asChild>
|
||||
<Button onClick={handleSaveClick} variant='default' size={'sm'} className={'mt-2'}>
|
||||
保存
|
||||
</Button>
|
||||
</CloseComponent>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function User() {
|
||||
const { t } = useTranslation("user");
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -139,7 +184,7 @@ export default function User() {
|
||||
userId={row.id}
|
||||
/>,
|
||||
<PreviewNodesDialog key="preview-nodes" userId={row.id} />,
|
||||
<ConfirmButton
|
||||
/* <ConfirmButton
|
||||
cancelText={t("cancel", "Cancel")}
|
||||
confirmText={t("confirm", "Confirm")}
|
||||
description={t(
|
||||
@@ -156,7 +201,7 @@ export default function User() {
|
||||
trigger={
|
||||
<Button variant="destructive">{t("delete", "Delete")}</Button>
|
||||
}
|
||||
/>,
|
||||
/>,*/
|
||||
<DropdownMenu key="more" modal={false}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline">{t("more", "More")}</Button>
|
||||
@@ -232,7 +277,7 @@ export default function User() {
|
||||
accessorKey: "id",
|
||||
header: "ID",
|
||||
},
|
||||
{
|
||||
/*{
|
||||
id: "deleted_at",
|
||||
accessorKey: "deleted_at",
|
||||
header: t("isDeleted", "Deleted"),
|
||||
@@ -244,11 +289,11 @@ export default function User() {
|
||||
<Badge variant="outline">{t("normal", "Normal")}</Badge>
|
||||
);
|
||||
},
|
||||
},
|
||||
},*/
|
||||
{
|
||||
id: "auth_methods",
|
||||
accessorKey: "auth_methods",
|
||||
header: t("userName", "Username"),
|
||||
header: '设备码/邮箱',
|
||||
cell: ({ row }) => {
|
||||
const method = row.original.auth_methods?.[0];
|
||||
const identifier = method?.auth_identifier || "";
|
||||
@@ -259,23 +304,48 @@ export default function User() {
|
||||
const display = isDevice ? deviceNo || identifier : identifier;
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<Badge
|
||||
{/* <Badge
|
||||
className="mr-1 uppercase"
|
||||
title={method?.verified ? t("verified", "Verified") : ""}
|
||||
>
|
||||
{method?.auth_type}
|
||||
</Badge>
|
||||
</Badge>*/}
|
||||
{deviceType && (
|
||||
<Badge className="mr-1" variant="secondary">
|
||||
{deviceType}
|
||||
</Badge>
|
||||
<Badge className="mr-1" variant="secondary">
|
||||
{deviceType}
|
||||
</Badge>
|
||||
)}
|
||||
<span title={isDevice ? display : undefined}>{display}</span>
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<div className={'flex items-center'}>
|
||||
{row.original?.remark ? `(${row.original.remark})` : ''}
|
||||
<FilePenLine size={14} className={'text-primary ml-2'} />
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className={'w-64'}>
|
||||
<RemarkForm
|
||||
initialRemark={row.original.remark}
|
||||
CloseComponent={PopoverClose}
|
||||
onSave={async (remark) => {
|
||||
const {
|
||||
id,
|
||||
} = row.original;
|
||||
await updateUserBasicInfo({
|
||||
user_id: id,
|
||||
remark,
|
||||
} as unknown as API.UpdateUserBasiceInfoRequest);
|
||||
toast.success(t('updateSuccess'));
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
/* {
|
||||
id: "balance",
|
||||
accessorKey: "balance",
|
||||
header: t("balance", "Balance"),
|
||||
@@ -290,7 +360,7 @@ export default function User() {
|
||||
cell: ({ row }) => (
|
||||
<Display type="currency" value={row.getValue("gift_amount")} />
|
||||
),
|
||||
},
|
||||
},*/
|
||||
{
|
||||
id: "commission",
|
||||
accessorKey: "commission",
|
||||
@@ -531,12 +601,11 @@ function UserSearchBar({
|
||||
}}
|
||||
value={searchType}
|
||||
>
|
||||
<SelectTrigger className="w-24">
|
||||
<SelectTrigger className="w-48">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="email">{t("email", "Email")}</SelectItem>
|
||||
<SelectItem value="device">{t("deviceSearch", "Device")}</SelectItem>
|
||||
<SelectItem value="email">设备码/邮箱</SelectItem>
|
||||
<SelectItem value="user_id">{t("userId", "User ID")}</SelectItem>
|
||||
<SelectItem value="subscribe_id">
|
||||
{t("subscription", "Subscription")}
|
||||
|
||||
Reference in New Issue
Block a user