Skip to content

Commit 3cfad5d

Browse files
committed
feat: update customer service nickname & email
1 parent fd29f05 commit 3cfad5d

File tree

7 files changed

+107
-17
lines changed

7 files changed

+107
-17
lines changed

next/api/src/controller/customer-service.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class FindCustomerServicePipe {
3535
}
3636
}
3737

38-
const roleSchema = z.union([z.literal('admin'), z.literal('customerService')]);
38+
const roleSchema = z.enum(['admin', 'customerService']);
3939
const rolesSchema = z.array(roleSchema).nonempty();
4040

4141
const createCustomerServiceSchema = z.object({
@@ -54,6 +54,8 @@ type AddCategoryData = z.infer<typeof addCategorySchema>;
5454
const updateCustomerServiceSchema = z.object({
5555
active: z.boolean().optional(),
5656
roles: rolesSchema.optional(),
57+
nickname: z.string().optional(),
58+
email: z.string().optional(),
5759
});
5860
type UpdateCustomerServiceData = z.infer<typeof updateCustomerServiceSchema>;
5961

@@ -133,6 +135,18 @@ export class CustomerServiceController {
133135
processQueue.push(roleService.updateUserCSRoleTo(data.roles, user.id));
134136
}
135137

138+
if (data.nickname || data.email) {
139+
processQueue.push(
140+
user.update(
141+
{
142+
name: data.nickname,
143+
email: data.email,
144+
},
145+
{ useMasterKey: true }
146+
)
147+
);
148+
}
149+
136150
await Promise.all(processQueue);
137151

138152
return {};

next/api/src/controller/user.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type AuthData = z.infer<typeof authSchema>;
6060
const preCraeteSchema = z.object({
6161
email: z.string().email().optional(),
6262
username: z.string().optional(),
63+
nickname: z.string().optional(),
6364
});
6465
type PreCreateUserData = z.infer<typeof preCraeteSchema>;
6566

@@ -204,6 +205,7 @@ export class UserController {
204205
{
205206
// username might be `""`
206207
username: username ? username : email,
208+
name: data.nickname,
207209
email,
208210
password: Math.random().toString(),
209211
},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { forwardRef } from 'react';
2+
import { Form, FormInstance, Input } from 'antd';
3+
4+
import { CSRole } from '@/api/customer-service';
5+
import { RoleCheckboxGroup } from '@/App/Admin/components/RoleCheckboxGroup';
6+
7+
export interface CustomerServiceFormData {
8+
nickname?: string;
9+
email?: string;
10+
roles?: CSRole[];
11+
}
12+
13+
export interface CustomerServiceFormProps {
14+
initData?: Partial<CustomerServiceFormData>;
15+
onSubmit?: (data: CustomerServiceFormData) => void;
16+
}
17+
18+
export const CustomerServiceForm = forwardRef<FormInstance, CustomerServiceFormProps>(
19+
({ initData, onSubmit }, ref) => {
20+
const handleSubmit = (data: CustomerServiceFormData) => {
21+
onSubmit?.({
22+
nickname: data.nickname || undefined,
23+
email: data.email || undefined,
24+
roles: data.roles || [],
25+
});
26+
};
27+
28+
return (
29+
<Form ref={ref} layout="vertical" initialValues={initData} onFinish={handleSubmit}>
30+
<Form.Item name="nickname" label="昵称">
31+
<Input />
32+
</Form.Item>
33+
<Form.Item name="email" label="邮箱">
34+
<Input />
35+
</Form.Item>
36+
<Form.Item
37+
name="roles"
38+
label="角色"
39+
rules={[{ type: 'array', min: 1 }]}
40+
style={{ marginBottom: 0 }}
41+
>
42+
<RoleCheckboxGroup />
43+
</Form.Item>
44+
</Form>
45+
);
46+
}
47+
);

next/web/src/App/Admin/Settings/Members/index.tsx

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ import {
1111
useDeleteCustomerService,
1212
useUpdateCustomerService,
1313
} from '@/api/customer-service';
14-
import { Button, Modal, Popover, Table, message } from '@/components/antd';
14+
import { Button, Modal, Popover, Table, message, FormInstance } from '@/components/antd';
1515
import { Category, Retry, UserSelect } from '@/components/common';
1616
import { UserLabel } from '@/App/Admin/components';
1717
import { groupBy, sortBy } from 'lodash-es';
1818
import { RoleCheckboxGroup } from '../../components/RoleCheckboxGroup';
19+
import { CustomerServiceForm, CustomerServiceFormData } from './components/CustomerServiceForm';
1920

2021
function MemberActions({
2122
id,
2223
nickname,
2324
active,
2425
onEdit,
25-
}: CustomerServiceSchema & { onEdit?: () => void }) {
26+
}: Pick<CustomerServiceSchema, 'id' | 'nickname' | 'active'> & { onEdit?: () => void }) {
2627
const queryClient = useQueryClient();
2728

2829
const { mutate: update, isLoading: isUpdating } = useUpdateCustomerService({
@@ -133,20 +134,20 @@ function AddUserModal({ visible, onHide }: AddUserModalProps) {
133134
}
134135

135136
interface EditUserModalRef {
136-
open: (id: string, roles: CSRole[]) => void;
137+
open: (id: string, data: CustomerServiceFormData) => void;
137138
}
138139

139140
const EditUserModal = forwardRef<EditUserModalRef>((_, ref) => {
140141
const [userId, setUserId] = useState<string | undefined>();
141-
const [roles, setRoles] = useState<CSRole[] | undefined>();
142+
const [data, setData] = useState<CustomerServiceFormData>();
142143
const [visible, setVisible] = useState(false);
143144

144145
const queryClient = useQueryClient();
145146

146147
useImperativeHandle(ref, () => ({
147-
open: (id, roles) => {
148+
open: (id, data) => {
148149
setUserId(id);
149-
setRoles(roles);
150+
setData(data);
150151
setVisible(true);
151152
},
152153
}));
@@ -160,17 +161,24 @@ const EditUserModal = forwardRef<EditUserModalRef>((_, ref) => {
160161
},
161162
});
162163

164+
const formRef = useRef<FormInstance>(null);
165+
163166
return (
164167
<Modal
165-
visible={visible}
168+
destroyOnClose
169+
open={visible}
166170
title="更新客服"
167-
onOk={() => update({ id: userId!, roles })}
171+
onOk={() => formRef.current?.submit()}
168172
confirmLoading={isUpdating}
169-
okButtonProps={{ disabled: isUpdating || !userId || roles?.length === 0 }}
173+
okButtonProps={{ disabled: isUpdating || !userId }}
170174
onCancel={() => setVisible(false)}
171175
cancelButtonProps={{ disabled: isUpdating }}
172176
>
173-
<RoleCheckboxGroup value={roles} onChange={(v) => setRoles(v as CSRole[])} />
177+
<CustomerServiceForm
178+
ref={formRef}
179+
initData={data}
180+
onSubmit={(data) => update({ ...data, id: userId! })}
181+
/>
174182
</Modal>
175183
);
176184
});
@@ -280,11 +288,17 @@ export function Members() {
280288
<Table.Column
281289
key="actions"
282290
title="操作"
283-
render={(_, v: CustomerService) => (
291+
render={(u: CustomerService) => (
284292
<MemberActions
285-
{...v}
293+
id={u.id}
294+
nickname={u.nickname}
295+
active={u.active}
286296
onEdit={() => {
287-
editUserModalRef.current?.open(v.id, v.roles);
297+
editUserModalRef.current?.open(u.id, {
298+
nickname: u.nickname,
299+
email: u.email,
300+
roles: u.roles,
301+
});
288302
}}
289303
/>
290304
)}

next/web/src/App/Admin/Settings/Users/index.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,27 @@ export function NewUser() {
3232
control={control}
3333
name="username"
3434
render={({ field }) => (
35-
<Form.Item label="Username" htmlFor="username">
35+
<Form.Item label="用户名" htmlFor="username">
3636
<Input {...field} autoFocus id="username" />
3737
</Form.Item>
3838
)}
3939
/>
4040

41+
<Controller
42+
control={control}
43+
name="nickname"
44+
render={({ field }) => (
45+
<Form.Item label="昵称" htmlFor="nickname">
46+
<Input {...field} autoFocus id="nickname" />
47+
</Form.Item>
48+
)}
49+
/>
50+
4151
<Controller
4252
control={control}
4353
name="email"
4454
render={({ field }) => (
45-
<Form.Item label="Email" htmlFor="email">
55+
<Form.Item label="邮箱" htmlFor="email">
4656
<Input type="email" {...field} id="email" />
4757
</Form.Item>
4858
)}

next/web/src/api/customer-service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ async function addCustomerService(data: AddCustomerServiceData) {
4848
}
4949

5050
export interface UpdateCustomerServiceData {
51+
id: string;
5152
active?: boolean;
5253
roles?: CSRole[];
53-
id: string;
54+
nickname?: string;
55+
email?: string;
5456
}
5557

5658
async function updateCustomerService({ id, ...data }: UpdateCustomerServiceData) {

next/web/src/api/user.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const useUser = (id: string, options?: UseQueryOptions<UserSchema, Error>
5757

5858
export interface CreateUserData {
5959
username?: string;
60+
nickname?: string;
6061
email?: string;
6162
}
6263

0 commit comments

Comments
 (0)