4a2b2b7d84
build / build (push) Successful in 1m5s
区域配置入口改为区域统计,五列表按当前通讯录整支人员去重;调岗依当前归属、零分母未知、最近真实提问时间和父行收起不重算。仅读治理正式总表,后台单并发/请求合并/60秒缓存,目录与配置版本隔离,客户端失败不伪零。 保留区域自定义目录与预览/双版本锁保存,父部门勾选联选全后代,取消子支清除祖先整支选择,避免隐式覆盖未选子级;允许删除无引用区域,已有引用不静默孤立。统计页与设置共享选择,统计支持累计与北京时间自然月;不新增迁移,不改DobotAI生产、代理、原问答、历史趋势或已有AI任务。 验证已执行:完整make verify退出0,705 Go/340前端通过、120项声明的可选集成跳过且必需0跳过;镜像全量隔离PG race退出0;新增去重/调岗/空分母、后台缓存/并发、HTTP授权/严格请求、真PG目录与配置失效、树选择/收起、五列与删除保护均先红后绿。旧导航测试按新名称更新后全量通过。上线前治理库备份与真实恢复72表/29张QA内容哈希一致,匹配独立主密钥受限备份。 当前尚待精确SHA CI、同镜像真实数据浏览器与正式读回,不把源码验证称为已上线。公司真实区域映射不在本轮擅改;只在隔离库验证保存。
27 lines
1.3 KiB
TypeScript
27 lines
1.3 KiB
TypeScript
import { it, expect } from 'vitest'
|
|
import { subtreeIDs, selectDepartmentBranch, departmentTree } from './qaRegionSelection'
|
|
const nodes = [
|
|
{ id: 'root', parent_id: '', name: 'Root' },
|
|
{ id: 'child', parent_id: 'root', name: 'Child' },
|
|
{ id: 'leaf', parent_id: 'child', name: 'Leaf' },
|
|
{ id: 'other', parent_id: 'root', name: 'Other' },
|
|
]
|
|
it('selects a full branch and removes partial ancestors when a descendant is unchecked', () => {
|
|
expect(new Set(subtreeIDs(nodes, ['child']))).toEqual(new Set(['child', 'leaf']))
|
|
const selected = selectDepartmentBranch(nodes, [], 'root', true)
|
|
expect(new Set(selected)).toEqual(new Set(nodes.map((d) => d.id)))
|
|
expect(new Set(selectDepartmentBranch(nodes, selected, 'leaf', false))).toEqual(new Set(['other']))
|
|
expect(selected).toHaveLength(4)
|
|
})
|
|
it('collapses hierarchy without dropping source rows or changing statistics', () => {
|
|
const before = JSON.stringify(nodes)
|
|
expect(departmentTree(nodes, new Set(['child'])).map((r) => r.department.id)).toEqual(['root', 'child', 'other'])
|
|
expect(departmentTree(nodes, new Set(['root']), 'Leaf').map((r) => r.department.id)).toEqual([
|
|
'root',
|
|
'child',
|
|
'leaf',
|
|
])
|
|
expect(JSON.stringify(nodes)).toBe(before)
|
|
expect(() => departmentTree([{ id: 'bad', parent_id: 'bad', name: 'Cycle' }], new Set())).toThrow()
|
|
})
|