@csntgao/uni-base 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.md +2 -0
- package/package.json +1 -1
- package/packages/web-components/package.json +1 -1
- package/packages/web-components/src/account-context.ts +26 -4
- package/packages/web-components/tests/account-context.test.ts +49 -2
- package//344/272/244/346/216/245/346/226/207/346/241/243.md +20 -16
package/AGENTS.md
CHANGED
|
@@ -45,7 +45,7 @@ examples/vanilla 原生 HTML / JavaScript 接入示例
|
|
|
45
45
|
|
|
46
46
|
`<uniplat-organization-single-employee-selector>` 是语义独立的组织员工单选公共组件。它可与多选组件复用内部数据控制器和真实 transport,但公开标签、`open()` 参数和确认 detail 必须独立。单选界面不渲染多选的已选右侧栏和移动端已选页签,候选区占满内容宽度,选择标识必须为单选圆点而非复选框。单选组件只接收 `initialSelectedEmployeeId`,确认时只返回 `{ employeeId, employee }`;不得向任一组件暴露 `selectionMode`,也不得让单选组件接收 `maxSelection` 或多选 ID 数组。候选数据继续只包含当前 JWT 组织内在职且启用的员工,JWT 和身份字段安全边界与多选组件一致。
|
|
47
47
|
|
|
48
|
-
`<uniplat-account-context>` 是 40.1 原型导航右侧的统一账户工作台组件,不渲染品牌和全局菜单。它在一个 Host 元素内包含工作台入口、账户胶囊、应用入口浮层和 6.7 企业/团队切换浮层;两个浮层互斥并绝对定位,不改变导航布局。组件根据 Host 提供的 `applicationName` 和账户 transport 自行加载当前应用对应的组织投影与企业认证状态;用户资料复用 `list_available_organizations` 顶层的 `display_name`、`avatar_url` 与 `mobile_masked`,不得再请求 `profile_summary_v2`,Host 不再组装这些展示数据。它支持无归属个人态、企业未认证/审核中/未通过/已认证/认证过期和团队态;组织切换由 Host 响应事件,应用加载与 ticket 跳转复用独立的 Application Switcher transport
|
|
48
|
+
`<uniplat-account-context>` 是 40.1 原型导航右侧的统一账户工作台组件,不渲染品牌和全局菜单。它在一个 Host 元素内包含工作台入口、账户胶囊、应用入口浮层和 6.7 企业/团队切换浮层;两个浮层互斥并绝对定位,不改变导航布局。组件根据 Host 提供的 `applicationName` 和账户 transport 自行加载当前应用对应的组织投影与企业认证状态;用户资料复用 `list_available_organizations` 顶层的 `display_name`、`avatar_url` 与 `mobile_masked`,不得再请求 `profile_summary_v2`,Host 不再组装这些展示数据。它支持无归属个人态、企业未认证/审核中/未通过/已认证/认证过期和团队态;组织切换由 Host 响应事件,应用加载与 ticket 跳转复用独立的 Application Switcher transport。选中组织时,账户胶囊和菜单资料区必须使用服务端投影中该组织的员工姓名与头像;没有选中组织或该组织没有员工身份时,回退到用户资料。账户胶囊宽度固定,胶囊内姓名超过 6 个字、组织名称超过 8 个字必须截断为省略号,完整值只放在 `title` 上,不得让长名称撑宽胶囊挤压导航左侧内容;展开菜单内仍显示完整名称。组织列表严格使用原型中的企业建筑与团队成员图标,不得替换成员工头像或组织首字。
|
|
49
49
|
|
|
50
50
|
`<uniplat-notification-center>` 是内嵌通知中心面板,复刻 AE-Enterprise-Admin 通知中心原型的两栏收件箱:面板顶栏、五类页签、列表、详情、关联资源、附件下载与“全部标已读”。**组件和 core 都不建立 WebSocket 连接**:Host 保留自己唯一的 `/api/user-realtime/ws` 连接并订阅 `notification` channel,把事件原始负载通过 `applyRealtimeEvent()` 喂给组件;`authenticate` 首帧、心跳、游标、重连和断连提示全部归 Host。组件只负责收件箱投影、增量更新和未读数,顶栏铃铛仍属 Host chrome。不得为通知新增第二条 socket 或平行实时通道。
|
|
51
51
|
|
|
@@ -439,7 +439,7 @@ npm 包名、导出类型名、Custom Element 标签、`configure()` 结构、
|
|
|
439
439
|
- Organization Selector 需测试完整列表、企业认证与团队类型样式、脱敏账户摘要与完整手机号拒绝、按名称和统一社会信用代码搜索且代码不进入 DOM、类型筛选与常显计数、“最近进入 / 全部组织”分组与默认选中、带目标名称的主按钮、无匹配与空归属状态、记住偏好、创建/进入/退出登录事件、`modal` 强制态无关闭按钮且遮罩点击与 `Escape` 都不关闭并在移除后解除 `Escape` 拦截、非法 `presentation` 与重复 ID 拒绝和普通文本插值;事件只包含稳定组织 ID 与偏好,不含姓名、手机号、组织名称或信用代码。`resolveOrganizationEntryDecision()` 需测试 0 个归属、单一归属、命中与失效的记住选择、2 个及以上的默认选中项和非法输入拒绝。
|
|
440
440
|
- Organization Multi Employee Selector 需测试部门树、员工分页和搜索、初始选择补取、跨部门按员工 ID 去重、多选上限、受保护项、确认/取消事件、独立滚动、移动视图、错误重试、身份切换清理,以及 JWT、完整手机号、身份字段和后端错误不进入 DOM、事件、URL或日志。专用 transport 必须测试每次请求重新读取 JWT、只使用 Authorization header、组织级 directory scope 和无调用方身份参数。
|
|
441
441
|
- Organization Single Employee Selector 需测试独立标签与导出、初始单个 ID 回显、新选择替换旧选择、未选时禁止确认、受保护项、标量确认 detail、拒绝多选打开参数,以及与多选组件相同的数据和认证安全边界。
|
|
442
|
-
- Account Context 需测试必填应用名、组件通过 transport
|
|
442
|
+
- Account Context 需测试必填应用名、组件通过 transport 自行加载用户资料与完整应用组织投影、无归属、企业五种认证状态和团队状态、当前组织员工身份优先及无组织用户身份回退、安全头像与加载失败回退、胶囊内姓名 6 字与组织名 8 字截断及完整 `title`、未超长时不加 `title`、工作台、账户菜单与内置入驻浮层互斥、浮层不改变导航布局、内嵌应用九宫格、创建入口直接启动内置入驻、Host 响应组织切换事件、退出和公共事件安全。专用 UniplatBase transport 还必须测试不请求 `profile_summary_v2`、从 `list_available_organizations` 顶层读取用户资料、按 `application_name` 加载投影、Open Application 的 `organization_oid` 切换、组织级应用目标 `xid` 选择、JWT 只进入 Authorization header 和 Host `setAccessToken()`、响应净化、稳定错误以及公共数据无 JWT;组件范围不得扩展为品牌或完整导航。
|
|
443
443
|
- 通知中心需测试组件注册与导出、两栏首版输出、数据驱动分类页签(`includeTypeFacets` 随收件箱请求、后端 `type_facets` 优先、无 facet 回退累积、筛选后页签不塌缩、展示名取 `notification_type_name` 且为空时回退原始 code、契约四个码不得残留内置中文名、实时新分类入目录)、未读角标与 `unread-count-change`、打开未读即标记已读、全部已读、加载更多、关联资源事件只含安全业务标识、附件经 transport 下载、Markdown 净化、`applyRealtimeEvent()` 不建立任何 WebSocket 且原地更新列表与未读数、事件无法映射时降级刷新、收件箱在途时延后 resync 不丢事件、`configure()` 之前与移除之后喂入事件无副作用、错误横幅为净化文案,以及 JWT 与后端原始正文不进入 DOM、公共事件或日志。小型通知浮层还需测试初始关闭、4 条未读投影、未读总数、严格原型结构与 SVG 图标、单条/全部已读、完整通知页意图事件只含稳定 ID、外部关闭、空态以及 Host 实时事件更新。
|
|
444
444
|
- 使用 fake timer 的测试必须恢复 timer;构造 fake WebSocket 时不要把测试凭据写入 URL。
|
|
445
445
|
- 修复竞态或生命周期问题时增加回归测试,不只验证最终 DOM。
|
package/CLAUDE.md
CHANGED
|
@@ -45,7 +45,7 @@ examples/vanilla 原生 HTML / JavaScript 接入示例
|
|
|
45
45
|
|
|
46
46
|
`<uniplat-organization-single-employee-selector>` 是语义独立的组织员工单选公共组件。它可与多选组件复用内部数据控制器和真实 transport,但公开标签、`open()` 参数和确认 detail 必须独立。单选界面不渲染多选的已选右侧栏和移动端已选页签,候选区占满内容宽度,选择标识必须为单选圆点而非复选框。单选组件只接收 `initialSelectedEmployeeId`,确认时只返回 `{ employeeId, employee }`;不得向任一组件暴露 `selectionMode`,也不得让单选组件接收 `maxSelection` 或多选 ID 数组。候选数据继续只包含当前 JWT 组织内在职且启用的员工,JWT 和身份字段安全边界与多选组件一致。
|
|
47
47
|
|
|
48
|
-
`<uniplat-account-context>` 是 40.1 原型导航右侧的统一账户工作台组件,不渲染品牌和全局菜单。它在一个 Host 元素内包含工作台入口、账户胶囊、应用入口浮层和 6.7 企业/团队切换浮层;两个浮层互斥并绝对定位,不改变导航布局。组件根据 Host 提供的 `applicationName` 和账户 transport 自行加载当前应用对应的组织投影与企业认证状态;用户资料复用 `list_available_organizations` 顶层的 `display_name`、`avatar_url` 与 `mobile_masked`,不得再请求 `profile_summary_v2`,Host 不再组装这些展示数据。它支持无归属个人态、企业未认证/审核中/未通过/已认证/认证过期和团队态;组织切换由 Host 响应事件,应用加载与 ticket 跳转复用独立的 Application Switcher transport
|
|
48
|
+
`<uniplat-account-context>` 是 40.1 原型导航右侧的统一账户工作台组件,不渲染品牌和全局菜单。它在一个 Host 元素内包含工作台入口、账户胶囊、应用入口浮层和 6.7 企业/团队切换浮层;两个浮层互斥并绝对定位,不改变导航布局。组件根据 Host 提供的 `applicationName` 和账户 transport 自行加载当前应用对应的组织投影与企业认证状态;用户资料复用 `list_available_organizations` 顶层的 `display_name`、`avatar_url` 与 `mobile_masked`,不得再请求 `profile_summary_v2`,Host 不再组装这些展示数据。它支持无归属个人态、企业未认证/审核中/未通过/已认证/认证过期和团队态;组织切换由 Host 响应事件,应用加载与 ticket 跳转复用独立的 Application Switcher transport。选中组织时,账户胶囊和菜单资料区必须使用服务端投影中该组织的员工姓名与头像;没有选中组织或该组织没有员工身份时,回退到用户资料。账户胶囊宽度固定,胶囊内姓名超过 6 个字、组织名称超过 8 个字必须截断为省略号,完整值只放在 `title` 上,不得让长名称撑宽胶囊挤压导航左侧内容;展开菜单内仍显示完整名称。组织列表严格使用原型中的企业建筑与团队成员图标,不得替换成员工头像或组织首字。
|
|
49
49
|
|
|
50
50
|
`<uniplat-notification-center>` 是内嵌通知中心面板,复刻 AE-Enterprise-Admin 通知中心原型的两栏收件箱:面板顶栏、五类页签、列表、详情、关联资源、附件下载与“全部标已读”。**组件和 core 都不建立 WebSocket 连接**:Host 保留自己唯一的 `/api/user-realtime/ws` 连接并订阅 `notification` channel,把事件原始负载通过 `applyRealtimeEvent()` 喂给组件;`authenticate` 首帧、心跳、游标、重连和断连提示全部归 Host。组件只负责收件箱投影、增量更新和未读数,顶栏铃铛仍属 Host chrome。不得为通知新增第二条 socket 或平行实时通道。
|
|
51
51
|
|
|
@@ -439,7 +439,7 @@ npm 包名、导出类型名、Custom Element 标签、`configure()` 结构、
|
|
|
439
439
|
- Organization Selector 需测试完整列表、企业认证与团队类型样式、脱敏账户摘要与完整手机号拒绝、按名称和统一社会信用代码搜索且代码不进入 DOM、类型筛选与常显计数、“最近进入 / 全部组织”分组与默认选中、带目标名称的主按钮、无匹配与空归属状态、记住偏好、创建/进入/退出登录事件、`modal` 强制态无关闭按钮且遮罩点击与 `Escape` 都不关闭并在移除后解除 `Escape` 拦截、非法 `presentation` 与重复 ID 拒绝和普通文本插值;事件只包含稳定组织 ID 与偏好,不含姓名、手机号、组织名称或信用代码。`resolveOrganizationEntryDecision()` 需测试 0 个归属、单一归属、命中与失效的记住选择、2 个及以上的默认选中项和非法输入拒绝。
|
|
440
440
|
- Organization Multi Employee Selector 需测试部门树、员工分页和搜索、初始选择补取、跨部门按员工 ID 去重、多选上限、受保护项、确认/取消事件、独立滚动、移动视图、错误重试、身份切换清理,以及 JWT、完整手机号、身份字段和后端错误不进入 DOM、事件、URL或日志。专用 transport 必须测试每次请求重新读取 JWT、只使用 Authorization header、组织级 directory scope 和无调用方身份参数。
|
|
441
441
|
- Organization Single Employee Selector 需测试独立标签与导出、初始单个 ID 回显、新选择替换旧选择、未选时禁止确认、受保护项、标量确认 detail、拒绝多选打开参数,以及与多选组件相同的数据和认证安全边界。
|
|
442
|
-
- Account Context 需测试必填应用名、组件通过 transport
|
|
442
|
+
- Account Context 需测试必填应用名、组件通过 transport 自行加载用户资料与完整应用组织投影、无归属、企业五种认证状态和团队状态、当前组织员工身份优先及无组织用户身份回退、安全头像与加载失败回退、胶囊内姓名 6 字与组织名 8 字截断及完整 `title`、未超长时不加 `title`、工作台、账户菜单与内置入驻浮层互斥、浮层不改变导航布局、内嵌应用九宫格、创建入口直接启动内置入驻、Host 响应组织切换事件、退出和公共事件安全。专用 UniplatBase transport 还必须测试不请求 `profile_summary_v2`、从 `list_available_organizations` 顶层读取用户资料、按 `application_name` 加载投影、Open Application 的 `organization_oid` 切换、组织级应用目标 `xid` 选择、JWT 只进入 Authorization header 和 Host `setAccessToken()`、响应净化、稳定错误以及公共数据无 JWT;组件范围不得扩展为品牌或完整导航。
|
|
443
443
|
- 通知中心需测试组件注册与导出、两栏首版输出、数据驱动分类页签(`includeTypeFacets` 随收件箱请求、后端 `type_facets` 优先、无 facet 回退累积、筛选后页签不塌缩、展示名取 `notification_type_name` 且为空时回退原始 code、契约四个码不得残留内置中文名、实时新分类入目录)、未读角标与 `unread-count-change`、打开未读即标记已读、全部已读、加载更多、关联资源事件只含安全业务标识、附件经 transport 下载、Markdown 净化、`applyRealtimeEvent()` 不建立任何 WebSocket 且原地更新列表与未读数、事件无法映射时降级刷新、收件箱在途时延后 resync 不丢事件、`configure()` 之前与移除之后喂入事件无副作用、错误横幅为净化文案,以及 JWT 与后端原始正文不进入 DOM、公共事件或日志。小型通知浮层还需测试初始关闭、4 条未读投影、未读总数、严格原型结构与 SVG 图标、单条/全部已读、完整通知页意图事件只含稳定 ID、外部关闭、空态以及 Host 实时事件更新。
|
|
444
444
|
- 使用 fake timer 的测试必须恢复 timer;构造 fake WebSocket 时不要把测试凭据写入 URL。
|
|
445
445
|
- 修复竞态或生命周期问题时增加回归测试,不只验证最终 DOM。
|
package/README.md
CHANGED
|
@@ -421,6 +421,8 @@ selector.addEventListener('selection-confirmed', (event) => {
|
|
|
421
421
|
|
|
422
422
|
账户区和组织菜单中的工作台、选择器、认证状态、选中、创建及退出图标使用 40.1 原型指定的 Tabler Icons 2.47.0 原始 SVG 路径;组织列表左侧使用原型中的企业建筑或团队成员图标。组件将这些原型资源打入独立运行时,不依赖 Host 的图标字体或全局样式。
|
|
423
423
|
|
|
424
|
+
账户胶囊宽度固定:胶囊内姓名超过 6 个字、当前组织名称超过 8 个字会截断为省略号,完整值只放在 `title` 上,长名称不会撑宽胶囊挤压导航左侧内容;展开后的菜单仍显示完整名称。
|
|
425
|
+
|
|
424
426
|
```js
|
|
425
427
|
import {
|
|
426
428
|
createUniplatBaseAccountContextTransport,
|
package/package.json
CHANGED
|
@@ -17,6 +17,10 @@ import type { UniplatUserMenu, UserMenuConfig } from './user-menu'
|
|
|
17
17
|
|
|
18
18
|
const INTERNAL_APPLICATION_SWITCHER_TAG = 'uniplat-internal-application-switcher'
|
|
19
19
|
|
|
20
|
+
// 账户胶囊固定宽度,超出的姓名与组织名在胶囊内截断,完整值只放在 title 里。
|
|
21
|
+
const CAPSULE_DISPLAY_NAME_MAX_CHARS = 6
|
|
22
|
+
const CAPSULE_ORGANIZATION_NAME_MAX_CHARS = 8
|
|
23
|
+
|
|
20
24
|
if (
|
|
21
25
|
typeof customElements !== 'undefined' &&
|
|
22
26
|
!customElements.get(INTERNAL_APPLICATION_SWITCHER_TAG)
|
|
@@ -328,16 +332,19 @@ export class UniplatAccountContext extends LitElement {
|
|
|
328
332
|
display: none;
|
|
329
333
|
}
|
|
330
334
|
|
|
335
|
+
/* 胶囊宽度固定,姓名与组织名再长也不挤压导航左侧内容。 */
|
|
331
336
|
.copy {
|
|
332
337
|
display: flex;
|
|
338
|
+
width: 96px;
|
|
333
339
|
min-width: 0;
|
|
340
|
+
flex: none;
|
|
334
341
|
flex-direction: column;
|
|
335
342
|
line-height: 1.3;
|
|
336
343
|
}
|
|
337
344
|
|
|
338
345
|
.display-name {
|
|
339
346
|
overflow: hidden;
|
|
340
|
-
max-width:
|
|
347
|
+
max-width: 100%;
|
|
341
348
|
font-size: 12.5px;
|
|
342
349
|
font-weight: 700;
|
|
343
350
|
text-overflow: ellipsis;
|
|
@@ -348,7 +355,7 @@ export class UniplatAccountContext extends LitElement {
|
|
|
348
355
|
display: inline-flex;
|
|
349
356
|
align-items: center;
|
|
350
357
|
gap: 4px;
|
|
351
|
-
max-width:
|
|
358
|
+
max-width: 100%;
|
|
352
359
|
margin-top: 1px;
|
|
353
360
|
}
|
|
354
361
|
|
|
@@ -912,7 +919,12 @@ export class UniplatAccountContext extends LitElement {
|
|
|
912
919
|
}
|
|
913
920
|
</span>
|
|
914
921
|
<span class="copy">
|
|
915
|
-
<span
|
|
922
|
+
<span
|
|
923
|
+
class="display-name"
|
|
924
|
+
part="display-name"
|
|
925
|
+
title=${capsuleTitle(viewModel.displayName, CAPSULE_DISPLAY_NAME_MAX_CHARS)}
|
|
926
|
+
>${truncateCapsuleText(viewModel.displayName, CAPSULE_DISPLAY_NAME_MAX_CHARS)}</span
|
|
927
|
+
>
|
|
916
928
|
${
|
|
917
929
|
organization
|
|
918
930
|
? this.renderOrganizationLine(organization, viewModel.showVerificationStatus)
|
|
@@ -995,7 +1007,8 @@ export class UniplatAccountContext extends LitElement {
|
|
|
995
1007
|
<span
|
|
996
1008
|
class=${`organization-name${status === 'verified' || status === 'team' ? ' normal' : ''}`}
|
|
997
1009
|
part="organization-name"
|
|
998
|
-
|
|
1010
|
+
title=${capsuleTitle(organization.name, CAPSULE_ORGANIZATION_NAME_MAX_CHARS)}
|
|
1011
|
+
>${truncateCapsuleText(organization.name, CAPSULE_ORGANIZATION_NAME_MAX_CHARS)}</span
|
|
999
1012
|
>
|
|
1000
1013
|
${
|
|
1001
1014
|
status
|
|
@@ -1474,6 +1487,15 @@ function normalizeOptionalText(value: unknown, maxLength: number): string {
|
|
|
1474
1487
|
return normalized
|
|
1475
1488
|
}
|
|
1476
1489
|
|
|
1490
|
+
function truncateCapsuleText(value: string, maxChars: number): string {
|
|
1491
|
+
const characters = [...value]
|
|
1492
|
+
return characters.length > maxChars ? `${characters.slice(0, maxChars).join('')}…` : value
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
function capsuleTitle(value: string, maxChars: number): string | typeof nothing {
|
|
1496
|
+
return [...value].length > maxChars ? value : nothing
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1477
1499
|
function organizationStatus(
|
|
1478
1500
|
organization: ResolvedAccountContextOrganization,
|
|
1479
1501
|
): EnterpriseVerificationStatus | 'team' {
|
|
@@ -273,7 +273,9 @@ describe('<uniplat-account-context>', () => {
|
|
|
273
273
|
await settle(context)
|
|
274
274
|
|
|
275
275
|
expect(context.shadowRoot?.textContent).toContain('工作台')
|
|
276
|
-
|
|
276
|
+
const capsuleOrganization = context.shadowRoot?.querySelector('.organization-name')
|
|
277
|
+
expect(capsuleOrganization?.textContent?.trim()).toBe('北京星河科技有限…')
|
|
278
|
+
expect(capsuleOrganization?.getAttribute('title')).toBe('北京星河科技有限公司')
|
|
277
279
|
const statusIcon = context.shadowRoot?.querySelector(`.status-icon.${cssClass}`)
|
|
278
280
|
expect(statusIcon?.getAttribute('aria-label')).toBe(label)
|
|
279
281
|
expect(statusIcon?.querySelector('svg')?.dataset.prototypeIcon).toBe(iconName)
|
|
@@ -797,6 +799,49 @@ describe('<uniplat-account-context>', () => {
|
|
|
797
799
|
expect(image?.hidden).toBe(false)
|
|
798
800
|
})
|
|
799
801
|
|
|
802
|
+
it('truncates long capsule names so the navigation width stays fixed', async () => {
|
|
803
|
+
const context = document.createElement(ACCOUNT_CONTEXT_TAG)
|
|
804
|
+
context.configure({
|
|
805
|
+
applicationName: APPLICATION_NAME,
|
|
806
|
+
displayName: '欧阳夏尔泽辉安',
|
|
807
|
+
organization: {
|
|
808
|
+
id: 'enterprise-huaqin',
|
|
809
|
+
name: '北京华勤百业技术服务有限公司',
|
|
810
|
+
type: 'enterprise',
|
|
811
|
+
applicationNames: [APPLICATION_NAME],
|
|
812
|
+
verificationStatus: 'verified',
|
|
813
|
+
},
|
|
814
|
+
})
|
|
815
|
+
document.body.append(context)
|
|
816
|
+
await settle(context)
|
|
817
|
+
|
|
818
|
+
const capsuleName = context.shadowRoot?.querySelector('.display-name')
|
|
819
|
+
const capsuleOrganization = context.shadowRoot?.querySelector('.organization-name')
|
|
820
|
+
expect(capsuleName?.textContent?.trim()).toBe('欧阳夏尔泽辉…')
|
|
821
|
+
expect(capsuleName?.getAttribute('title')).toBe('欧阳夏尔泽辉安')
|
|
822
|
+
expect(capsuleOrganization?.textContent?.trim()).toBe('北京华勤百业技术…')
|
|
823
|
+
expect(capsuleOrganization?.getAttribute('title')).toBe('北京华勤百业技术服务有限公司')
|
|
824
|
+
|
|
825
|
+
context.configure({
|
|
826
|
+
applicationName: APPLICATION_NAME,
|
|
827
|
+
displayName: '高高高',
|
|
828
|
+
organization: {
|
|
829
|
+
id: 'team-small',
|
|
830
|
+
name: '小团队',
|
|
831
|
+
type: 'team',
|
|
832
|
+
applicationNames: [APPLICATION_NAME],
|
|
833
|
+
},
|
|
834
|
+
})
|
|
835
|
+
await settle(context)
|
|
836
|
+
|
|
837
|
+
const shortName = context.shadowRoot?.querySelector('.display-name')
|
|
838
|
+
const shortOrganization = context.shadowRoot?.querySelector('.organization-name')
|
|
839
|
+
expect(shortName?.textContent?.trim()).toBe('高高高')
|
|
840
|
+
expect(shortName?.hasAttribute('title')).toBe(false)
|
|
841
|
+
expect(shortOrganization?.textContent?.trim()).toBe('小团队')
|
|
842
|
+
expect(shortOrganization?.hasAttribute('title')).toBe(false)
|
|
843
|
+
})
|
|
844
|
+
|
|
800
845
|
it('requires enterprise status, rejects raw mobile numbers and renders labels as text', async () => {
|
|
801
846
|
const context = document.createElement(ACCOUNT_CONTEXT_TAG)
|
|
802
847
|
expect(() =>
|
|
@@ -826,6 +871,8 @@ describe('<uniplat-account-context>', () => {
|
|
|
826
871
|
document.body.append(context)
|
|
827
872
|
await settle(context)
|
|
828
873
|
expect(context.shadowRoot?.querySelector('script')).toBeNull()
|
|
829
|
-
|
|
874
|
+
const capsuleName = context.shadowRoot?.querySelector('.display-name')
|
|
875
|
+
expect(capsuleName?.textContent?.trim()).toBe('<scrip…')
|
|
876
|
+
expect(capsuleName?.getAttribute('title')).toBe('<script>unsafe()</script>')
|
|
830
877
|
})
|
|
831
878
|
})
|
|
@@ -38,7 +38,7 @@ HEAD = 7d2f9bb
|
|
|
38
38
|
|
|
39
39
|
| 位置 | npm 名称 | 当前本地版本 | 说明 |
|
|
40
40
|
| ------------------------- | -------------------------------------- | -----------: | --------------------------------------- |
|
|
41
|
-
| 根目录 | `@csntgao/uni-base` | `0.1.4` | 当前公开发布入口;npmjs
|
|
41
|
+
| 根目录 | `@csntgao/uni-base` | `0.1.4` | 当前公开发布入口;npmjs 已发布此版本 |
|
|
42
42
|
| `packages/core` | `@uniplat/ai-employee-client` | `0.14.0` | UI 无关的 HTTP/WebSocket/Core 状态机 |
|
|
43
43
|
| `packages/web-components` | `@uniplat/ai-employee-web-components` | `0.24.0` | Lit Web Components 与独立浏览器 runtime |
|
|
44
44
|
| `examples/vanilla` | `@uniplat/ai-employee-vanilla-example` | 私有示例 | 必须消费 workspace 包的构建产物 |
|
|
@@ -322,27 +322,31 @@ https://registry.npmjs.org/
|
|
|
322
322
|
当前远端状态:
|
|
323
323
|
|
|
324
324
|
```text
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
npm whoami csntgao(已登录)
|
|
326
|
+
@csntgao/uni-base 0.1.4 已发布并回读校验
|
|
327
|
+
@uniplat/ai-employee-client 未发布,PUT 返回 404(无 scope 创建权限)
|
|
328
|
+
@uniplat/ai-employee-web-components 未发布,同上
|
|
328
329
|
```
|
|
329
330
|
|
|
330
|
-
|
|
331
|
+
`@csntgao/uni-base@0.1.4` 的远端 shasum 为 `1ec9b946789b1840cd418af26ab1621ea1c8af96`,
|
|
332
|
+
与本地打包一致。注意该包没有 `main`/`exports`/`files`,发布内容是 91 个源码文件,
|
|
333
|
+
不是可直接 `import` 的库;调用方仍应使用 runtime 或 workspace 包。
|
|
331
334
|
|
|
332
|
-
|
|
333
|
-
npm
|
|
334
|
-
npm whoami
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
登录成功后必须重新查询远端版本;确认 `0.1.4` 不存在,再从已提交且干净的工作树发布并回读:
|
|
335
|
+
发布需要浏览器 2FA。本机 shell 不是交互终端,直接 `npm publish` 会以 `EOTP` 退出;
|
|
336
|
+
用伪终端包一层即可让 npm 停下来等浏览器授权:
|
|
338
337
|
|
|
339
338
|
```bash
|
|
340
|
-
|
|
341
|
-
npm publish --access public
|
|
342
|
-
npm view @csntgao/uni-base@0.1.4 version
|
|
339
|
+
script -q /dev/null npm publish <绝对路径或 tarball> --access public
|
|
343
340
|
```
|
|
344
341
|
|
|
345
|
-
|
|
342
|
+
注意两个陷阱:`npm publish packages/core` 会被当成 git 仓库简写;`npm publish <目录>`
|
|
343
|
+
不会改写 `workspace:*`,发布 web-components 必须使用 `pnpm pack` 生成的 tarball。
|
|
344
|
+
|
|
345
|
+
两个 `@uniplat/*` 包仍未发布,属外部阻塞。`npm access list packages @uniplat` 只显示
|
|
346
|
+
`@uniplat/html5-qrcode: read-write`,且该包 maintainer 是 `ytl003
|
|
347
|
+
<yanghua19970726@163.com>`,`npm org ls uniplat` 无输出,说明当前账号在该 scope 下
|
|
348
|
+
只有单包权限、没有创建新包的权限。需要 scope 所有者发布,或把 `@uniplat` 作为组织把
|
|
349
|
+
`csntgao` 加入并授予创建 public package 的权限;不要通过重命名内部包规避公开契约。
|
|
346
350
|
|
|
347
351
|
## 9. 发布流程
|
|
348
352
|
|
|
@@ -388,7 +392,7 @@ Enterprise Admin:/Users/gaostudio/ae_design/实现/ae-enterprise-admin
|
|
|
388
392
|
1. 完整阅读 `AGENTS.md`;
|
|
389
393
|
2. 确认 Git 分支、工作树和最新提交;
|
|
390
394
|
3. 根据用户当前任务定位对应组件及测试,不要顺手改公开契约;
|
|
391
|
-
4. 若继续 npm
|
|
395
|
+
4. 若继续 npm 发布,两个 `@uniplat/*` 包仍缺 scope 创建权限,见第 8.2 节;
|
|
392
396
|
5. 若继续官网登录联调,重点确认 `setAccessToken()` 完成后是否调用 Account Context `refresh()`;
|
|
393
397
|
6. 所有认证问题排查只查看安全状态码和白名单错误码,不复制 JWT;
|
|
394
398
|
7. 代码修改完成后走完整验证、打包、版本、提交、发布和远端回读流程。
|