- 批量解析:智能区分字段分隔符(Tab优先,否则中英逗号/分号),避免竖线误伤;支持工作组被切到多个字段后自动合并 - 工作组匹配:新增多种分隔符与忽略空格匹配;当义工号字段非纯数字且命中工作组时自动识别为工作组(兼容3列格式:班级,姓名,工作组) - 列表展示:前端二次按班级locale排序(中文+数字感知)+ 姓名,与后端SQL排序互补
This commit is contained in:
@@ -112,6 +112,11 @@ export default function Users() {
|
||||
group_ids: x.group_ids ?? [],
|
||||
group_names: x.group_names ?? [],
|
||||
}));
|
||||
filled.sort((a, b) => {
|
||||
const c = (a.class || '').localeCompare(b.class || '', 'zh-Hans-CN', { numeric: true });
|
||||
if (c !== 0) return c;
|
||||
return (a.name || '').localeCompare(b.name || '', 'zh-Hans-CN');
|
||||
});
|
||||
setList(filled);
|
||||
setGroups(g);
|
||||
} finally {
|
||||
@@ -188,36 +193,80 @@ export default function Users() {
|
||||
const rows: BatchParsedRow[] = [];
|
||||
const lines = batchText.split(/\r?\n/);
|
||||
const groupMap = new Map<string, number>();
|
||||
for (const g of groups) groupMap.set(g.name.trim(), g.id);
|
||||
const groupNameNormalized = new Map<string, string>();
|
||||
for (const g of groups) {
|
||||
const key = g.name.trim();
|
||||
groupMap.set(key, g.id);
|
||||
groupNameNormalized.set(key, g.name);
|
||||
groupMap.set(g.name, g.id);
|
||||
groupNameNormalized.set(g.name, g.name);
|
||||
const noSpace = key.replace(/\s+/g, '');
|
||||
if (noSpace !== key) {
|
||||
groupMap.set(noSpace, g.id);
|
||||
groupNameNormalized.set(noSpace, g.name);
|
||||
}
|
||||
}
|
||||
|
||||
const splitGroupNames = (s: string): string[] => {
|
||||
const result: string[] = [];
|
||||
if (!s) return result;
|
||||
const segs = s.split(/[\/、||,,;;\s\u3000]+/);
|
||||
for (const seg of segs) {
|
||||
const n = seg.trim().replace(/\s+/g, '');
|
||||
if (n) result.push(n);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (!line.trim()) continue;
|
||||
const parts = line.split(/[,,\t|;;]/).map((p) => p.trim());
|
||||
const [cls, name, volunteer_no = '', groupsStr = ''] = parts;
|
||||
let parts: string[];
|
||||
if (line.includes('\t')) {
|
||||
parts = line.split(/\t/).map((p) => p.trim());
|
||||
} else {
|
||||
parts = line.split(/[,,;;]/).map((p) => p.trim());
|
||||
}
|
||||
const [cls = '', name = '', volunteer_no = '', ...rest] = parts;
|
||||
const groupsStr = rest.join(',');
|
||||
const errors: string[] = [];
|
||||
if (!cls) errors.push('缺少班级');
|
||||
if (!name) errors.push('缺少姓名');
|
||||
const groupIds: number[] = [];
|
||||
const groupNames: string[] = [];
|
||||
if (groupsStr) {
|
||||
const rawNames = groupsStr.split(/[/、|\s]+/).map((x) => x.trim()).filter(Boolean);
|
||||
for (const n of rawNames) {
|
||||
const gid = groupMap.get(n);
|
||||
if (gid === undefined) {
|
||||
errors.push(`工作组「${n}」不存在`);
|
||||
} else {
|
||||
if (!groupIds.includes(gid)) {
|
||||
groupIds.push(gid);
|
||||
groupNames.push(n);
|
||||
}
|
||||
const rawNames = splitGroupNames([volunteer_no, groupsStr].filter(Boolean).join('/'));
|
||||
const volunteerLooksLikeNo = /^\d+$/.test(volunteer_no.trim());
|
||||
const realRawNames: string[] = [];
|
||||
if (volunteer_no.trim() && !volunteerLooksLikeNo) {
|
||||
const probe = splitGroupNames(volunteer_no);
|
||||
const allMatch = probe.length > 0 && probe.every((n) => groupMap.has(n));
|
||||
if (allMatch) {
|
||||
realRawNames.push(...probe);
|
||||
} else {
|
||||
realRawNames.push(...splitGroupNames(groupsStr));
|
||||
}
|
||||
} else {
|
||||
realRawNames.push(...splitGroupNames(groupsStr));
|
||||
}
|
||||
for (const n of realRawNames) {
|
||||
if (!n) continue;
|
||||
const gid = groupMap.get(n);
|
||||
if (gid === undefined) {
|
||||
errors.push(`工作组「${n}」不存在`);
|
||||
} else {
|
||||
if (!groupIds.includes(gid)) {
|
||||
groupIds.push(gid);
|
||||
const display = groupNameNormalized.get(n) || n;
|
||||
if (!groupNames.includes(display)) groupNames.push(display);
|
||||
}
|
||||
}
|
||||
}
|
||||
const vol = volunteerLooksLikeNo ? volunteer_no : '';
|
||||
rows.push({
|
||||
idx: i,
|
||||
class: cls || '',
|
||||
name: name || '',
|
||||
volunteer_no,
|
||||
volunteer_no: vol,
|
||||
group_ids: groupIds,
|
||||
group_names: groupNames,
|
||||
raw: line,
|
||||
|
||||
Reference in New Issue
Block a user