UserDetail.tsx
9.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { message } from 'antd'
import { createUser, listUsers, updateUser } from '@/api/usr'
import { BizError } from '@/api/request'
import { useAppDispatch } from '@/store'
import { closeTab } from '@/store/tabs'
import type { UserListItem } from '@/api/types'
import { IconCancel, IconDelete, IconEdit, IconGrid, IconPlus, IconSave } from '@/components/icons'
interface Props {
mode: 'new' | 'edit'
}
const PERMS = [
'默认显示(必选)', '禁止查看价格', '客服跟单', '报价组员工', '物控部员工', '供应链PMC', '允许查看订单价格',
'储运部员工', '外部供应商', '品质部员工', '技术中心员工', '机修组员工', '生产部计划员工', '外发组员工',
'模烫车间', '装订车间', '后加工车间', '品质部管理', '精品车间', '人事组', '统计组', '机修主管',
'样品开发部员工', '设计开发', '总经办', '审核组', '结算组', '打样车间', '制版组', '文控组', '行政组',
'成本组', '采购组', 'OA管理员', '开发组', 'API对接', 'MES管理员', '报表组',
]
const TABS = ['权限组', '客户查看权限', '供应商查看权限', '人员查看权限', '工序查看权限', '司机查看权限']
const USER_TYPES = ['超级管理员', '普通用户']
const LANGS = [{ v: 'zh', t: '中文' }, { v: 'en', t: '英文' }]
interface FormState {
sUserNo: string
sUserName: string
sUserType: string
sLanguage: string
bCanModifyDocs: boolean
perms: Set<number>
tCreateDate: string
sCreatedBy: string
sStaffName: string
}
const empty: FormState = {
sUserNo: '',
sUserName: '',
sUserType: '超级管理员',
sLanguage: 'zh',
bCanModifyDocs: false,
perms: new Set([0]),
tCreateDate: '',
sCreatedBy: '',
sStaffName: '',
}
export default function UserDetail({ mode }: Props) {
const navigate = useNavigate()
const dispatch = useAppDispatch()
const params = useParams()
const userId = mode === 'edit' ? Number(params.id) : null
const [form, setForm] = useState<FormState>(empty)
const [tab, setTab] = useState(0)
const [submitting, setSubmitting] = useState(false)
const [editing, setEditing] = useState(mode === 'new')
const [loaded, setLoaded] = useState(mode === 'new')
useEffect(() => {
if (mode !== 'edit' || !userId) return
let cancelled = false
;(async () => {
try {
const res = await listUsers({ pageNum: 1, pageSize: 100, queryField: 'username', matchType: 'contains', queryValue: '' })
if (cancelled) return
const found = res.list.find((u: UserListItem) => u.iIncrement === userId)
if (!found) {
message.warning('用户不存在或已删除')
return
}
setForm({
sUserNo: found.sUserNo,
sUserName: found.sUserName,
sUserType: found.sUserType,
sLanguage: found.sLanguage,
bCanModifyDocs: false,
perms: new Set([0]),
tCreateDate: found.tCreateDate ?? '',
sCreatedBy: found.sCreatedBy ?? '',
sStaffName: found.sStaffName ?? '',
})
setLoaded(true)
} catch (err) {
const msg = err instanceof BizError ? err.message : '加载用户信息失败'
message.error(msg)
}
})()
return () => { cancelled = true }
}, [mode, userId])
const togglePerm = (i: number) => {
if (!editing) return
setForm(f => {
const next = new Set(f.perms)
if (next.has(i)) next.delete(i); else next.add(i)
next.add(0)
return { ...f, perms: next }
})
}
const handleSave = async () => {
if (!form.sUserNo.trim() || !form.sUserName.trim()) {
message.warning('请填写必填字段:用户号、用户名')
return
}
setSubmitting(true)
try {
const permIds = [...form.perms].map(i => i + 1)
if (mode === 'new') {
await createUser({
sUserNo: form.sUserNo.trim(),
sUserName: form.sUserName.trim(),
sUserType: form.sUserType,
sLanguage: form.sLanguage,
bCanModifyDocs: form.bCanModifyDocs,
permissionCategoryIds: permIds,
})
message.success('用户创建成功,初始密码 666666')
closeAndBack()
} else if (userId) {
await updateUser(userId, {
sUserType: form.sUserType,
sLanguage: form.sLanguage,
bCanModifyDocs: form.bCanModifyDocs,
permissionCategoryIds: permIds,
})
message.success('保存成功')
setEditing(false)
}
} catch (err) {
const msg = err instanceof BizError ? err.message : '保存失败'
message.error(msg)
} finally {
setSubmitting(false)
}
}
const closeAndBack = () => {
dispatch(closeTab('userdetail'))
navigate('/users')
}
const isNew = mode === 'new'
const langText = useMemo(
() => LANGS.find(l => l.v === form.sLanguage)?.t ?? form.sLanguage,
[form.sLanguage],
)
return (
<div className="userdetail-screen">
<div className="toolbar">
<span className={`tb-btn ${editing && !isNew ? 'disabled' : ''}`} onClick={() => !editing && navigate('/users/new')}>
<IconPlus />新增
</span>
<span className={`tb-btn ${editing || isNew ? 'disabled' : ''}`} onClick={() => !isNew && setEditing(true)}>
<IconEdit />修改
</span>
<span className="tb-btn disabled"><IconDelete />删除</span>
<span className={`tb-btn ${editing && !submitting ? '' : 'disabled'}`} onClick={editing ? handleSave : undefined}>
<IconSave />保存
</span>
<span className={`tb-btn ${editing && !isNew ? '' : 'disabled'}`} onClick={() => editing && !isNew && setEditing(false)}>
<IconCancel />取消
</span>
<span className="tb-btn disabled"><IconGrid />功能</span>
<span className="tb-btn disabled">作废</span>
<span className="tb-btn disabled">重置密码</span>
<span className="tb-btn disabled">取消作废</span>
<span className="spacer" />
<span className="gear">⚙</span>
</div>
<div className="form-grid">
<div className="form-cell">
<span className="lbl">创建时间:</span>
<div className="field readonly">{isNew ? '' : form.tCreateDate}</div>
</div>
<div className="form-cell">
<span className="lbl">制单人:</span>
<div className="field readonly">{isNew ? '保存后自动生成' : form.sCreatedBy}</div>
</div>
<div className="form-cell">
<span className="lbl req">员工名:</span>
<input
type="text"
value={form.sStaffName}
onChange={e => setForm(f => ({ ...f, sStaffName: e.target.value }))}
disabled={!editing}
placeholder="(暂不绑定员工档案)"
/>
</div>
<div className="form-cell">
<span className="lbl req">用户名:</span>
<input
type="text"
value={form.sUserName}
onChange={e => setForm(f => ({ ...f, sUserName: e.target.value }))}
disabled={!editing || !isNew}
/>
</div>
<div className="form-cell">
<span className="lbl req">类型:</span>
{editing ? (
<select className="field" value={form.sUserType} onChange={e => setForm(f => ({ ...f, sUserType: e.target.value }))}>
{USER_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
</select>
) : (
<div className="field readonly">{form.sUserType}</div>
)}
</div>
<div className="form-cell">
<span className="lbl req">语言:</span>
{editing ? (
<select className="field" value={form.sLanguage} onChange={e => setForm(f => ({ ...f, sLanguage: e.target.value }))}>
{LANGS.map(l => <option key={l.v} value={l.v}>{l.t}</option>)}
</select>
) : (
<div className="field readonly">{langText}</div>
)}
</div>
<div className="form-cell">
<span className="lbl req">用户号:</span>
<input
type="text"
value={form.sUserNo}
onChange={e => setForm(f => ({ ...f, sUserNo: e.target.value }))}
disabled={!editing || !isNew}
/>
</div>
<div className="form-cell"></div>
<div className="form-cell">
<span className="lbl">单据修改权限:</span>
<span
className={`cb ${form.bCanModifyDocs ? 'checked' : ''}`}
onClick={() => editing && setForm(f => ({ ...f, bCanModifyDocs: !f.bCanModifyDocs }))}
/>
</div>
</div>
<div className="tabs-row">
{TABS.map((t, i) => (
<div key={t} className={`tb ${tab === i ? 'active' : ''}`} onClick={() => setTab(i)}>
{t}
</div>
))}
</div>
<div className="perm-list">
<div className="perm-row head">
<span className="cb"></span>
<span>权限分类</span>
<span className="ic" style={{ marginLeft: 'auto', color: '#aaa' }}>⇅</span>
</div>
{tab === 0 ? (
loaded && PERMS.map((p, i) => (
<div key={p} className="perm-row" onClick={() => togglePerm(i)}>
<span className={`cb ${form.perms.has(i) ? 'checked' : ''}`} />
<span>{p}</span>
</div>
))
) : (
<div style={{ padding: '40px 14px', color: '#888', textAlign: 'center' }}>该 tab 后端暂未实现</div>
)}
</div>
</div>
)
}