Просмотр исходного кода

📝 docs(architecture): add Navbar and Dialog style specifications

- add Navbar navigation bar style specifications including height layout, color system, preset variants and platform adaptation
- add Dialog component style specifications including basic styles, component structure and preset variants
- update migration guide with Navbar and Dialog implementation examples

✨ feat(passengers): implement style specifications for Navbar and Dialog

- apply NavbarPresets.primary style to passengers page navigation bar
- enhance delete confirmation dialog with clearer message and cancel button
- update detail dialog with brand color for confirm button
- adjust DialogFooter layout with gap-4 spacing
- set DialogTitle font style according to specifications

♻️ refactor(ui): adjust component styles to meet specifications

- update Navbar primary preset to use bg-primary instead of bg-blue-500
- remove default margin-top from Button component
- delete passengers.config.ts as navigation is now handled by Navbar component
- update button className in migration guide examples to use bg-primary
- adjust dialog styles in passengers page to match specifications
yourname 3 месяцев назад
Родитель
Сommit
e41c3f742c

+ 293 - 2
docs/architecture/mini-demo-migration-guide.md

@@ -91,7 +91,7 @@
 // mini/src/pages/home/index.tsx
 // mini/src/pages/home/index.tsx
 <View className="p-5 bg-white">
 <View className="p-5 bg-white">
   <Text className="text-[32rpx] font-bold text-gray-900">标题</Text>
   <Text className="text-[32rpx] font-bold text-gray-900">标题</Text>
-  <Button className="bg-blue-500 text-white rounded-[8rpx] px-10 py-5">
+  <Button className="bg-primary text-white rounded-[8rpx] px-10 py-5">
     按钮
     按钮
   </Button>
   </Button>
 </View>
 </View>
@@ -263,7 +263,7 @@ export default function HomePage() {
 
 
       {/* 查询按钮 */}
       {/* 查询按钮 */}
       <Button
       <Button
-        className="w-full bg-blue-500 text-white py-3 rounded-lg mt-6"
+        className="w-full bg-primary text-white py-3 rounded-lg mt-6"
         onClick={handleSearch}
         onClick={handleSearch}
         disabled={!startLocation || !endLocation}
         disabled={!startLocation || !endLocation}
       >
       >
@@ -930,6 +930,297 @@ module.exports = {
 - [ ] 按钮交互效果相同
 - [ ] 按钮交互效果相同
 - [ ] 包车主题效果一致
 - [ ] 包车主题效果一致
 
 
+## Navbar 导航栏样式规范
+
+### 基础样式定义
+
+#### 高度和布局
+```css
+/* 导航栏总高度计算 */
+--navbar-height: 44px
+--status-bar-height: 系统状态栏高度
+--total-height: status-bar-height + navbar-height
+```
+
+#### 颜色系统
+```css
+/* 背景色 */
+--navbar-bg-default: #ffffff
+--navbar-bg-dark: #1a1a1a
+--navbar-bg-primary: #4A90C2
+--navbar-bg-transparent: transparent
+
+/* 文字色 */
+--navbar-text-default: #333333
+--navbar-text-light: #ffffff
+--navbar-text-primary: #ffffff
+```
+
+### 预设样式变体
+
+#### 默认导航栏
+```tsx
+// 样式配置
+{
+  backgroundColor: 'bg-white',
+  textColor: 'text-gray-900',
+  border: true,
+}
+
+// Tailwind 类名
+className="bg-white text-gray-900 border-b border-gray-200"
+```
+
+#### 深色导航栏
+```tsx
+// 样式配置
+{
+  backgroundColor: 'bg-gray-900',
+  textColor: 'text-white',
+  border: true,
+}
+
+// Tailwind 类名
+className="bg-gray-900 text-white border-b border-gray-700"
+```
+
+#### 透明导航栏
+```tsx
+// 样式配置
+{
+  backgroundColor: 'bg-transparent',
+  textColor: 'text-white',
+  border: false,
+}
+
+// Tailwind 类名
+className="bg-transparent text-white"
+```
+
+#### 主色调导航栏
+```tsx
+// 样式配置
+{
+  backgroundColor: 'bg-primary',
+  textColor: 'text-white',
+  border: false,
+}
+
+// Tailwind 类名
+className="bg-primary text-white"
+```
+
+### 平台适配规范
+
+#### 微信小程序
+```tsx
+// 高度计算
+const NAVBAR_HEIGHT = 44
+const STATUS_BAR_HEIGHT = systemInfo.statusBarHeight || 0
+const TOTAL_HEIGHT = STATUS_BAR_HEIGHT + NAVBAR_HEIGHT
+
+// 胶囊按钮避让
+const menuButtonInfo = Taro.getMenuButtonBoundingClientRect()
+const rightPosition = systemInfo.screenWidth - menuButtonInfo.left + 10
+
+// 标题宽度限制
+const titleMaxWidth = `calc(100% - ${rightPosition}px - 60px - 60px)`
+```
+
+#### H5 环境
+```tsx
+// 标准布局
+left: '12px'  // left-3
+right: '12px' // right-3
+```
+
+### 使用示例
+
+#### 基础导航栏
+```tsx
+<Navbar
+  title="页面标题"
+  leftIcon="i-heroicons-chevron-left-20-solid"
+  rightText="完成"
+  onClickLeft={() => Taro.navigateBack()}
+  onClickRight={handleComplete}
+/>
+```
+
+#### 自定义样式导航栏
+```tsx
+<Navbar
+  title="个人中心"
+  backgroundColor="bg-gradient-to-r from-blue-500 to-purple-600"
+  textColor="text-white"
+  border={false}
+  rightIcon="i-heroicons-cog-6-tooth-20-solid"
+  onClickRight={handleSettings}
+/>
+```
+
+## Dialog 对话框样式规范
+
+### 基础样式定义
+
+#### 遮罩层
+```tsx
+// 遮罩样式
+className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
+```
+
+#### 对话框容器
+```tsx
+// 对话框基础样式
+className="relative bg-white rounded-lg shadow-lg max-w-md w-full mx-4"
+
+// 阴影系统
+--dialog-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)
+```
+
+### 组件结构样式
+
+#### DialogContent 内容区域
+```tsx
+// 基础内边距
+className="p-6"
+
+// 自定义样式
+className={cn("p-6", className)}
+```
+
+#### DialogHeader 头部区域
+```tsx
+// 底部外边距
+className="mb-4"
+
+// 自定义样式
+className={cn("mb-4", className)}
+```
+
+#### DialogTitle 标题
+```tsx
+// 标题样式
+className="text-lg font-semibold text-gray-900"
+
+// 自定义样式
+className={cn("text-lg font-semibold text-gray-900", className)}
+```
+
+#### DialogFooter 底部区域
+```tsx
+// 按钮布局
+className="flex justify-end space-x-2"
+
+// 自定义样式
+className={cn("flex justify-end space-x-2", className)}
+```
+
+### 预设变体样式
+
+#### 确认对话框
+```tsx
+<Dialog open={open} onOpenChange={setOpen}>
+  <DialogContent>
+    <DialogHeader>
+      <DialogTitle>确认操作</DialogTitle>
+    </DialogHeader>
+    <Text className="text-gray-600 mb-6">
+      确定要执行此操作吗?
+    </Text>
+    <DialogFooter>
+      <Button variant="outline" onClick={() => setOpen(false)}>
+        取消
+      </Button>
+      <Button onClick={handleConfirm}>
+        确认
+      </Button>
+    </DialogFooter>
+  </DialogContent>
+</Dialog>
+```
+
+#### 表单对话框
+```tsx
+<Dialog open={open} onOpenChange={setOpen}>
+  <DialogContent className="max-w-lg">
+    <DialogHeader>
+      <DialogTitle>添加乘客</DialogTitle>
+    </DialogHeader>
+    <View className="space-y-4">
+      <Input placeholder="乘客姓名" />
+      <Input placeholder="手机号码" />
+      <Select>
+        <SelectTrigger>
+          <SelectValue placeholder="证件类型" />
+        </SelectTrigger>
+        <SelectContent>
+          <SelectItem value="idCard">身份证</SelectItem>
+          <SelectItem value="passport">护照</SelectItem>
+        </SelectContent>
+      </Select>
+    </View>
+    <DialogFooter>
+      <Button variant="outline" onClick={() => setOpen(false)}>
+        取消
+      </Button>
+      <Button onClick={handleSubmit}>
+        保存
+      </Button>
+    </DialogFooter>
+  </DialogContent>
+</Dialog>
+```
+
+#### 警告对话框
+```tsx
+<Dialog open={open} onOpenChange={setOpen}>
+  <DialogContent>
+    <DialogHeader>
+      <View className="flex items-center justify-center w-12 h-12 bg-red-100 rounded-full mb-4">
+        <Text className="i-heroicons-exclamation-triangle-20-solid w-6 h-6 text-red-600" />
+      </View>
+      <DialogTitle className="text-center">警告</DialogTitle>
+    </DialogHeader>
+    <Text className="text-gray-600 text-center mb-6">
+      此操作不可撤销,请谨慎操作。
+    </Text>
+    <DialogFooter>
+      <Button variant="outline" onClick={() => setOpen(false)}>
+        取消
+      </Button>
+      <Button variant="destructive" onClick={handleDelete}>
+        删除
+      </Button>
+    </DialogFooter>
+  </DialogContent>
+</Dialog>
+```
+
+### 迁移指南
+
+#### Navbar 迁移
+```tsx
+// 原小程序
+<navigation-bar title="页面标题" background="#ffffff" />
+
+// 迁移后
+<Navbar title="页面标题" backgroundColor="bg-white" />
+```
+
+#### Dialog 迁移
+```tsx
+// 原小程序
+<modal visible={visible}>
+  <view class="modal-content">内容</view>
+</modal>
+
+// 迁移后
+<Dialog open={visible} onOpenChange={setVisible}>
+  <DialogContent>内容</DialogContent>
+</Dialog>
+```
+
 ---
 ---
 
 
 **文档状态**: 正式版
 **文档状态**: 正式版

+ 16 - 0
docs/stories/005.006.story.md

@@ -34,6 +34,8 @@ Approved
   - [ ] 实现设置默认乘客功能
   - [ ] 实现设置默认乘客功能
   - [ ] 集成真实的后端API替换模拟数据
   - [ ] 集成真实的后端API替换模拟数据
   - [ ] 保持原有样式和用户体验
   - [ ] 保持原有样式和用户体验
+  - [ ] 遵循Navbar样式规范实现页面导航栏
+  - [ ] 遵循Dialog样式规范实现添加/编辑/删除对话框
 - [ ] 创建Taro小程序独立添加乘客页面 (AC: 1, 2, 3, 4)
 - [ ] 创建Taro小程序独立添加乘客页面 (AC: 1, 2, 3, 4)
   - [ ] 迁移 `mini-demo/pages/add-passenger/add-passenger` 页面到 `mini/src/pages/passengers/add-passenger.tsx`
   - [ ] 迁移 `mini-demo/pages/add-passenger/add-passenger` 页面到 `mini/src/pages/passengers/add-passenger.tsx`
   - [ ] 遵循 [mini-demo迁移指导规范](docs/architecture/mini-demo-migration-guide.md) 进行技术栈转换
   - [ ] 遵循 [mini-demo迁移指导规范](docs/architecture/mini-demo-migration-guide.md) 进行技术栈转换
@@ -47,6 +49,8 @@ Approved
   - [ ] 支持多种证件类型选择器
   - [ ] 支持多种证件类型选择器
   - [ ] 集成真实的后端API
   - [ ] 集成真实的后端API
   - [ ] 保持原有样式和用户体验
   - [ ] 保持原有样式和用户体验
+  - [ ] 遵循Navbar样式规范实现页面导航栏
+  - [ ] 遵循Dialog样式规范实现表单验证提示对话框
 - [ ] 集成乘客页面到小程序路由 (AC: 1)
 - [ ] 集成乘客页面到小程序路由 (AC: 1)
   - [ ] 在Taro小程序路由配置中添加乘客页面
   - [ ] 在Taro小程序路由配置中添加乘客页面
   - [ ] 在个人中心页面添加乘客管理入口
   - [ ] 在个人中心页面添加乘客管理入口
@@ -182,6 +186,14 @@ export const passengerRoutes = createCrudRoutes({
 - 技术栈转换:原生小程序 → Taro + React + TypeScript
 - 技术栈转换:原生小程序 → Taro + React + TypeScript
 - 数据集成:模拟数据 → 真实后端API
 - 数据集成:模拟数据 → 真实后端API
 
 
+**Navbar和Dialog样式规范** [Source: architecture/mini-demo-migration-guide.md#navbar-导航栏样式规范]:
+- 遵循Navbar导航栏样式规范进行导航栏开发
+- 使用预设样式变体(默认、深色、透明、主色调)
+- 正确处理微信小程序和H5平台的适配差异
+- 遵循Dialog对话框样式规范进行弹窗开发
+- 使用标准对话框组件结构(Content、Header、Title、Footer)
+- 实现确认对话框、表单对话框、警告对话框等预设变体
+
 ### Testing
 ### Testing
 
 
 **测试要求** [Source: architecture/testing-strategy.md#主项目测试体系]:
 **测试要求** [Source: architecture/testing-strategy.md#主项目测试体系]:
@@ -200,10 +212,13 @@ export const passengerRoutes = createCrudRoutes({
   - 测试乘客列表页面渲染
   - 测试乘客列表页面渲染
   - 验证添加乘客表单功能
   - 验证添加乘客表单功能
   - 测试编辑和删除乘客功能
   - 测试编辑和删除乘客功能
+  - 验证Navbar组件样式和交互
+  - 验证Dialog组件样式和交互
 - **页面迁移兼容性测试** (P1优先级)
 - **页面迁移兼容性测试** (P1优先级)
   - 验证迁移后的添加乘客页面功能完整性
   - 验证迁移后的添加乘客页面功能完整性
   - 测试样式保留和用户体验一致性
   - 测试样式保留和用户体验一致性
   - 验证与后端API的集成
   - 验证与后端API的集成
+  - 验证Navbar和Dialog样式规范遵循情况
 - **乘客信息验证测试** (P0优先级)
 - **乘客信息验证测试** (P0优先级)
   - 验证证件类型和号码格式
   - 验证证件类型和号码格式
   - 测试手机号验证规则
   - 测试手机号验证规则
@@ -212,6 +227,7 @@ export const passengerRoutes = createCrudRoutes({
 ## Change Log
 ## Change Log
 | Date | Version | Description | Author |
 | Date | Version | Description | Author |
 |------|---------|-------------|--------|
 |------|---------|-------------|--------|
+| 2025-10-22 | 1.3 | 添加Navbar和Dialog样式规范要求 | Winston (Architect) |
 | 2025-10-21 | 1.2 | 故事验证通过,状态更新为Approved | Sarah (Product Owner) |
 | 2025-10-21 | 1.2 | 故事验证通过,状态更新为Approved | Sarah (Product Owner) |
 | 2025-10-21 | 1.1 | 添加页面迁移任务和测试要求 | Bob (Scrum Master) |
 | 2025-10-21 | 1.1 | 添加页面迁移任务和测试要求 | Bob (Scrum Master) |
 | 2025-10-21 | 1.0 | 初始故事创建,基于史诗005 US005-06需求 | Bob (Scrum Master) |
 | 2025-10-21 | 1.0 | 初始故事创建,基于史诗005 US005-06需求 | Bob (Scrum Master) |

+ 5 - 0
mini/src/app.css

@@ -190,4 +190,9 @@
 
 
 .scroll-indicator:hover::after {
 .scroll-indicator:hover::after {
   opacity: 1;
   opacity: 1;
+}
+
+
+#taro-navigation-bar {
+  display: none;
 }
 }

+ 1 - 1
mini/src/components/ui/button.tsx

@@ -3,7 +3,7 @@ import { cn } from '@/utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 import { cva, type VariantProps } from 'class-variance-authority'
 
 
 const buttonVariants = cva(
 const buttonVariants = cva(
-  'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
+  'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background mt-0',
   {
   {
     variants: {
     variants: {
       variant: {
       variant: {

+ 1 - 1
mini/src/components/ui/navbar.tsx

@@ -216,7 +216,7 @@ export const NavbarPresets = {
   
   
   // 主色调导航栏
   // 主色调导航栏
   primary: {
   primary: {
-    backgroundColor: 'bg-blue-500',
+    backgroundColor: 'bg-primary',
     textColor: 'text-white',
     textColor: 'text-white',
     border: false,
     border: false,
   },
   },

+ 0 - 6
mini/src/pages/passengers/passengers.config.ts

@@ -1,6 +0,0 @@
-export default definePageConfig({
-  navigationBarTitleText: '乘车人管理',
-  enablePullDownRefresh: false,
-  backgroundColor: '#f8f9fa',
-  navigationStyle: 'default'
-})

+ 9 - 6
mini/src/pages/passengers/passengers.tsx

@@ -2,7 +2,7 @@ import { useState } from 'react'
 import { View, Text, ScrollView, Picker } from '@tarojs/components'
 import { View, Text, ScrollView, Picker } from '@tarojs/components'
 import Taro from '@tarojs/taro'
 import Taro from '@tarojs/taro'
 import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
 import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
-import { Navbar } from '@/components/ui/navbar'
+import { Navbar, NavbarPresets } from '@/components/ui/navbar'
 import { Button } from '@/components/ui/button'
 import { Button } from '@/components/ui/button'
 import { Card, CardContent } from '@/components/ui/card'
 import { Card, CardContent } from '@/components/ui/card'
 import { Input as ShadcnInput } from '@/components/ui/input'
 import { Input as ShadcnInput } from '@/components/ui/input'
@@ -178,9 +178,10 @@ const PassengersPage: React.FC = () => {
   const deletePassenger = (passenger: Passenger) => {
   const deletePassenger = (passenger: Passenger) => {
     Taro.showModal({
     Taro.showModal({
       title: '确认删除',
       title: '确认删除',
-      content: `确定要删除乘车人"${passenger.name}"吗?`,
+      content: `确定要删除乘车人"${passenger.name}"吗?此操作不可恢复。`,
       confirmText: '删除',
       confirmText: '删除',
       confirmColor: '#ff4d4f',
       confirmColor: '#ff4d4f',
+      cancelText: '取消',
       success: (res) => {
       success: (res) => {
         if (res.confirm) {
         if (res.confirm) {
           deleteMutation.mutate(passenger.id)
           deleteMutation.mutate(passenger.id)
@@ -228,7 +229,8 @@ const PassengersPage: React.FC = () => {
       title: '乘车人详情',
       title: '乘车人详情',
       content: `姓名:${passenger.name}\n证件类型:${passenger.idType}\n证件号码:${passenger.idNumber}\n手机号:${passenger.phone}\n创建时间:${new Date(passenger.createdAt).toLocaleString('zh-CN')}`,
       content: `姓名:${passenger.name}\n证件类型:${passenger.idType}\n证件号码:${passenger.idNumber}\n手机号:${passenger.phone}\n创建时间:${new Date(passenger.createdAt).toLocaleString('zh-CN')}`,
       showCancel: false,
       showCancel: false,
-      confirmText: '知道了'
+      confirmText: '知道了',
+      confirmColor: '#4A90C2'
     })
     })
   }
   }
 
 
@@ -257,6 +259,7 @@ const PassengersPage: React.FC = () => {
         title="乘车人管理"
         title="乘车人管理"
         leftIcon="i-heroicons-arrow-left-20-solid"
         leftIcon="i-heroicons-arrow-left-20-solid"
         onClickLeft={() => Taro.navigateBack()}
         onClickLeft={() => Taro.navigateBack()}
+        {...NavbarPresets.primary}
       />
       />
 
 
       {/* 顶部操作栏 */}
       {/* 顶部操作栏 */}
@@ -341,7 +344,7 @@ const PassengersPage: React.FC = () => {
                     </View>
                     </View>
                   </View>
                   </View>
 
 
-                  <View className="flex justify-end space-x-2">
+                  <View className="flex justify-end gap-2">
                     {!passenger.isDefault && (
                     {!passenger.isDefault && (
                       <Button
                       <Button
                         variant="outline"
                         variant="outline"
@@ -393,7 +396,7 @@ const PassengersPage: React.FC = () => {
       <Dialog open={showAddModal} onOpenChange={setShowAddModal}>
       <Dialog open={showAddModal} onOpenChange={setShowAddModal}>
         <DialogContent className="max-w-md max-h-80vh overflow-hidden">
         <DialogContent className="max-w-md max-h-80vh overflow-hidden">
           <DialogHeader>
           <DialogHeader>
-            <DialogTitle>
+            <DialogTitle className="text-lg font-semibold text-gray-900">
               {editingPassenger ? '编辑乘车人' : '添加乘车人'}
               {editingPassenger ? '编辑乘车人' : '添加乘车人'}
             </DialogTitle>
             </DialogTitle>
           </DialogHeader>
           </DialogHeader>
@@ -451,7 +454,7 @@ const PassengersPage: React.FC = () => {
             </View>
             </View>
           </ScrollView>
           </ScrollView>
 
 
-          <DialogFooter className="pt-4 border-t border-gray-100 bg-gray-50/50">
+          <DialogFooter className="pt-4 border-t border-gray-100 bg-gray-50/50 flex flex-row gap-4">
             <Button
             <Button
               variant="outline"
               variant="outline"
               onClick={() => setShowAddModal(false)}
               onClick={() => setShowAddModal(false)}