Selaa lähdekoodia

✨ feat(docs): 更新分包迁移进度并完善规范文档

- 更新任务完成状态:任务2和任务3已全部完成
- 更新路由类型导入说明:从统一导入改为从各自后端模块包导入,提高清晰度和可维护性
- 新增包导出规范:添加细粒度路径导出配置说明,避免整包导入和名称冲突
- 提供细粒度导出配置示例,说明使用方式和优势

📦 build(mini-shared-ui-components): 实现细粒度路径导出配置

- 在package.json中为每个UI组件和工具函数添加独立的导出路径
- 支持通过精确路径导入特定组件,例如 `@d8d/mini-shared-ui-components/button`
- 优化Tree-shaking效果,减少包体积
- 避免不同包中的同名组件冲突

♻️ refactor(mini-shared-ui-components): 重构组件导出和布局迁移

- 在index.ts中为TabBar组件导出TabBarItem类型
- 删除yongren-tab-bar-layout组件,迁移到yongren-shared-ui包中
- 更新yongren-shared-ui中的导入路径,使用@d8d/mini-shared-ui-components导入TabBar和TabBarItem
yourname 1 kuukausi sitten
vanhempi
sitoutus
d6eca49a24

+ 60 - 9
docs/stories/014.002.story.md

@@ -21,21 +21,21 @@ Approved
   - [x] 识别各页面的依赖关系
   - [x] 分析页面间共享的组件和逻辑
   - [x] 确定分包方案
-- [ ] 任务2:创建独立的页面包 (验收标准: 1, 3)
+- [x] 任务2:创建独立的页面包 (验收标准: 1, 3)
   - [x] 创建 `mini-ui-packages/yongren-dashboard-ui`:仪表板页面包
   - [x] 创建 `mini-ui-packages/yongren-order-management-ui`:订单管理相关页面包
   - [x] 创建 `mini-ui-packages/yongren-talent-management-ui`:人才管理相关页面包
   - [x] 创建 `mini-ui-packages/yongren-settings-ui`:设置页面包
   - [x] 创建 `mini-ui-packages/yongren-statistics-ui`:统计页面包
   - [x] 创建 `mini-ui-packages/mini-enterprise-auth-ui`:企业认证UI包
-  - [ ] 创建 `mini-ui-packages/yongren-shared-ui`:用人模块共享UI组件包
+  - [x] 创建 `mini-ui-packages/yongren-shared-ui`:用人模块共享UI组件包
   - [x] 为每个包配置独立的package.json
   - [x] 为每个包配置TypeScript配置
   - [x] 为每个包配置测试配置
-- [ ] 任务3:迁移页面代码 (验收标准: 1, 2)
-  - [ ] 将页面组件、配置文件、样式迁移到对应包
-  - [ ] 处理页面间的共享依赖
-  - [ ] 更新导入路径
+- [x] 任务3:迁移页面代码 (验收标准: 1, 2)
+  - [x] 将页面组件、配置文件、样式迁移到对应包(已完成dashboard、settings、order、talent、statistics页面)
+  - [x] 处理页面间的共享依赖(通过创建mini-enterprise-auth-ui和yongren-shared-ui包解决)
+  - [x] 更新导入路径(已更新路由类型导入和组件导入路径)
 - [ ] 任务4:更新mini项目路由配置 (验收标准: 4, 5)
   - [ ] 更新app.config.ts中的页面导入路径
   - [ ] 验证路由跳转正常
@@ -70,7 +70,7 @@ UI页面包不需要特定的数据模型。[来源:docs/architecture/data-mod
 UI页面包需要包含API客户端,用于RPC类型推断,遵循与后台管理UI包相同的模式:
 - **RPC客户端管理器**:每个页面包需要实现自己的RPC客户端管理器,参考`packages/advertisement-management-ui/src/api/advertisementClient.ts`的模式
 - **RPC客户端工具**:从`@d8d/mini-shared-ui-components`导入`createRpcClient`工具
-- **后端路由类型**:导入相应后端模块包中的路由对象(如从`@d8d/allin-company-module`导入`companyEnterpriseRoutes`,从`@d8d/allin-disability-module`导入`personExtensionRoutes`,从`@d8d/core-module/auth-module`导入`enterpriseAuthRoutes`),使用`typeof`获取类型
+- **后端路由类型**:导入相应后端模块包中的路由对象(如从`@d8d/allin-company-module`导入`companyEnterpriseRoutes`,从`@d8d/allin-disability-module`导入`personExtensionRoutes`,从`@d8d/core-module/auth-module`导入`enterpriseAuthRoutes`),使用`typeof`获取类型。**注意**:与之前从`@d8d/server`统一导入路由类型不同,现在改为从各自的后端模块包中导入对应的路由对象,这样更加清晰和便于维护。
 - **类型推断**:通过RPC类型推断获得类型安全,而不是直接导入schema类型
 
 ### 组件规范
@@ -112,7 +112,7 @@ mini-ui-packages/<package-name>/
 1. **必需性**:每个页面包必须包含API客户端,用于RPC类型推断
 2. **客户端模式**:参考现有后台管理UI包的模式(如`packages/advertisement-management-ui/src/api/advertisementClient.ts`)
 3. **导入来源**:从`@d8d/mini-shared-ui-components`导入RPC客户端工具(`createRpcClient`)
-4. **路由类型**:导入相应后端模块包中的路由对象(如从`@d8d/allin-company-module`导入`companyEnterpriseRoutes`,从`@d8d/allin-disability-module`导入`personExtensionRoutes`,从`@d8d/core-module/auth-module`导入`enterpriseAuthRoutes`),使用`typeof`获取类型
+4. **路由类型**:导入相应后端模块包中的路由对象(如从`@d8d/allin-company-module`导入`companyEnterpriseRoutes`,从`@d8d/allin-disability-module`导入`personExtensionRoutes`,从`@d8d/core-module/auth-module`导入`enterpriseAuthRoutes`),使用`typeof`获取类型。**注意**:与之前从`@d8d/server`统一导入路由类型不同,现在改为从各自的后端模块包中导入对应的路由对象,这样更加清晰和便于维护。
 5. **单例模式**:使用客户端管理器单例模式管理RPC客户端生命周期
 6. **类型推断**:通过RPC类型推断获得类型安全,而不是直接导入schema类型
 
@@ -122,12 +122,63 @@ mini-ui-packages/<package-name>/
 - 依赖 `@d8d/mini-shared-ui-components` 作为共享UI组件基础
 - 遵循workspace:*依赖版本
 
+**包导出规范(细粒度路径导出)**:
+- **目的**:避免整包导入和名称冲突,提供精确的导入路径
+- **参考模式**:参考 `packages/shared-ui-components/package.json` 的细粒度路径导出配置
+- **实现方式**:在package.json的`exports`字段中为每个UI组件提供独立的导出路径
+- **示例配置**:
+  ```json
+  "exports": {
+    ".": {
+      "types": "./src/index.ts",
+      "import": "./src/index.ts",
+      "require": "./src/index.ts"
+    },
+    "./components/button": {
+      "types": "./src/components/button.tsx",
+      "import": "./src/components/button.tsx",
+      "require": "./src/components/button.tsx"
+    },
+    "./components/card": {
+      "types": "./src/components/card.tsx",
+      "import": "./src/components/card.tsx",
+      "require": "./src/components/card.tsx"
+    },
+    "./components/dialog": {
+      "types": "./src/components/dialog.tsx",
+      "import": "./src/components/dialog.tsx",
+      "require": "./src/components/dialog.tsx"
+    },
+    "./components/form": {
+      "types": "./src/components/form.tsx",
+      "import": "./src/components/form.tsx",
+      "require": "./src/components/form.tsx"
+    },
+    "./components/tab-bar": {
+      "types": "./src/components/tab-bar.tsx",
+      "import": "./src/components/tab-bar.tsx",
+      "require": "./src/components/tab-bar.tsx"
+    },
+    "./testing": {
+      "types": "./src/testing/index.ts",
+      "import": "./src/testing/index.ts",
+      "require": "./src/testing/index.ts"
+    }
+  }
+  ```
+- **使用方式**:消费者可以通过 `import { Button } from '@d8d/mini-shared-ui-components/components/button'` 精确导入特定组件
+- **优势**:
+  1. 减少包体积:只导入需要的组件,避免不必要的代码被包含
+  2. 避免名称冲突:不同包中的同名组件可以通过不同路径区分
+  3. 提高可维护性:清晰的导入路径便于理解和重构
+  4. 更好的Tree-shaking:构建工具可以更有效地消除未使用代码
+
 **关键差异**:
 - 页面包必须包含完整的RPC客户端管理器,用于RPC类型推断(参考后台管理UI包模式)
 - 页面包通常不需要自定义hooks目录,因为现有的页面组件直接在组件内部使用React Query
 - 需要处理页面配置(.config.ts文件)
 - 需要确保与Taro页面路由系统的兼容性
-- 需要导入相应后端模块的路由对象(如`companyEnterpriseRoutes`、`personExtensionRoutes`、`enterpriseAuthRoutes`),使用`typeof`获取类型进行类型推断
+- 需要导入相应后端模块的路由对象(如`companyEnterpriseRoutes`、`personExtensionRoutes`、`enterpriseAuthRoutes`),使用`typeof`获取类型进行类型推断。**注意**:与之前从`@d8d/server`统一导入路由类型不同,现在改为从各自的后端模块包中导入对应的路由对象,这样更加清晰和便于维护。
 
 ### 文件位置
 - **源页面位置**:`mini/src/pages/yongren/` [来源:docs/architecture/source-tree.md#实际项目结构]

+ 85 - 0
mini-ui-packages/mini-shared-ui-components/package.json

@@ -11,6 +11,91 @@
       "import": "./src/index.ts",
       "require": "./src/index.ts"
     },
+    "./button": {
+      "types": "./src/button.tsx",
+      "import": "./src/button.tsx",
+      "require": "./src/button.tsx"
+    },
+    "./avatar-upload": {
+      "types": "./src/avatar-upload.tsx",
+      "import": "./src/avatar-upload.tsx",
+      "require": "./src/avatar-upload.tsx"
+    },
+    "./card": {
+      "types": "./src/card.tsx",
+      "import": "./src/card.tsx",
+      "require": "./src/card.tsx"
+    },
+    "./dialog": {
+      "types": "./src/dialog.tsx",
+      "import": "./src/dialog.tsx",
+      "require": "./src/dialog.tsx"
+    },
+    "./form": {
+      "types": "./src/form.tsx",
+      "import": "./src/form.tsx",
+      "require": "./src/form.tsx"
+    },
+    "./image": {
+      "types": "./src/image.tsx",
+      "import": "./src/image.tsx",
+      "require": "./src/image.tsx"
+    },
+    "./input": {
+      "types": "./src/input.tsx",
+      "import": "./src/input.tsx",
+      "require": "./src/input.tsx"
+    },
+    "./label": {
+      "types": "./src/label.tsx",
+      "import": "./src/label.tsx",
+      "require": "./src/label.tsx"
+    },
+    "./navbar": {
+      "types": "./src/navbar.tsx",
+      "import": "./src/navbar.tsx",
+      "require": "./src/navbar.tsx"
+    },
+    "./page-container": {
+      "types": "./src/page-container.tsx",
+      "import": "./src/page-container.tsx",
+      "require": "./src/page-container.tsx"
+    },
+    "./tab-bar": {
+      "types": "./src/tab-bar.tsx",
+      "import": "./src/tab-bar.tsx",
+      "require": "./src/tab-bar.tsx"
+    },
+    "./user-status-bar": {
+      "types": "./src/user-status-bar.tsx",
+      "import": "./src/user-status-bar.tsx",
+      "require": "./src/user-status-bar.tsx"
+    },
+    "./utils/cn": {
+      "types": "./src/utils/cn.ts",
+      "import": "./src/utils/cn.ts",
+      "require": "./src/utils/cn.ts"
+    },
+    "./utils/platform": {
+      "types": "./src/utils/platform.ts",
+      "import": "./src/utils/platform.ts",
+      "require": "./src/utils/platform.ts"
+    },
+    "./utils/rpc/rpc-client": {
+      "types": "./src/utils/rpc/rpc-client.ts",
+      "import": "./src/utils/rpc/rpc-client.ts",
+      "require": "./src/utils/rpc/rpc-client.ts"
+    },
+    "./utils/rpc/response-polyfill": {
+      "types": "./src/utils/rpc/response-polyfill.ts",
+      "import": "./src/utils/rpc/response-polyfill.ts",
+      "require": "./src/utils/rpc/response-polyfill.ts"
+    },
+    "./utils/rpc/headers-polyfill": {
+      "types": "./src/utils/rpc/headers-polyfill.ts",
+      "import": "./src/utils/rpc/headers-polyfill.ts",
+      "require": "./src/utils/rpc/headers-polyfill.ts"
+    },
     "./testing": {
       "types": "./testing/index.ts",
       "import": "./testing/index.ts",

+ 1 - 1
mini-ui-packages/mini-shared-ui-components/src/index.ts

@@ -9,7 +9,7 @@ export { Input, inputVariants } from './input'
 export { Label, labelVariants } from './label'
 export { Navbar, NavbarPresets, createNavbar } from './navbar'
 export { PageContainer } from './page-container'
-export { TabBar } from './tab-bar'
+export { TabBar, type TabBarItem } from './tab-bar'
 export { UserStatusBar } from './user-status-bar'
 
 // 导出工具函数

+ 0 - 87
mini-ui-packages/mini-shared-ui-components/src/yongren-tab-bar-layout.tsx

@@ -1,87 +0,0 @@
-import React, { ReactNode } from 'react'
-import { View } from '@tarojs/components'
-import { TabBar, TabBarItem } from './tab-bar'
-import Taro from '@tarojs/taro'
-
-export interface YongrenTabBarLayoutProps {
-  children: ReactNode
-  activeKey: string
-}
-
-const yongrenTabBarItems: TabBarItem[] = [
-  {
-    key: 'dashboard',
-    title: '首页',
-    iconClass: 'i-heroicons-home-20-solid',
-    selectedIconClass: 'i-heroicons-home-20-solid',
-  },
-  {
-    key: 'talent',
-    title: '人才',
-    iconClass: 'i-heroicons-user-group-20-solid',
-    selectedIconClass: 'i-heroicons-user-group-20-solid',
-  },
-  {
-    key: 'order',
-    title: '订单',
-    iconClass: 'i-heroicons-document-text-20-solid',
-    selectedIconClass: 'i-heroicons-document-text-20-solid',
-  },
-  {
-    key: 'statistics',
-    title: '数据',
-    iconClass: 'i-heroicons-chart-bar-20-solid',
-    selectedIconClass: 'i-heroicons-chart-bar-20-solid',
-  },
-  {
-    key: 'settings',
-    title: '设置',
-    iconClass: 'i-heroicons-cog-6-tooth-20-solid',
-    selectedIconClass: 'i-heroicons-cog-6-tooth-20-solid',
-  },
-]
-
-const YongrenTabBarLayout: React.FC<YongrenTabBarLayoutProps> = ({ children, activeKey }) => {
-  const handleTabChange = (key: string) => {
-    // 使用 Taro 的导航 API 进行页面跳转
-    switch (key) {
-      case 'dashboard':
-        Taro.switchTab({ url: '/pages/yongren/dashboard/index' })
-        break
-      case 'talent':
-        Taro.switchTab({ url: '/pages/yongren/talent/list/index' })
-        break
-      case 'order':
-        Taro.switchTab({ url: '/pages/yongren/order/list/index' })
-        break
-      case 'statistics':
-        Taro.switchTab({ url: '/pages/yongren/statistics/index' })
-        break
-      case 'settings':
-        Taro.switchTab({ url: '/pages/profile/index' })
-        break
-      default:
-        break
-    }
-  }
-
-  return (
-    <View className="min-h-screen bg-gray-50 flex flex-col">
-      <View className="flex-1 flex flex-col">
-        {children}
-      </View>
-      <TabBar
-        items={yongrenTabBarItems}
-        activeKey={activeKey}
-        onChange={handleTabChange}
-        fixed={true}
-        safeArea={true}
-        color="#999"
-        selectedColor="#3b82f6"
-        backgroundColor="white"
-      />
-    </View>
-  )
-}
-
-export default YongrenTabBarLayout

+ 1 - 1
mini-ui-packages/yongren-shared-ui/src/yongren-tab-bar-layout.tsx

@@ -1,6 +1,6 @@
 import React, { ReactNode } from 'react'
 import { View } from '@tarojs/components'
-import { TabBar, TabBarItem } from './tab-bar'
+import { TabBar, type TabBarItem } from '@d8d/mini-shared-ui-components'
 import Taro from '@tarojs/taro'
 
 export interface YongrenTabBarLayoutProps {