wlzboy
2025-10-26 5c5cddb1c2ee0d19adddebaf3a3a10a6d93fd2ad
feat:优化微信小程序可以运行
18个文件已修改
14个文件已添加
5621 ■■■■■ 已修改文件
app/components/map-selector.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/config.js 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/login.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/mine/index.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/mine/privacy-policy/index.vue 439 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/mine/user-agreement/index.vue 384 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/register.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/task/detail.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/task/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/permission.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/小程序本地调试配置指南.md 598 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/快速配置清单.md 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/uni-app模板语法修复-class绑定.md 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/后台任务管理-急救转运扩展显示.md 387 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/用户协议与隐私政策完善说明.md 552 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/用户协议与隐私政策说明.md 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/登录注册协议链接优化说明.md 407 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/绑定车辆部门过滤-已实现.md 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/车辆同步部门查询修复说明.md 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/车辆查询部门自动匹配功能说明.md 347 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/部门分公司ID获取方法说明.md 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prd/隐私政策和用户协议匿名访问配置.md 449 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/task/general/detail.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/task/general/index.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/components/map-selector.vue
@@ -38,7 +38,7 @@
      <view 
        class="address-item" 
        v-for="(item, index) in searchResults" 
        :key="'search-' + index"
        :key="index"
        @click="selectAddress(item)"
      >
        <!-- ç¡®ä¿ä½¿ç”¨æ’值语法 -->
app/config.js
@@ -1,25 +1,62 @@
// åº”用全局配置
// âš ï¸ é‡è¦ï¼šæœ¬åœ°å¼€å‘时,请修改此处的LOCAL_IP为你的电脑内网IP
// Windows查看: cmd执行 ipconfig
// Mac/Linux查看: ç»ˆç«¯æ‰§è¡Œ ifconfig æˆ– ip addr
const LOCAL_IP = 'localhost'  // ä¿®æ”¹ä¸ºä½ çš„IP,如: '192.168.1.100'
// çŽ¯å¢ƒé…ç½®
const ENV_CONFIG = {
  // æœ¬åœ°å¼€å‘环境
  development: {
    baseUrl: `http://${LOCAL_IP}:8080`,
    description: '本地开发环境'
  },
  // æµ‹è¯•环境
  test: {
    baseUrl: 'http://test.yourdomain.com',
    description: '测试环境'
  },
  // ç”Ÿäº§çŽ¯å¢ƒ
  production: {
    baseUrl: 'https://api.yourdomain.com',
    description: '生产环境'
  }
}
// å½“前使用的环境(手动切换)
// å¯é€‰å€¼: 'development', 'test', 'production'
const CURRENT_ENV = 'development'
module.exports = {
  // baseUrl: 'https://vue.ruoyi.vip/prod-api',
  baseUrl: 'http://localhost:8080',
  // API基础地址
  baseUrl: ENV_CONFIG[CURRENT_ENV].baseUrl,
  // åº”用信息
  appInfo: {
    // åº”用名称
    name: "ruoyi-app",
    name: "民航调度系统",
    // åº”用版本
    version: "1.1.0",
    // åº”用logo
    logo: "/static/logo.png",
    // å®˜æ–¹ç½‘ç«™
    site_url: "http://ruoyi.vip",
    // æ”¿ç­–协议
    agreements: [{
    // å½“前环境信息(仅开发时显示)
    env: CURRENT_ENV,
    envDescription: ENV_CONFIG[CURRENT_ENV].description,
    showEnv: CURRENT_ENV === 'development',  // æ˜¯å¦æ˜¾ç¤ºçŽ¯å¢ƒä¿¡æ¯
    // æ”¿ç­–协议(使用本地页面)
    agreements: [
      {
        title: "隐私政策",
        url: "https://ruoyi.vip/protocol.html"
        url: "/pages/mine/privacy-policy/index"
      },
      {
        title: "用户服务协议",
        url: "https://ruoyi.vip/protocol.html"
        url: "/pages/mine/user-agreement/index"
      }
    ]
  }
app/manifest.json
@@ -41,7 +41,7 @@
    },
    "quickapp" : {},
    "mp-weixin" : {
        "appid" : "wxccd7e2a0911b3397",
        "appid" : "wx40692cc44953a8cb",
        "setting" : {
            "urlCheck" : false,
            "es6" : false,
app/pages.json
@@ -71,6 +71,16 @@
      "navigationBarTitleText": "关于我们"
    }
  }, {
    "path": "pages/mine/user-agreement/index",
    "style": {
      "navigationBarTitleText": "用户服务协议"
    }
  }, {
    "path": "pages/mine/privacy-policy/index",
    "style": {
      "navigationBarTitleText": "隐私政策"
    }
  }, {
    "path": "pages/common/webview/index",
    "style": {
      "navigationBarTitleText": "浏览网页"
app/pages/index.vue
@@ -55,7 +55,7 @@
            <!-- ä»»åŠ¡å¤´éƒ¨ï¼šæ ‡é¢˜å’ŒçŠ¶æ€æ ‡ç­¾ -->
            <view class="task-header">
              <view class="task-title">{{ getTaskTypeText(task.type) }} - {{ task.vehicle }}</view>
              <view class="task-status" :class="getStatusClass(task.taskStatus)">
              <view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
                {{ getStatusText(task.status) }}
              </view>
            </view>
app/pages/login.vue
@@ -30,14 +30,12 @@
          <text class="wechat-text">微信一键登录</text>
        </view>
      </view>
      <view class="reg text-center" v-if="register">
        <text class="text-grey1">没有账号?</text>
        <text @click="handleUserRegister" class="text-blue">立即注册</text>
      </view>
      <view class="xieyi text-center">
        <text class="text-grey1">登录即代表同意</text>
        <text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
        <text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
        <text @click.stop="handleUserAgrement" class="text-blue agreement-link">《用户协议》</text>
        <text class="text-grey1">和</text>
        <text @click.stop="handlePrivacy" class="text-blue agreement-link">《隐私协议》</text>
      </view>
    </view>
  </scroll-view>
@@ -55,8 +53,8 @@
        register: false,
        globalConfig: getApp().globalData.config,
        loginForm: {
          username: "admin",
          password: "admin123",
          username: "",
          password: "",
          code: "",
          uuid: ''
        }
@@ -72,13 +70,11 @@
      },
      // éšç§åè®®
      handlePrivacy() {
        let site = this.globalConfig.appInfo.agreements[0]
        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
        this.$tab.navigateTo('/pages/mine/privacy-policy/index')
      },
      // ç”¨æˆ·åè®®
      handleUserAgrement() {
        let site = this.globalConfig.appInfo.agreements[1]
        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
        this.$tab.navigateTo('/pages/mine/user-agreement/index')
      },
      // èŽ·å–å›¾å½¢éªŒè¯ç 
      getCode() {
@@ -297,7 +293,7 @@
        }
      }
      .reg, .xieyi {
      .reg {
        margin: 20rpx 0;
        .text-grey1 {
@@ -309,6 +305,27 @@
          color: #007AFF;
        }
      }
      .xieyi {
        margin: 50rpx 0 30rpx 0;
        padding: 20rpx 0;
        line-height: 2;
        .text-grey1 {
          color: #888;
          font-size: 24rpx;
        }
        .agreement-link {
          color: #007AFF;
          font-size: 24rpx;
          padding: 10rpx 8rpx;
          margin: 0 5rpx;
          display: inline-block;
          position: relative;
          z-index: 10;
        }
      }
    }
  }
</style>
app/pages/mine/index.vue
@@ -80,6 +80,18 @@
            <view>编辑资料</view>
          </view>
        </view>
        <view class="list-cell list-cell-arrow" @click="handleUserAgreement">
          <view class="menu-item-box">
            <view class="iconfont icon-text menu-icon"></view>
            <view>用户服务协议</view>
          </view>
        </view>
        <view class="list-cell list-cell-arrow" @click="handlePrivacyPolicy">
          <view class="menu-item-box">
            <view class="iconfont icon-safe menu-icon"></view>
            <view>隐私政策</view>
          </view>
        </view>
        <view class="list-cell list-cell-arrow" @click="handleHelp">
          <view class="menu-item-box">
            <view class="iconfont icon-help menu-icon"></view>
@@ -227,6 +239,12 @@
      handleAbout() {
        this.$tab.navigateTo('/pages/mine/about/index')
      },
      handleUserAgreement() {
        this.$tab.navigateTo('/pages/mine/user-agreement/index')
      },
      handlePrivacyPolicy() {
        this.$tab.navigateTo('/pages/mine/privacy-policy/index')
      },
      handleJiaoLiuQun() {
        this.$modal.showToast('QQ群:①133713780(满)、②146013835(满)、③189091635')
      },
app/pages/mine/privacy-policy/index.vue
New file
@@ -0,0 +1,439 @@
<template>
  <view class="privacy-container">
    <view class="header">
      <view class="back-btn" @click="goBack">
        <uni-icons type="arrowleft" size="20"></uni-icons>
      </view>
      <view class="title">隐私政策</view>
    </view>
    <scroll-view class="content" scroll-y="true">
      <view class="privacy-content">
        <view class="update-time">更新日期:2025å¹´1月25日</view>
        <view class="effect-time">生效日期:2025å¹´10月25日</view>
        <view class="section">
          <text class="section-title">引言</text>
          <text class="section-text">
            æ€¥æ•‘转运调度系统(以下简称"我们")深知个人信息对您的重要性,我们将按照法律法规的要求,采取相应的安全保护措施,尽力保护您的个人信息安全可控。
          </text>
          <text class="section-text">
            æœ¬ã€Šéšç§æ”¿ç­–》适用于我们向您提供的所有服务。我们希望通过本政策向您说明我们如何收集、使用、存储和分享您的个人信息,以及您享有的相关权利。
          </text>
          <text class="section-text highlight">
            è¯·æ‚¨åœ¨ä½¿ç”¨æˆ‘们的产品/服务前,仔细阅读并充分理解本政策,特别是以粗体/下划线标识的条款,您应重点阅读。如您对本政策有任何疑问,可通过本政策文末提供的联系方式与我们联系。
          </text>
        </view>
        <view class="section">
          <text class="section-title">一、我们如何收集和使用您的个人信息</text>
          <text class="section-text">
            ä¸ªäººä¿¡æ¯æ˜¯æŒ‡ä»¥ç”µå­æˆ–者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。
          </text>
          <text class="section-text">
            æˆ‘们仅会出于以下目的,收集和使用您的个人信息:
          </text>
          <text class="subsection-title">1.1 è´¦å·æ³¨å†Œä¸Žç™»å½•</text>
          <text class="section-text">
            å½“您注册及使用本系统时,我们需要收集:
          </text>
          <text class="section-text indent">
            Â· æ‰‹æœºå·ç ï¼šç”¨äºŽè´¦å·æ³¨å†Œã€ç™»å½•验证和安全保障
          </text>
          <text class="section-text indent">
            Â· å§“名:用于身份识别和任务分配
          </text>
          <text class="section-text indent">
            Â· æ‰€å±žéƒ¨é—¨/机构:用于权限管理和任务协作
          </text>
          <text class="section-text indent">
            Â· èŒä½/角色:用于确定系统使用权限
          </text>
          <text class="subsection-title">1.2 ä»»åŠ¡è°ƒåº¦æœåŠ¡</text>
          <text class="section-text">
            ä¸ºäº†å‘您提供任务调度服务,我们需要收集:
          </text>
          <text class="section-text indent">
            Â· ä½ç½®ä¿¡æ¯ï¼šèŽ·å–æ‚¨çš„å®žæ—¶ä½ç½®ï¼Œç”¨äºŽä»»åŠ¡åˆ†é…ã€è½¦è¾†è°ƒåº¦å’Œè·¯å¾„è§„åˆ’
          </text>
          <text class="section-text indent">
            Â· ä»»åŠ¡ç›¸å…³ä¿¡æ¯ï¼šåŒ…æ‹¬æ‚£è€…ä¿¡æ¯ï¼ˆå§“åã€å¹´é¾„ã€æ€§åˆ«ã€ç—…æƒ…æè¿°ï¼‰ã€åœ°å€ä¿¡æ¯ã€åŒ»é™¢ä¿¡æ¯ç­‰
          </text>
          <text class="section-text indent">
            Â· è½¦è¾†ä¿¡æ¯ï¼šè½¦ç‰Œå·ã€è½¦è¾†ç±»åž‹ã€è®¾å¤‡ç¼–号等
          </text>
          <text class="section-text highlight">
            ä½ç½®ä¿¡æ¯å±žäºŽæ•æ„Ÿä¸ªäººä¿¡æ¯ï¼Œæˆ‘们仅在您主动开启定位权限并使用相关功能时收集,您可以随时在系统设置中关闭定位权限。拒绝提供位置信息可能导致部分功能无法使用,但不影响其他功能的正常使用。
          </text>
          <text class="subsection-title">1.3 æ¶ˆæ¯æŽ¨é€æœåŠ¡</text>
          <text class="section-text">
            ä¸ºäº†åŠæ—¶å‘您推送任务通知、系统消息等信息,我们需要收集:
          </text>
          <text class="section-text indent">
            Â· è®¾å¤‡ä¿¡æ¯ï¼šè®¾å¤‡åž‹å·ã€æ“ä½œç³»ç»Ÿç‰ˆæœ¬ã€è®¾å¤‡æ ‡è¯†ç¬¦
          </text>
          <text class="section-text indent">
            Â· æŽ¨é€token:用于消息推送
          </text>
          <text class="subsection-title">1.4 ç³»ç»Ÿå®‰å…¨ä¸Žä¼˜åŒ–</text>
          <text class="section-text">
            ä¸ºäº†ä¿éšœç³»ç»Ÿå®‰å…¨ç¨³å®šè¿è¡Œå¹¶æå‡ç”¨æˆ·ä½“验,我们会收集:
          </text>
          <text class="section-text indent">
            Â· æ—¥å¿—信息:操作日志、错误日志、性能数据
          </text>
          <text class="section-text indent">
            Â· ç½‘络信息:IP地址、网络类型
          </text>
          <text class="section-text indent">
            Â· åº”用使用情况:页面访问记录、功能使用频率
          </text>
        </view>
        <view class="section">
          <text class="section-title">二、我们如何使用Cookie和同类技术</text>
          <text class="section-text">
            Cookie是一种网络服务器存储在计算机或移动设备上的纯文本文件。我们使用Cookie和同类技术主要为了实现以下功能:
          </text>
          <text class="section-text indent">
            Â· è®°ä½æ‚¨çš„登录状态,避免重复登录
          </text>
          <text class="section-text indent">
            Â· åˆ†æžæ‚¨ä½¿ç”¨æˆ‘们服务的情况,以便优化服务体验
          </text>
          <text class="section-text indent">
            Â· ä¿éšœç³»ç»Ÿå®‰å…¨ï¼Œé˜²èŒƒå®‰å…¨é£Žé™©
          </text>
          <text class="section-text">
            æ‚¨å¯ä»¥é€šè¿‡æµè§ˆå™¨æˆ–设备设置拒绝或管理Cookie,但这可能影响您使用我们服务的部分功能。
          </text>
        </view>
        <view class="section">
          <text class="section-title">三、我们如何共享、转让、公开披露您的个人信息</text>
          <text class="subsection-title">3.1 å…±äº«</text>
          <text class="section-text">
            æˆ‘们不会向第三方共享您的个人信息,除非:
          </text>
          <text class="section-text indent">
            Â· äº‹å…ˆèŽ·å¾—æ‚¨çš„æ˜Žç¡®åŒæ„
          </text>
          <text class="section-text indent">
            Â· ä¸Žå…³è”机构共享:在业务需要且符合法律规定的情况下,我们可能与您所属医疗机构、急救中心共享必要信息
          </text>
          <text class="section-text indent">
            Â· æ³•律法规规定的其他情形
          </text>
          <text class="subsection-title">3.2 è½¬è®©</text>
          <text class="section-text">
            æˆ‘们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:
          </text>
          <text class="section-text indent">
            Â· äº‹å…ˆèŽ·å¾—æ‚¨çš„æ˜Žç¡®åŒæ„
          </text>
          <text class="section-text indent">
            Â· æ ¹æ®æ³•律法规或强制性的行政或司法要求
          </text>
          <text class="subsection-title">3.3 å…¬å¼€æŠ«éœ²</text>
          <text class="section-text">
            æˆ‘们仅会在以下情况下公开披露您的个人信息:
          </text>
          <text class="section-text indent">
            Â· èŽ·å¾—æ‚¨çš„æ˜Žç¡®åŒæ„
          </text>
          <text class="section-text indent">
            Â· åŸºäºŽæ³•律法规、法律程序、诉讼或政府主管部门强制性要求
          </text>
        </view>
        <view class="section">
          <text class="section-title">四、我们如何保护您的个人信息</text>
          <text class="section-text">
            4.1 æˆ‘们非常重视个人信息安全,并采取一切合理可行的措施保护您的个人信息:
          </text>
          <text class="section-text indent">
            Â· æ•°æ®åŠ å¯†ï¼šé‡‡ç”¨SSL/TLS加密传输,对敏感数据进行加密存储
          </text>
          <text class="section-text indent">
            Â· è®¿é—®æŽ§åˆ¶ï¼šå»ºç«‹ä¸¥æ ¼çš„æ•°æ®è®¿é—®æƒé™æŽ§åˆ¶å’Œå®¡æ‰¹æœºåˆ¶
          </text>
          <text class="section-text indent">
            Â· å®‰å…¨å®¡è®¡ï¼šå®šæœŸè¿›è¡Œå®‰å…¨å®¡è®¡å’Œé£Žé™©è¯„ä¼°
          </text>
          <text class="section-text indent">
            Â· äººå‘˜ç®¡ç†ï¼šå¯¹å¤„理个人信息的员工进行身份认证和权限管理
          </text>
          <text class="section-text indent">
            Â· åº”急响应:制定个人信息安全事件应急预案
          </text>
          <text class="section-text">
            4.2 æˆ‘们会采取合理可行的措施,尽力避免收集无关的个人信息。
          </text>
          <text class="section-text highlight">
            4.3 äº’联网并非绝对安全的环境,我们强烈建议您采取积极措施保护个人信息的安全,包括但不限于使用复杂密码、定期修改密码、不将自己的账号密码等个人信息透露给他人。
          </text>
          <text class="section-text highlight">
            4.4 å¦‚果发生个人信息安全事件,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议等。
          </text>
        </view>
        <view class="section">
          <text class="section-title">五、您如何管理个人信息</text>
          <text class="section-text">
            æŒ‰ç…§ä¸­å›½ç›¸å…³çš„æ³•律法规,我们保障您对自己的个人信息行使以下权利:
          </text>
          <text class="subsection-title">5.1 è®¿é—®å’Œæ›´æ­£æ‚¨çš„个人信息</text>
          <text class="section-text">
            æ‚¨å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼è®¿é—®å’Œæ›´æ­£æ‚¨çš„个人信息:
          </text>
          <text class="section-text indent">
            Â· é€šè¿‡"我的-个人信息"页面查看和修改基本信息
          </text>
          <text class="section-text indent">
            Â· è”系系统管理员协助修改
          </text>
          <text class="subsection-title">5.2 åˆ é™¤æ‚¨çš„个人信息</text>
          <text class="section-text">
            åœ¨ä»¥ä¸‹æƒ…形中,您可以向我们提出删除个人信息的请求:
          </text>
          <text class="section-text indent">
            Â· æˆ‘们处理个人信息的行为违反法律法规
          </text>
          <text class="section-text indent">
            Â· æˆ‘们收集、使用您的个人信息,却未征得您的同意
          </text>
          <text class="section-text indent">
            Â· æˆ‘们处理个人信息的行为违反了与您的约定
          </text>
          <text class="section-text indent">
            Â· æ‚¨æ³¨é”€äº†è´¦å·
          </text>
          <text class="subsection-title">5.3 æ³¨é”€è´¦å·</text>
          <text class="section-text">
            æ‚¨å¯ä»¥é€šè¿‡è”系系统管理员申请注销账号。账号注销后,我们将停止为您提供服务,并根据法律法规要求删除您的个人信息。
          </text>
          <text class="subsection-title">5.4 æ’¤å›žåŒæ„</text>
          <text class="section-text">
            æ‚¨å¯ä»¥é€šè¿‡è®¾å¤‡æƒé™è®¾ç½®æ’¤å›žå¯¹ä½ç½®ä¿¡æ¯ã€æ‘„像头、相册等敏感权限的授权。
          </text>
          <text class="section-text">
            è¯·æ‚¨ç†è§£ï¼Œç‰¹å®šçš„业务功能需要您的信息才能得以完成,当您撤回同意后,我们无法继续为您提供撤回同意所对应的服务。
          </text>
        </view>
        <view class="section">
          <text class="section-title">六、我们如何处理未成年人的个人信息</text>
          <text class="section-text">
            6.1 æœ¬ç³»ç»Ÿä¸»è¦é¢å‘医疗急救从业人员,原则上不向未成年人提供服务。
          </text>
          <text class="section-text">
            6.2 å¦‚果我们发现在未事先获得可证实的父母或法定监护人同意的情况下收集了未成年人的个人信息,我们会设法尽快删除相关数据。
          </text>
        </view>
        <view class="section">
          <text class="section-title">七、您的个人信息如何在全球范围内转移</text>
          <text class="section-text">
            æˆ‘们在中华人民共和国境内收集和产生的个人信息将存储在中华人民共和国境内。
          </text>
        </view>
        <view class="section">
          <text class="section-title">八、本政策如何更新</text>
          <text class="section-text">
            8.1 æˆ‘们可能适时修订本政策内容。如该等变更会导致您在本政策项下权利的实质减损,我们将在变更生效前,通过在页面显著位置提示、向您发送消息等方式通知您。
          </text>
          <text class="section-text highlight">
            8.2 åœ¨è¯¥ç§æƒ…况下,若您继续使用我们的服务,即表示同意受经修订的本政策的约束。
          </text>
        </view>
        <view class="section">
          <text class="section-title">九、如何联系我们</text>
          <text class="section-text">
            9.1 å¦‚您对本隐私政策或您个人信息的相关事宜有任何问题、意见或建议,请通过以下方式与我们联系:
          </text>
          <text class="section-text">
            ç”µå­é‚®ç®±ï¼šwanglizhong@966120.com.cn
          </text>
          <text class="section-text">
            å®¢æœç”µè¯ï¼š020-966120
          </text>
          <text class="section-text">
            å·¥ä½œæ—¶é—´ï¼šå‘¨ä¸€è‡³å‘¨æ—¥ 24小时
          </text>
          <text class="section-text">
            9.2 ä¸€èˆ¬æƒ…况下,我们将在15个工作日内回复您的请求。
          </text>
        </view>
        <view class="section">
          <text class="section-title">十、定义</text>
          <text class="section-text">
            ä¸ªäººä¿¡æ¯ï¼šæŒ‡ä»¥ç”µå­æˆ–者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。
          </text>
          <text class="section-text">
            æ•æ„Ÿä¸ªäººä¿¡æ¯ï¼šæŒ‡ä¸€æ—¦æ³„露或者非法使用,容易导致自然人的人格尊严受到侵害或者人身、财产安全受到危害的个人信息,包括生物识别、宗教信仰、特定身份、医疗健康、金融账户、行踪轨迹等信息。
          </text>
          <text class="section-text">
            ä¸ªäººä¿¡æ¯åˆ é™¤ï¼šæŒ‡åœ¨å®žçŽ°æ—¥å¸¸ä¸šåŠ¡åŠŸèƒ½æ‰€æ¶‰åŠçš„ç³»ç»Ÿä¸­åŽ»é™¤ä¸ªäººä¿¡æ¯çš„è¡Œä¸ºï¼Œä½¿å…¶ä¿æŒä¸å¯è¢«æ£€ç´¢ã€è®¿é—®çš„çŠ¶æ€ã€‚
          </text>
        </view>
        <view class="footer">
          <text class="footer-text">感谢您信任并使用急救转运调度系统!</text>
        </view>
      </view>
    </scroll-view>
  </view>
</template>
<script>
  export default {
    data() {
      return {}
    },
    methods: {
      goBack() {
        uni.navigateBack()
      }
    }
  }
</script>
<style lang="scss">
  .privacy-container {
    height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: #f5f5f5;
    .header {
      display: flex;
      align-items: center;
      padding: 20rpx;
      background-color: white;
      border-bottom: 1rpx solid #f0f0f0;
      .back-btn {
        width: 60rpx;
        height: 60rpx;
        border-radius: 50%;
        background-color: #f0f0f0;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 20rpx;
      }
      .title {
        font-size: 36rpx;
        font-weight: bold;
        color: #333;
      }
    }
    .content {
      flex: 1;
      padding: 30rpx;
    }
    .privacy-content {
      background-color: white;
      border-radius: 15rpx;
      padding: 40rpx 30rpx;
      .update-time,
      .effect-time {
        font-size: 24rpx;
        color: #999;
        margin-bottom: 10rpx;
      }
      .section {
        margin-top: 40rpx;
        &:first-child {
          margin-top: 30rpx;
        }
        .section-title {
          display: block;
          font-size: 32rpx;
          font-weight: bold;
          color: #333;
          margin-bottom: 20rpx;
          line-height: 1.5;
        }
        .subsection-title {
          display: block;
          font-size: 30rpx;
          font-weight: bold;
          color: #666;
          margin: 25rpx 0 15rpx;
          line-height: 1.5;
        }
        .section-text {
          display: block;
          font-size: 28rpx;
          color: #666;
          line-height: 1.8;
          margin-bottom: 15rpx;
          text-align: justify;
          &.highlight {
            background-color: #fff8e6;
            padding: 20rpx;
            border-left: 4rpx solid #ff9500;
            border-radius: 8rpx;
            margin: 20rpx 0;
            font-weight: bold;
            color: #333;
          }
          &.indent {
            padding-left: 40rpx;
            position: relative;
            &::before {
              content: '';
              position: absolute;
              left: 20rpx;
              top: 18rpx;
              width: 8rpx;
              height: 8rpx;
              background-color: #666;
              border-radius: 50%;
            }
          }
        }
      }
      .footer {
        margin-top: 60rpx;
        padding-top: 40rpx;
        border-top: 1rpx solid #f0f0f0;
        text-align: center;
        .footer-text {
          font-size: 28rpx;
          color: #007AFF;
          font-weight: bold;
        }
      }
    }
  }
</style>
app/pages/mine/user-agreement/index.vue
New file
@@ -0,0 +1,384 @@
<template>
  <view class="agreement-container">
    <view class="header">
      <view class="back-btn" @click="goBack">
        <uni-icons type="arrowleft" size="20"></uni-icons>
      </view>
      <view class="title">用户服务协议</view>
    </view>
    <scroll-view class="content" scroll-y="true">
      <view class="agreement-content">
        <view class="update-time">更新日期:2025å¹´1月25日</view>
        <view class="effect-time">生效日期:2025å¹´1月25日</view>
        <view class="section">
          <text class="section-title">欢迎使用急救转运调度系统!</text>
          <text class="section-text">
            åœ¨æ‚¨ä½¿ç”¨æ€¥æ•‘转运调度系统(以下简称"本系统"或"本服务")之前,请您仔细阅读并充分理解本《用户服务协议》(以下简称"本协议")。
          </text>
          <text class="section-text">
            æœ¬åè®®æ˜¯æ‚¨ä¸Žæœ¬ç³»ç»Ÿè¿è¥æ–¹ï¼ˆä»¥ä¸‹ç®€ç§°"我们")之间就使用本系统所订立的协议。通过注册、登录或使用本系统,即表示您已阅读、理解并同意接受本协议的全部内容。
          </text>
        </view>
        <view class="section">
          <text class="section-title">一、服务说明</text>
          <text class="section-text">
            1.1 æœ¬ç³»ç»Ÿæ˜¯ä¸€ä¸ªä¸“业的急救转运调度管理平台,为医疗机构、急救中心及相关工作人员提供任务调度、车辆管理、人员协调等服务。
          </text>
          <text class="section-text">
            1.2 æœ¬ç³»ç»Ÿæ”¯æŒçš„功能包括但不限于:
          </text>
          <text class="section-text indent">
            Â· æ€¥æ•‘转运任务创建与管理
          </text>
          <text class="section-text indent">
            Â· ç¦ç¥‰è½¦æœåŠ¡ä»»åŠ¡ç®¡ç†
          </text>
          <text class="section-text indent">
            Â· è½¦è¾†è°ƒåº¦ä¸Žå®šä½è·Ÿè¸ª
          </text>
          <text class="section-text indent">
            Â· äººå‘˜åˆ†é…ä¸Žåä½œ
          </text>
          <text class="section-text indent">
            Â· ä»»åŠ¡çŠ¶æ€å®žæ—¶æ›´æ–°
          </text>
          <text class="section-text indent">
            Â· æ¶ˆæ¯é€šçŸ¥ä¸Žæé†’
          </text>
          <text class="section-text">
            1.3 æˆ‘们将根据业务发展需要,不定期地对本系统及相关功能进行调整、升级或优化。
          </text>
        </view>
        <view class="section">
          <text class="section-title">二、账号注册与使用</text>
          <text class="section-text">
            2.1 æ‚¨éœ€è¦é€šè¿‡åˆæ³•途径注册并获得本系统账号,账号由系统管理员统一分配和管理。
          </text>
          <text class="section-text">
            2.2 æ‚¨åº”当妥善保管账号及密码,不得将账号转让、出借或以其他方式提供给他人使用。因您保管不善导致的账号被盗用等损失由您自行承担。
          </text>
          <text class="section-text">
            2.3 æ‚¨æ‰¿è¯ºæä¾›çš„æ³¨å†Œä¿¡æ¯çœŸå®žã€å‡†ç¡®ã€å®Œæ•´ï¼Œå¹¶åŠæ—¶æ›´æ–°ç›¸å…³ä¿¡æ¯ã€‚如因提供虚假信息造成的一切后果由您自行承担。
          </text>
          <text class="section-text">
            2.4 æ‚¨ç†è§£å¹¶åŒæ„ï¼Œæ‚¨çš„账号仅限本人使用,禁止赠与、借用、租用、转让或售卖。
          </text>
        </view>
        <view class="section">
          <text class="section-title">三、用户行为规范</text>
          <text class="section-text">
            3.1 æ‚¨åœ¨ä½¿ç”¨æœ¬ç³»ç»Ÿæ—¶ï¼Œåº”当遵守中华人民共和国相关法律法规,不得利用本系统从事违法违规活动。
          </text>
          <text class="section-text">
            3.2 æ‚¨ä¸å¾—进行以下行为:
          </text>
          <text class="section-text indent">
            Â· å‘布、传播违法违规信息
          </text>
          <text class="section-text indent">
            Â· ä¾µçŠ¯ä»–äººçŸ¥è¯†äº§æƒã€å•†ä¸šç§˜å¯†æˆ–å…¶ä»–åˆæ³•æƒç›Š
          </text>
          <text class="section-text indent">
            Â· æ¶æ„æ”»å‡»ã€ç ´åç³»ç»Ÿå®‰å…¨
          </text>
          <text class="section-text indent">
            Â· ä¼ æ’­è®¡ç®—机病毒或其他破坏性程序
          </text>
          <text class="section-text indent">
            Â· åˆ©ç”¨ç³»ç»Ÿæ¼æ´žè°‹å–不正当利益
          </text>
          <text class="section-text indent">
            Â· å¹²æ‰°ç³»ç»Ÿæ­£å¸¸è¿è¡Œ
          </text>
          <text class="section-text indent">
            Â· å½•任意编造、捏造虚假任务信息
          </text>
          <text class="section-text">
            3.3 æ‚¨åº”当按照真实情况填写任务信息,确保患者信息、地址信息等准确无误,以保障急救服务的及时性和有效性。
          </text>
          <text class="section-text">
            3.4 ä½œä¸ºæ€¥æ•‘转运工作人员,您应当:
          </text>
          <text class="section-text indent">
            Â· åŠæ—¶å“åº”任务分配
          </text>
          <text class="section-text indent">
            Â· å‡†ç¡®æ›´æ–°ä»»åŠ¡çŠ¶æ€
          </text>
          <text class="section-text indent">
            Â· éµå®ˆèŒä¸šé“德和操作规范
          </text>
          <text class="section-text indent">
            Â· ä¿æŠ¤æ‚£è€…隐私和个人信息
          </text>
        </view>
        <view class="section">
          <text class="section-title">四、隐私保护</text>
          <text class="section-text">
            4.1 æˆ‘们非常重视用户隐私保护,将按照《隐私政策》的约定收集、使用、存储和保护您的个人信息。
          </text>
          <text class="section-text">
            4.2 åœ¨ä½¿ç”¨æœ¬ç³»ç»Ÿè¿‡ç¨‹ä¸­ï¼Œæˆ‘们可能需要收集以下信息:
          </text>
          <text class="section-text indent">
            Â· åŸºæœ¬ä¿¡æ¯ï¼šå§“名、手机号码、所属部门等
          </text>
          <text class="section-text indent">
            Â· ä½ç½®ä¿¡æ¯ï¼šç”¨äºŽä»»åŠ¡å®šä½å’Œè½¦è¾†è·Ÿè¸ª
          </text>
          <text class="section-text indent">
            Â· è®¾å¤‡ä¿¡æ¯ï¼šç”¨äºŽç³»ç»Ÿä¼˜åŒ–和问题排查
          </text>
          <text class="section-text indent">
            Â· æ“ä½œæ—¥å¿—:用于服务改进和安全保障
          </text>
          <text class="section-text">
            4.3 æœªç»æ‚¨åŒæ„ï¼Œæˆ‘们不会向第三方提供、出售、出租、分享或交易您的个人信息。
          </text>
        </view>
        <view class="section">
          <text class="section-title">五、知识产权</text>
          <text class="section-text">
            5.1 æœ¬ç³»ç»ŸåŠå…¶åŒ…含的所有内容(包括但不限于文字、图片、软件、程序、数据等)的知识产权均归我们所有或已获得合法授权。
          </text>
          <text class="section-text">
            5.2 æœªç»æˆ‘们书面许可,您不得以任何形式复制、传播、展示、镜像、上传、下载本系统的任何内容。
          </text>
          <text class="section-text">
            5.3 æ‚¨åœ¨ä½¿ç”¨æœ¬ç³»ç»Ÿè¿‡ç¨‹ä¸­åˆ›å»ºçš„任务数据、操作记录等,其使用权归您所有,但我们有权将其用于统计分析、服务改进等目的。
          </text>
        </view>
        <view class="section">
          <text class="section-title">六、服务中断或终止</text>
          <text class="section-text">
            6.1 åœ¨ä»¥ä¸‹æƒ…况下,我们有权中断或终止向您提供服务:
          </text>
          <text class="section-text indent">
            Â· æ‚¨è¿åæœ¬åè®®çš„任何约定
          </text>
          <text class="section-text indent">
            Â· ç³»ç»Ÿç»´æŠ¤ã€å‡çº§éœ€è¦
          </text>
          <text class="section-text indent">
            Â· ä¸å¯æŠ—力或其他不可控因素
          </text>
          <text class="section-text indent">
            Â· æ”¿åºœéƒ¨é—¨ã€å¸æ³•机关的要求
          </text>
          <text class="section-text">
            6.2 å› ç³»ç»Ÿç»´æŠ¤æˆ–升级等原因需要暂停服务的,我们将尽可能事先通知您。
          </text>
          <text class="section-text">
            6.3 å¦‚果您不再使用本系统,可以申请注销账号。账号注销后,您将无法再使用该账号,且无法恢复相关数据。
          </text>
        </view>
        <view class="section">
          <text class="section-title">七、免责声明</text>
          <text class="section-text">
            7.1 æœ¬ç³»ç»Ÿä»…作为急救转运调度管理工具,我们对以下情况不承担责任:
          </text>
          <text class="section-text indent">
            Â· å› ç”¨æˆ·æ“ä½œä¸å½“导致的任何损失
          </text>
          <text class="section-text indent">
            Â· å› ç½‘络故障、设备故障等技术原因导致的服务中断
          </text>
          <text class="section-text indent">
            Â· å› ä¸å¯æŠ—力导致的服务中断或数据丢失
          </text>
          <text class="section-text indent">
            Â· ç”¨æˆ·ä¹‹é—´å› ä½¿ç”¨æœ¬ç³»ç»Ÿäº§ç”Ÿçš„纠纷
          </text>
          <text class="section-text">
            7.2 æœ¬ç³»ç»Ÿæä¾›çš„定位、导航等功能仅供参考,实际执行任务时请以现场实际情况为准。
          </text>
          <text class="section-text">
            7.3 æˆ‘们对本系统中第三方提供的服务或内容不承担责任。
          </text>
        </view>
        <view class="section">
          <text class="section-title">八、协议变更</text>
          <text class="section-text">
            8.1 æˆ‘们有权根据需要修改本协议的内容,修改后的协议将在系统内公布。
          </text>
          <text class="section-text">
            8.2 å¦‚果您不同意修改后的协议内容,您有权停止使用本系统。如果您继续使用本系统,则视为您接受修改后的协议。
          </text>
        </view>
        <view class="section">
          <text class="section-title">九、争议解决</text>
          <text class="section-text">
            9.1 æœ¬åè®®çš„订立、执行和解释及争议的解决均应适用中华人民共和国法律。
          </text>
          <text class="section-text">
            9.2 å¦‚双方就本协议内容或其执行发生任何争议,双方应尽量友好协商解决;协商不成时,任何一方均可向我们所在地人民法院提起诉讼。
          </text>
        </view>
        <view class="section">
          <text class="section-title">十、其他</text>
          <text class="section-text">
            10.1 æœ¬åè®®æž„成您与我们之间关于使用本系统的完整协议,取代双方之前就相同事项达成的任何口头或书面协议。
          </text>
          <text class="section-text">
            10.2 å¦‚本协议的任何条款被视为无效或无法执行,该条款应予以删除,其余条款继续有效。
          </text>
          <text class="section-text">
            10.3 æˆ‘们对本协议拥有最终解释权。
          </text>
        </view>
        <view class="section">
          <text class="section-title">十一、联系我们</text>
          <text class="section-text">
            å¦‚您对本协议有任何疑问、意见或建议,请通过以下方式联系我们:
          </text>
          <text class="section-text">
            ç”µå­é‚®ç®±ï¼šwanglizhong@966129.com.cn
          </text>
          <text class="section-text">
            å®¢æœç”µè¯ï¼š966120
          </text>
          <text class="section-text">
            å·¥ä½œæ—¶é—´ï¼šå‘¨ä¸€è‡³å‘¨æ—¥ 24小时
          </text>
        </view>
        <view class="footer">
          <text class="footer-text">再次感谢您选择使用广东民航调度系统!</text>
        </view>
      </view>
    </scroll-view>
  </view>
</template>
<script>
  export default {
    data() {
      return {}
    },
    methods: {
      goBack() {
        uni.navigateBack()
      }
    }
  }
</script>
<style lang="scss">
  .agreement-container {
    height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: #f5f5f5;
    .header {
      display: flex;
      align-items: center;
      padding: 20rpx;
      background-color: white;
      border-bottom: 1rpx solid #f0f0f0;
      .back-btn {
        width: 60rpx;
        height: 60rpx;
        border-radius: 50%;
        background-color: #f0f0f0;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 20rpx;
      }
      .title {
        font-size: 36rpx;
        font-weight: bold;
        color: #333;
      }
    }
    .content {
      flex: 1;
      padding: 30rpx;
    }
    .agreement-content {
      background-color: white;
      border-radius: 15rpx;
      padding: 40rpx 30rpx;
      .update-time,
      .effect-time {
        font-size: 24rpx;
        color: #999;
        margin-bottom: 10rpx;
      }
      .section {
        margin-top: 40rpx;
        &:first-child {
          margin-top: 30rpx;
        }
        .section-title {
          display: block;
          font-size: 32rpx;
          font-weight: bold;
          color: #333;
          margin-bottom: 20rpx;
          line-height: 1.5;
        }
        .section-text {
          display: block;
          font-size: 28rpx;
          color: #666;
          line-height: 1.8;
          margin-bottom: 15rpx;
          text-align: justify;
          &.indent {
            padding-left: 40rpx;
            position: relative;
            &::before {
              content: '';
              position: absolute;
              left: 20rpx;
              top: 18rpx;
              width: 8rpx;
              height: 8rpx;
              background-color: #666;
              border-radius: 50%;
            }
          }
        }
      }
      .footer {
        margin-top: 60rpx;
        padding-top: 40rpx;
        border-top: 1rpx solid #f0f0f0;
        text-align: center;
        .footer-text {
          font-size: 28rpx;
          color: #007AFF;
          font-weight: bold;
        }
      }
    }
  }
</style>
app/pages/register.vue
@@ -25,6 +25,22 @@
          <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
        </view>
      </view>
      <!-- åè®®åŒæ„ -->
      <view class="agreement-section">
        <checkbox-group @change="handleAgreementChange">
          <label class="agreement-label">
            <checkbox value="agreed" :checked="agreedToTerms" color="#007AFF" />
            <text class="agreement-text">
              æˆ‘已阅读并同意
              <text class="agreement-link" @click.stop="handleUserAgreement">《用户服务协议》</text>
              å’Œ
              <text class="agreement-link" @click.stop="handlePrivacy">《隐私政策》</text>
            </text>
          </label>
        </checkbox-group>
      </view>
      <view class="action-btn">
        <button @click="handleRegister()" class="register-btn cu-btn block bg-blue lg round">注册</button>
      </view>
@@ -43,6 +59,7 @@
      return {
        codeUrl: "",
        captchaEnabled: true,
        agreedToTerms: false,
        globalConfig: getApp().globalData.config,
        registerForm: {
          username: "",
@@ -60,6 +77,18 @@
      // ç”¨æˆ·ç™»å½•
      handleUserLogin() {
        this.$tab.navigateTo(`/pages/login`)
      },
      // åè®®é€‰æ‹©å˜æ›´
      handleAgreementChange(e) {
        this.agreedToTerms = e.detail.value.length > 0
      },
      // ç”¨æˆ·åè®®
      handleUserAgreement() {
        this.$tab.navigateTo('/pages/mine/user-agreement/index')
      },
      // éšç§æ”¿ç­–
      handlePrivacy() {
        this.$tab.navigateTo('/pages/mine/privacy-policy/index')
      },
      // èŽ·å–å›¾å½¢éªŒè¯ç 
      getCode() {
@@ -83,6 +112,8 @@
          this.$modal.msgError("两次输入的密码不一致")
        } else if (this.registerForm.code === "" && this.captchaEnabled) {
          this.$modal.msgError("请输入验证码")
        } else if (!this.agreedToTerms) {
          this.$modal.msgError("请先阅读并同意用户服务协议和隐私政策")
        } else {
          this.$modal.loading("注册中,请耐心等待...")
          this.register()
@@ -179,6 +210,38 @@
        margin-top: 20px;
      }
      
      .agreement-section {
        margin: 30rpx 0;
        .agreement-label {
          display: flex;
          align-items: flex-start;
          checkbox {
            margin-right: 15rpx;
            transform: scale(0.9);
            flex-shrink: 0;
          }
          .agreement-text {
            flex: 1;
            font-size: 26rpx;
            color: #666;
            line-height: 2;
            text-align: left;
            .agreement-link {
              color: #007AFF;
              text-decoration: underline;
              padding: 8rpx 5rpx;
              display: inline-block;
              position: relative;
              z-index: 10;
            }
          }
        }
      }
      .login-code {
        height: 38px;
        float: right;
app/pages/task/detail.vue
@@ -20,7 +20,7 @@
        </view>
        <view class="info-item">
          <view class="label">任务状态</view>
          <view class="value status" :class="taskDetail.taskStatus.toLowerCase()">
          <view class="value status" :class="taskDetail.taskStatus === 'PENDING' ? 'pending' : taskDetail.taskStatus === 'DEPARTING' ? 'in_progress' : taskDetail.taskStatus === 'ARRIVED' ? 'in_progress' : taskDetail.taskStatus === 'RETURNING' ? 'in_progress' : taskDetail.taskStatus === 'IN_PROGRESS' ? 'in_progress' : taskDetail.taskStatus === 'COMPLETED' ? 'completed' : taskDetail.taskStatus === 'CANCELLED' ? 'cancelled' : ''">
            {{ getStatusText(taskDetail.taskStatus) }}
          </view>
        </view>
app/pages/task/index.vue
@@ -113,7 +113,7 @@
              <!-- ä»»åŠ¡å¤´éƒ¨ï¼šæ ‡é¢˜å’ŒçŠ¶æ€æ ‡ç­¾ -->
              <view class="task-header">
                <view class="task-title">{{ getTaskTypeText(task.taskType) }} - {{ task.vehicle }}</view>
                <view class="task-status" :class="getStatusClass(task.taskStatus)">
                <view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
                  {{ getStatusText(task.taskStatus) }}
                </view>
              </view>
app/permission.js
@@ -5,7 +5,11 @@
  
// é¡µé¢ç™½åå•
const whiteList = [
  '/pages/login', '/pages/register', '/pages/common/webview/index'
  '/pages/login',
  '/pages/register',
  '/pages/common/webview/index',
  '/pages/mine/privacy-policy/index',  // éšç§æ”¿ç­–(匿名访问)
  '/pages/mine/user-agreement/index'   // ç”¨æˆ·åè®®ï¼ˆåŒ¿åè®¿é—®ï¼‰
]
// æ£€æŸ¥åœ°å€ç™½åå•
app/С³ÌÐò±¾µØµ÷ÊÔÅäÖÃÖ¸ÄÏ.md
New file
@@ -0,0 +1,598 @@
# å¾®ä¿¡å°ç¨‹åºæœ¬åœ°æŽ¥å£è°ƒè¯•配置指南
## ä¸€ã€å½“前配置状态
### 1.1 åŽç«¯æŽ¥å£åœ°å€é…ç½®
**文件位置**: `app/config.js`
```javascript
module.exports = {
  baseUrl: 'http://localhost:8080',  // âœ… å·²é…ç½®ä¸ºæœ¬åœ°æŽ¥å£
  // ...其他配置
}
```
### 1.2 é—®é¢˜è¯´æ˜Ž
微信小程序默认**不允许访问本地接口**(localhost æˆ– 127.0.0.1),会报以下错误:
```
request:fail url not in domain list
// æˆ–
request:fail -104:net::ERR_CONNECTION_FAILED
```
## äºŒã€è§£å†³æ–¹æ¡ˆï¼ˆ3种方法)
### æ–¹æ¡ˆ1:开发者工具中关闭域名校验(推荐用于开发调试)
这是最简单快速的方法,适合本地开发调试。
#### æ­¥éª¤ï¼š
1. **打开微信开发者工具**
   - ç¡®ä¿å·²å®‰è£…微信开发者工具
   - å¯¼å…¥é¡¹ç›®ï¼šé€‰æ‹© `app` ç›®å½•
2. **关闭域名校验**
   - ç‚¹å‡»å³ä¸Šè§’"详情"按钮
   - åˆ‡æ¢åˆ°"本地设置"选项卡
   - å‹¾é€‰ âœ… **不校验合法域名、web-view(业务域名)、TLS ç‰ˆæœ¬ä»¥åŠ HTTPS è¯ä¹¦**
3. **确认配置生效**
   ```javascript
   // app/config.js ä¿æŒ
   baseUrl: 'http://localhost:8080'
   ```
4. **重新编译**
   - ç‚¹å‡»"编译"按钮
   - æŸ¥çœ‹æŽ§åˆ¶å°æ˜¯å¦æœ‰ç½‘络请求
#### ä¼˜ç‚¹ï¼š
- âœ… é…ç½®ç®€å•,立即生效
- âœ… é€‚合开发调试
- âœ… ä¸éœ€è¦ä¿®æ”¹ä»£ç 
#### ç¼ºç‚¹ï¼š
- âŒ ä»…在开发者工具中有效
- âŒ çœŸæœºé¢„览时无效
- âŒ æ­£å¼ç‰ˆæœ¬å¿…须配置合法域名
---
### æ–¹æ¡ˆ2:使用内网IP地址(推荐用于真机调试)
使用电脑的内网IP地址替代localhost,可以让手机访问电脑上的后端服务。
#### æ­¥éª¤ï¼š
1. **查找电脑内网IP**
   **Windows系统**:
   ```bash
   # å‘½ä»¤è¡Œæ‰§è¡Œ
   ipconfig
   # æŸ¥æ‰¾ç±»ä¼¼è¿™æ ·çš„地址
   IPv4 åœ°å€ . . . . . . . . . . . . : 192.168.1.100
   ```
   **Mac/Linux系统**:
   ```bash
   # ç»ˆç«¯æ‰§è¡Œ
   ifconfig
   # æˆ–
   ip addr show
   # æŸ¥æ‰¾ä»¥ 192.168.x.x æˆ– 10.x.x.x å¼€å¤´çš„地址
   ```
2. **修改配置文件**
   **方法A:直接修改config.js(简单但不灵活)**
   ```javascript
   // app/config.js
   module.exports = {
     baseUrl: 'http://192.168.1.100:8080',  // æ”¹ä¸ºä½ çš„内网IP
     // ...
   }
   ```
   **方法B:环境变量配置(推荐)**
   ```javascript
   // app/config.js
   module.exports = {
     // æ ¹æ®è¿è¡ŒçŽ¯å¢ƒè‡ªåŠ¨é€‰æ‹©
     baseUrl: process.env.NODE_ENV === 'development'
       ? 'http://192.168.1.100:8080'  // å¼€å‘环境:内网IP
       : 'https://api.yourdomain.com',  // ç”Ÿäº§çŽ¯å¢ƒï¼šçº¿ä¸ŠåŸŸå
     // ...
   }
   ```
3. **确保后端允许跨域访问**
   æ£€æŸ¥åŽç«¯é…ç½®ï¼ˆRuoYi框架默认已配置):
   ```java
   // ruoyi-framework/src/main/java/com/ruoyi/framework/config/CorsConfig.java
   @Override
   public void addCorsMappings(CorsRegistry registry) {
       registry.addMapping("/**")
           .allowedOriginPatterns("*")  // å…è®¸æ‰€æœ‰æ¥æº
           .allowCredentials(true)
           .allowedMethods("GET", "POST", "PUT", "DELETE")
           .maxAge(3600);
   }
   ```
4. **确保电脑防火墙允许访问**
   **Windows防火墙**:
   - æŽ§åˆ¶é¢æ¿ â†’ Windows Defender é˜²ç«å¢™ â†’ é«˜çº§è®¾ç½®
   - å…¥ç«™è§„则 â†’ æ–°å»ºè§„则 â†’ ç«¯å£ â†’ TCP â†’ ç‰¹å®šç«¯å£ 8080
   - å…è®¸è¿žæŽ¥
   **临时关闭防火墙测试**:
   ```bash
   # Windows(管理员权限)
   netsh advfirewall set allprofiles state off
   # æµ‹è¯•完成后记得打开
   netsh advfirewall set allprofiles state on
   ```
5. **手机和电脑连接同一WiFi**
   - ç¡®ä¿æ‰‹æœºå’Œç”µè„‘在同一局域网
   - æ‰“开微信开发者工具 â†’ é¢„览 â†’ æ‰«ç çœŸæœºè°ƒè¯•
#### ä¼˜ç‚¹ï¼š
- âœ… å¯ä»¥çœŸæœºè°ƒè¯•
- âœ… å›¢é˜Ÿæˆå‘˜å¯ä»¥å…±äº«è°ƒè¯•
- âœ… æŽ¥è¿‘真实环境
#### ç¼ºç‚¹ï¼š
- âŒ IP地址可能会变化
- âŒ éœ€è¦é…ç½®é˜²ç«å¢™
- âŒ ä»…限同一局域网
---
### æ–¹æ¡ˆ3:使用内网穿透工具(推荐用于远程调试)
使用内网穿透工具(如花生壳、ngrok、FRP)将本地服务映射到公网域名。
#### 3.1 ä½¿ç”¨ ngrok(免费且简单)
1. **下载安装 ngrok**
   - å®˜ç½‘:https://ngrok.com/
   - ä¸‹è½½å¯¹åº”系统版本
   - æ³¨å†Œè´¦å·èŽ·å–authtoken
2. **启动后端服务**
   ```bash
   # ç¡®ä¿åŽç«¯è¿è¡Œåœ¨8080端口
   cd RuoYi-Vue-master
   java -jar ruoyi-admin.jar
   ```
3. **启动 ngrok**
   ```bash
   # Windows
   ngrok.exe http 8080
   # Mac/Linux
   ./ngrok http 8080
   ```
4. **获取公网地址**
   ```
   Session Status    online
   Forwarding        https://abc123.ngrok.io -> http://localhost:8080
                     ^^^^^^^^^^^^^^^^^^^^^^^^
                     è¿™å°±æ˜¯ä½ çš„公网地址
   ```
5. **修改配置**
   ```javascript
   // app/config.js
   module.exports = {
     baseUrl: 'https://abc123.ngrok.io',  // ngrok提供的地址
     // ...
   }
   ```
6. **在微信小程序后台配置域名**
   - ç™»å½•微信公众平台:https://mp.weixin.qq.com
   - å¼€å‘ â†’ å¼€å‘管理 â†’ å¼€å‘设置 â†’ æœåŠ¡å™¨åŸŸå
   - é…ç½® request合法域名:`https://abc123.ngrok.io`
#### 3.2 ä½¿ç”¨èŠ±ç”Ÿå£³ï¼ˆå›½å†…ç¨³å®šï¼‰
1. **下载安装花生壳**
   - å®˜ç½‘:https://hsk.oray.com/
   - æ³¨å†Œè´¦å·
2. **创建内网穿透映射**
   - å†…网主机:localhost
   - å†…网端口:8080
   - å¤–网域名:系统分配(如 xxx.vicp.fun)
3. **修改配置**
   ```javascript
   // app/config.js
   module.exports = {
     baseUrl: 'http://xxx.vicp.fun',  // èŠ±ç”Ÿå£³æä¾›çš„åŸŸå
     // ...
   }
   ```
#### ä¼˜ç‚¹ï¼š
- âœ… å¯ä»¥è¿œç¨‹è®¿é—®
- âœ… ç¨³å®šçš„域名
- âœ… æ”¯æŒHTTPS
#### ç¼ºç‚¹ï¼š
- âŒ éœ€è¦ç¬¬ä¸‰æ–¹æœåŠ¡
- âŒ å…è´¹ç‰ˆæœ‰é™åˆ¶
- âŒ å¯èƒ½æœ‰å»¶è¿Ÿ
---
## ä¸‰ã€æŽ¨èé…ç½®æ–¹æ¡ˆ
### 3.1 å¤šçŽ¯å¢ƒé…ç½®ï¼ˆæœ€ä½³å®žè·µï¼‰
修改 `app/config.js`,支持多环境自动切换:
```javascript
// app/config.js
// çŽ¯å¢ƒé…ç½®
const ENV_CONFIG = {
  // å¼€å‘环境
  development: {
    baseUrl: 'http://192.168.1.100:8080',  // ä¿®æ”¹ä¸ºä½ çš„内网IP
    description: '开发环境'
  },
  // æµ‹è¯•环境
  test: {
    baseUrl: 'http://test.yourdomain.com',
    description: '测试环境'
  },
  // ç”Ÿäº§çŽ¯å¢ƒ
  production: {
    baseUrl: 'https://api.yourdomain.com',
    description: '生产环境'
  }
}
// å½“前环境(手动切换)
const CURRENT_ENV = 'development'  // å¯é€‰: development, test, production
// å¯¼å‡ºé…ç½®
module.exports = {
  baseUrl: ENV_CONFIG[CURRENT_ENV].baseUrl,
  // åº”用信息
  appInfo: {
    name: "民航调度系统",
    version: "1.1.0",
    logo: "/static/logo.png",
    site_url: "http://ruoyi.vip",
    // çŽ¯å¢ƒä¿¡æ¯ï¼ˆç”¨äºŽè°ƒè¯•ï¼‰
    env: CURRENT_ENV,
    envDescription: ENV_CONFIG[CURRENT_ENV].description,
    // åè®®ï¼ˆä½¿ç”¨æœ¬åœ°é¡µé¢ï¼‰
    agreements: [
      {
        title: "隐私政策",
        url: "/pages/mine/privacy-policy/index"
      },
      {
        title: "用户服务协议",
        url: "/pages/mine/user-agreement/index"
      }
    ]
  }
}
```
### 3.2 æ˜¾ç¤ºå½“前环境信息(调试用)
在首页显示当前使用的接口地址:
```vue
<!-- app/pages/index.vue -->
<template>
  <view>
    <!-- å¼€å‘环境提示 -->
    <view v-if="isDev" class="dev-info">
      <text>{{ envInfo }}</text>
    </view>
    <!-- ...其他内容 -->
  </view>
</template>
<script>
export default {
  data() {
    return {
      isDev: process.env.NODE_ENV === 'development',
      envInfo: ''
    }
  },
  onLoad() {
    const config = getApp().globalData.config
    this.envInfo = `环境:${config.appInfo.envDescription}\n接口:${config.baseUrl}`
  }
}
</script>
<style>
.dev-info {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(255, 0, 0, 0.8);
  color: white;
  padding: 10rpx;
  font-size: 20rpx;
  text-align: center;
  z-index: 9999;
}
</style>
```
---
## å››ã€å®Œæ•´é…ç½®æ­¥éª¤ï¼ˆæŽ¨èæµç¨‹ï¼‰
### æ­¥éª¤1: å¯åŠ¨åŽç«¯æœåŠ¡
```bash
# è¿›å…¥åŽç«¯é¡¹ç›®ç›®å½•
cd d:\project\急救转运\code\Api\RuoYi-Vue-master
# å¯åŠ¨åŽç«¯ï¼ˆç¡®ä¿ç«¯å£8080)
# æ–¹æ³•1: IDEA直接运行 RuoYiApplication.java
# æ–¹æ³•2: å‘½ä»¤è¡Œè¿è¡Œ
mvn spring-boot:run
```
### æ­¥éª¤2: æŸ¥æ‰¾ç”µè„‘内网IP
```bash
# Windows
ipconfig
# æ‰¾åˆ°ç±»ä¼¼è¿™æ ·çš„地址
以太网适配器 ä»¥å¤ªç½‘:
   IPv4 åœ°å€ . . . . . . . . . . . . : 192.168.1.100
```
### æ­¥éª¤3: ä¿®æ”¹é…ç½®æ–‡ä»¶
```javascript
// app/config.js
module.exports = {
  baseUrl: 'http://192.168.1.100:8080',  // æ”¹ä¸ºä½ çš„IP
  // ...
}
```
### æ­¥éª¤4: å¾®ä¿¡å¼€å‘者工具配置
1. **打开项目**
   - HBuilderX â†’ è¿è¡Œ â†’ è¿è¡Œåˆ°å°ç¨‹åºæ¨¡æ‹Ÿå™¨ â†’ å¾®ä¿¡å¼€å‘者工具
   - æˆ–直接在微信开发者工具中导入 `app` ç›®å½•
2. **关闭域名校验**
   - è¯¦æƒ… â†’ æœ¬åœ°è®¾ç½®
   - âœ… å‹¾é€‰"不校验合法域名..."
3. **清除缓存重新编译**
   - å·¥å…· â†’ æ¸…除缓存 â†’ æ¸…除所有缓存
   - ç‚¹å‡»"编译"
### æ­¥éª¤5: éªŒè¯é…ç½®
1. **检查网络请求**
   - æ‰“开调试器 â†’ Network
   - ç™»å½•系统,查看请求地址是否正确
2. **测试接口**
   ```javascript
   // åœ¨æŽ§åˆ¶å°æ‰§è¡Œ
   console.log(getApp().globalData.config.baseUrl)
   // åº”该输出: http://192.168.1.100:8080
   ```
---
## äº”、常见问题排查
### é—®é¢˜1: request:fail url not in domain list
**原因**: åŸŸåæ ¡éªŒæœªå…³é—­
**解决**:
- å¾®ä¿¡å¼€å‘者工具 â†’ è¯¦æƒ… â†’ æœ¬åœ°è®¾ç½®
- âœ… å‹¾é€‰"不校验合法域名..."
---
### é—®é¢˜2: request:fail -104:net::ERR_CONNECTION_FAILED
**原因**:
1. åŽç«¯æœåŠ¡æœªå¯åŠ¨
2. IP地址错误
3. é˜²ç«å¢™é˜»æ­¢
**解决**:
```bash
# 1. æ£€æŸ¥åŽç«¯æ˜¯å¦å¯åЍ
netstat -ano | findstr 8080
# 2. æ£€æŸ¥IP是否正确
ipconfig
# 3. æµ‹è¯•后端是否可访问
# æµè§ˆå™¨æ‰“å¼€: http://192.168.1.100:8080
```
---
### é—®é¢˜3: çœŸæœºè°ƒè¯•无法访问
**原因**: æ‰‹æœºå’Œç”µè„‘不在同一WiFi
**解决**:
1. ç¡®ä¿æ‰‹æœºå’Œç”µè„‘连接同一WiFi
2. ä½¿ç”¨å†…网IP而非localhost
3. æ£€æŸ¥é˜²ç«å¢™è®¾ç½®
---
### é—®é¢˜4: è·¨åŸŸé”™è¯¯
**原因**: åŽç«¯æœªé…ç½®è·¨åŸŸ
**解决**:
```java
// ruoyi-framework/src/main/java/com/ruoyi/framework/config/CorsConfig.java
// ç¡®ä¿å·²é…ç½®CORS
```
---
## å…­ã€ä¸åŒå¼€å‘工具的配置
### 6.1 HBuilderX
1. **运行到微信小程序**
   - èœå• â†’ è¿è¡Œ â†’ è¿è¡Œåˆ°å°ç¨‹åºæ¨¡æ‹Ÿå™¨ â†’ å¾®ä¿¡å¼€å‘者工具
2. **配置微信开发者工具路径**
   - å·¥å…· â†’ è®¾ç½® â†’ è¿è¡Œé…ç½®
   - é…ç½®"微信开发者工具路径"
3. **manifest.json配置**
   - æºç è§†å›¾ â†’ mp-weixin â†’ appid
   - å¡«å†™ä½ çš„小程序AppID
### 6.2 ç›´æŽ¥ä½¿ç”¨å¾®ä¿¡å¼€å‘者工具
1. **导入项目**
   - æ‰“开微信开发者工具
   - é€‰æ‹©"导入项目"
   - é¡¹ç›®ç›®å½•:`app`
   - AppID:使用测试号或你的AppID
2. **配置**
   - è¯¦æƒ… â†’ æœ¬åœ°è®¾ç½® â†’ ä¸æ ¡éªŒåŸŸå
---
## ä¸ƒã€æŽ¨èé…ç½®ï¼ˆæœ€ç»ˆç‰ˆæœ¬ï¼‰
```javascript
// app/config.js - å®Œæ•´é…ç½®ç¤ºä¾‹
// è‡ªåŠ¨æ£€æµ‹è¿è¡ŒçŽ¯å¢ƒ
const isDev = process.env.NODE_ENV === 'development'
const isMP = process.env.VUE_APP_PLATFORM === 'mp-weixin'
// èŽ·å–æœ¬åœ°IP(需要手动配置)
const LOCAL_IP = '192.168.1.100'  // âš ï¸ ä¿®æ”¹ä¸ºä½ çš„电脑IP
// çŽ¯å¢ƒé…ç½®
const ENV_CONFIG = {
  // æœ¬åœ°å¼€å‘
  local: `http://${LOCAL_IP}:8080`,
  // æµ‹è¯•环境
  test: 'http://test.yourdomain.com',
  // ç”Ÿäº§çŽ¯å¢ƒ
  prod: 'https://api.yourdomain.com'
}
// è‡ªåŠ¨é€‰æ‹©çŽ¯å¢ƒ
let baseUrl = ENV_CONFIG.local  // é»˜è®¤æœ¬åœ°å¼€å‘
// æ ¹æ®ä¸åŒæ¡ä»¶é€‰æ‹©çŽ¯å¢ƒ
if (process.env.UNI_PLATFORM === 'h5' && !isDev) {
  // H5生产环境
  baseUrl = ENV_CONFIG.prod
}
module.exports = {
  baseUrl: baseUrl,
  appInfo: {
    name: "民航调度系统",
    version: "1.1.0",
    logo: "/static/logo.png",
    site_url: "http://ruoyi.vip",
    // æ˜¾ç¤ºå½“前环境(开发时可见)
    showEnv: isDev,
    currentEnv: baseUrl,
    agreements: [
      {
        title: "隐私政策",
        url: "/pages/mine/privacy-policy/index"
      },
      {
        title: "用户服务协议",
        url: "/pages/mine/user-agreement/index"
      }
    ]
  }
}
```
---
## å…«ã€æ€»ç»“
### å¼€å‘阶段推荐方案
| åœºæ™¯ | æŽ¨èæ–¹æ¡ˆ | é…ç½®å¤æ‚度 |
|------|----------|-----------|
| å¾®ä¿¡å¼€å‘者工具调试 | æ–¹æ¡ˆ1 + localhost | â­ ç®€å• |
| çœŸæœºè°ƒè¯• | æ–¹æ¡ˆ2 + å†…网IP | â­â­ ä¸­ç­‰ |
| è¿œç¨‹è°ƒè¯•/演示 | æ–¹æ¡ˆ3 + å†…网穿透 | â­â­â­ å¤æ‚ |
### å¿«é€Ÿå¼€å§‹ï¼ˆæœ€ç®€å•方式)
1. **启动后端**: è¿è¡Œ RuoYiApplication.java
2. **配置前端**: `config.js` ä¸­ `baseUrl: 'http://localhost:8080'`
3. **微信工具**: å‹¾é€‰"不校验合法域名"
4. **开始调试**: ç‚¹å‡»"编译"
### æ³¨æ„äº‹é¡¹
⚠️ **安全提醒**:
- ç”Ÿäº§çŽ¯å¢ƒå¿…é¡»ä½¿ç”¨HTTPS域名
- ä¸è¦å°†æµ‹è¯•配置提交到代码仓库
- ä½¿ç”¨ `.env` æ–‡ä»¶ç®¡ç†æ•æ„Ÿé…ç½®
⚠️ **性能提醒**:
- å†…网穿透会增加延迟
- å»ºè®®ä¼˜å…ˆä½¿ç”¨å±€åŸŸç½‘调试
- å¤§æ–‡ä»¶ä¸Šä¼ å»ºè®®ä½¿ç”¨ç›´è¿ž
---
如有其他问题,请参考:
- å¾®ä¿¡å°ç¨‹åºå®˜æ–¹æ–‡æ¡£ï¼šhttps://developers.weixin.qq.com/miniprogram/dev/
- uni-app官方文档:https://uniapp.dcloud.io/
app/¿ìËÙÅäÖÃÇåµ¥.md
New file
@@ -0,0 +1,266 @@
# å¾®ä¿¡å°ç¨‹åºæœ¬åœ°è°ƒè¯• - å¿«é€Ÿé…ç½®æ¸…单
## âœ… é…ç½®æ­¥éª¤ï¼ˆ5分钟完成)
### ç¬¬1步:查找电脑IP地址(1分钟)
**Windows系统**:
```bash
# æ‰“开命令提示符(Win+R,输入cmd)
ipconfig
# æ‰¾åˆ°è¿™ä¸€è¡Œï¼š
IPv4 åœ°å€ . . . . . . . . . . . . : 192.168.1.100
                                    â†‘↑↑↑↑↑↑↑↑↑↑↑↑↑
                                    è®°ä¸‹è¿™ä¸ªIP地址
```
**Mac系统**:
```bash
# æ‰“开终端
ifconfig
# æ‰¾åˆ° en0 æˆ– en1 ä¸‹çš„ inet åœ°å€
inet 192.168.1.100
     â†‘↑↑↑↑↑↑↑↑↑↑↑↑↑
     è®°ä¸‹è¿™ä¸ªIP地址
```
---
### ç¬¬2步:修改配置文件(30秒)
打开文件:`app/config.js`
找到第6行,修改为你的IP:
```javascript
// ä¿®æ”¹å‰
const LOCAL_IP = 'localhost'
// ä¿®æ”¹åŽï¼ˆå¡«å…¥ä½ åˆšæ‰è®°ä¸‹çš„IP)
const LOCAL_IP = '192.168.1.100'  // âš ï¸ æ”¹æˆä½ çš„IP
```
保存文件。
---
### ç¬¬3步:启动后端服务(1分钟)
**方法1:使用IDEA**
- æ‰“开项目 `RuoYi-Vue-master`
- æ‰¾åˆ° `ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java`
- ç‚¹å‡»è¿è¡ŒæŒ‰é’® â–¶ï¸
- ç­‰å¾…启动完成,看到 `Application Run Successfully`
**方法2:命令行**
```bash
cd d:\project\急救转运\code\Api\RuoYi-Vue-master
mvn spring-boot:run
```
**验证后端是否启动**:
- æµè§ˆå™¨æ‰“开:http://localhost:8080
- åº”该看到若依系统的登录页面
---
### ç¬¬4步:配置微信开发者工具(2分钟)
1. **打开微信开发者工具**
   - å¦‚果没有安装,下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
2. **导入项目**
   - ç‚¹å‡»"+"号 â†’ å¯¼å…¥é¡¹ç›®
   - ç›®å½•:`d:\project\急救转运\code\Api\RuoYi-Vue-master\app`
   - AppID:使用测试号(或填入你的AppID)
   - é¡¹ç›®åç§°ï¼šæ€¥æ•‘转运调度系统
3. **关闭域名校验**(重要!)
   - ç‚¹å‡»å³ä¸Šè§’"详情"
   - åˆ‡æ¢åˆ°"本地设置"标签
   - âœ… å‹¾é€‰"不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书"
4. **编译运行**
   - ç‚¹å‡»"编译"按钮
   - ç­‰å¾…编译完成
---
### ç¬¬5步:测试验证(1分钟)
1. **测试登录**
   - åœ¨å°ç¨‹åºæ¨¡æ‹Ÿå™¨ä¸­è¾“入账号密码
   - è´¦å·ï¼š`admin`
   - å¯†ç ï¼š`admin123`
   - ç‚¹å‡»ç™»å½•
2. **检查网络请求**
   - æ‰“开调试器 â†’ Network æ ‡ç­¾
   - åº”该能看到请求发送到:`http://192.168.1.100:8080/...`
3. **如果登录成功**
   - âœ… é…ç½®å®Œæˆï¼
---
## âŒ å¸¸è§é—®é¢˜å¿«é€Ÿè§£å†³
### é—®é¢˜1:request:fail -104
**原因**:后端没有启动或IP错误
**解决**:
```bash
# 1. æ£€æŸ¥åŽç«¯æ˜¯å¦è¿è¡Œ
浏览器打开: http://192.168.1.100:8080
# 2. å¦‚果打不开,检查IP是否正确
再次执行: ipconfig
# 3. ç¡®ä¿ç«¯å£8080没有被占用
netstat -ano | findstr 8080
```
---
### é—®é¢˜2:request:fail url not in domain list
**原因**:没有关闭域名校验
**解决**:
- å¾®ä¿¡å¼€å‘者工具 â†’ è¯¦æƒ… â†’ æœ¬åœ°è®¾ç½®
- âœ… å‹¾é€‰"不校验合法域名..."
---
### é—®é¢˜3:真机调试无法访问
**原因**:手机和电脑不在同一WiFi
**解决**:
1. ç¡®ä¿æ‰‹æœºå’Œç”µè„‘连接同一WiFi
2. æ£€æŸ¥ç”µè„‘防火墙是否阻止了8080端口
3. ä¸´æ—¶å…³é—­é˜²ç«å¢™æµ‹è¯•:
   ```bash
   # Windows(管理员权限)
   netsh advfirewall set allprofiles state off
   # æµ‹è¯•完成后记得打开
   netsh advfirewall set allprofiles state on
   ```
---
## ðŸ“± çœŸæœºè°ƒè¯•配置
### çœŸæœºé¢„览
1. **微信开发者工具中**
   - ç‚¹å‡»"预览"按钮
   - æ‰«æäºŒç»´ç 
2. **手机连接同一WiFi**
   - ç¡®ä¿æ‰‹æœºå’Œç”µè„‘在同一网络
3. **如果无法访问**
   - æ£€æŸ¥é˜²ç«å¢™è®¾ç½®
   - å°è¯•临时关闭防火墙
---
## ðŸ”§ çŽ¯å¢ƒåˆ‡æ¢
### å¼€å‘环境(本地调试)
```javascript
// app/config.js
const CURRENT_ENV = 'development'  // ä½¿ç”¨æœ¬åœ°IP
```
### æµ‹è¯•环境
```javascript
// app/config.js
const CURRENT_ENV = 'test'  // ä½¿ç”¨æµ‹è¯•服务器
```
需要先在第13-16行配置测试服务器地址:
```javascript
test: {
  baseUrl: 'http://test.yourdomain.com',  // æ”¹ä¸ºå®žé™…地址
  description: '测试环境'
}
```
### ç”Ÿäº§çŽ¯å¢ƒ
```javascript
// app/config.js
const CURRENT_ENV = 'production'  // ä½¿ç”¨çº¿ä¸ŠæœåС噍
```
需要先在第17-20行配置生产服务器地址:
```javascript
production: {
  baseUrl: 'https://api.yourdomain.com',  // æ”¹ä¸ºå®žé™…地址
  description: '生产环境'
}
```
---
## ðŸ“‹ é…ç½®æ£€æŸ¥æ¸…单
开始调试前,请确认:
- [ ] åŽç«¯æœåŠ¡å·²å¯åŠ¨ï¼ˆhttp://localhost:8080 å¯ä»¥è®¿é—®ï¼‰
- [ ] å·²æŸ¥åˆ°ç”µè„‘IP地址
- [ ] config.js ä¸­å·²å¡«å†™æ­£ç¡®çš„IP地址
- [ ] å¾®ä¿¡å¼€å‘者工具已安装
- [ ] å·²å…³é—­åŸŸåæ ¡éªŒ
- [ ] æ‰‹æœºå’Œç”µè„‘在同一WiFi(真机调试时)
---
## ðŸ’¡ æç¤º
### æŸ¥çœ‹å½“前配置
在小程序中打开控制台(Console),执行:
```javascript
console.log(getApp().globalData.config.baseUrl)
// åº”该输出: http://192.168.1.100:8080
```
### æŸ¥çœ‹å½“前环境
```javascript
const config = getApp().globalData.config
console.log('环境:', config.appInfo.envDescription)
console.log('接口:', config.baseUrl)
```
---
## ðŸ“ž éœ€è¦å¸®åŠ©ï¼Ÿ
如果按照以上步骤仍无法解决,请提供:
1. é”™è¯¯æˆªå›¾ï¼ˆæŽ§åˆ¶å° Console å’Œ Network)
2. é…ç½®æ–‡ä»¶å†…容(config.js)
3. åŽç«¯å¯åŠ¨æ—¥å¿—
4. ç”µè„‘IP地址
---
## âœ… é…ç½®æˆåŠŸæ ‡å¿—
当你看到:
- âœ… å°ç¨‹åºèƒ½æ­£å¸¸ç™»å½•
- âœ… Network中能看到请求发送到你的IP地址
- âœ… åŽç«¯èƒ½æ”¶åˆ°è¯·æ±‚并返回数据
恭喜你,配置成功!🎉
prd/uni-appÄ£°åÓï·¨ÐÞ¸´-class°ó¶¨.md
New file
@@ -0,0 +1,279 @@
# uni-app æ¨¡æ¿è¯­æ³•修复 - :class æ–¹æ³•调用问题
## é—®é¢˜æè¿°
编译时遇到以下错误:
```
Module Error (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/templateLoader.js):
(Emitted value instead of an instance of Error)
  Errors compiling template:
  :class不支持 getStatusClass(task.taskStatus) è¯­æ³•
```
## é—®é¢˜åŽŸå› 
在 uni-app çš„æ¨¡æ¿ä¸­ï¼Œ`:class` ä¸æ”¯æŒç›´æŽ¥è°ƒç”¨æ–¹æ³•,例如:
```vue
<!-- âŒ é”™è¯¯å†™æ³• -->
<view class="task-status" :class="getStatusClass(task.taskStatus)">
```
这是 uni-app çš„语法限制,与标准 Vue.js ä¸åŒã€‚
## è§£å†³æ–¹æ¡ˆ
将方法调用改为表达式拼接字符串的形式,使用三元运算符(条件表达式)来实现:
```vue
<!-- âœ… æ­£ç¡®å†™æ³• -->
<view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
```
## ä¿®æ”¹æ–‡ä»¶
### 1. app/pages/index.vue
**修改前:**
```vue
<view class="task-status" :class="getStatusClass(task.taskStatus)">
  {{ getStatusText(task.status) }}
</view>
```
**修改后:**
```vue
<view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
  {{ getStatusText(task.status) }}
</view>
```
### 2. app/pages/task/index.vue
**修改前:**
```vue
<view class="task-status" :class="getStatusClass(task.taskStatus)">
  {{ getStatusText(task.taskStatus) }}
</view>
```
**修改后:**
```vue
<view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
  {{ getStatusText(task.taskStatus) }}
</view>
```
### 3. app/pages/task/detail.vue
**修改前:**
```vue
<view class="value status" :class="taskDetail.taskStatus.toLowerCase()">
  {{ getStatusText(taskDetail.taskStatus) }}
</view>
```
**修改后:**
```vue
<view class="value status" :class="taskDetail.taskStatus === 'PENDING' ? 'pending' : taskDetail.taskStatus === 'DEPARTING' ? 'in_progress' : taskDetail.taskStatus === 'ARRIVED' ? 'in_progress' : taskDetail.taskStatus === 'RETURNING' ? 'in_progress' : taskDetail.taskStatus === 'IN_PROGRESS' ? 'in_progress' : taskDetail.taskStatus === 'COMPLETED' ? 'completed' : taskDetail.taskStatus === 'CANCELLED' ? 'cancelled' : ''">
  {{ getStatusText(taskDetail.taskStatus) }}
</view>
```
**说明:**
- `detail.vue` ä¸­ä½¿ç”¨çš„æ˜¯å°å†™çš„状态类名(`pending`, `in_progress`, `completed`, `cancelled`)
- å°†å¤šä¸ªè¿›è¡Œä¸­çš„状态(`DEPARTING`, `ARRIVED`, `RETURNING`, `IN_PROGRESS`)都映射为 `in_progress` ç±»
## çŠ¶æ€ç±»åæ˜ å°„
原 `getStatusClass` æ–¹æ³•的映射逻辑:
```javascript
getStatusClass(status) {
  const statusClassMap = {
    'PENDING': 'status-pending',        // å¾…处理
    'DEPARTING': 'status-departing',    // å‡ºå‘中
    'ARRIVED': 'status-arrived',        // å·²åˆ°è¾¾
    'RETURNING': 'status-returning',    // è¿”程中
    'COMPLETED': 'status-completed',    // å·²å®Œæˆ
    'CANCELLED': 'status-cancelled',    // å·²å–消
    'IN_PROGRESS': 'status-in-progress' // å¤„理中
  }
  return statusClassMap[status] || 'status-default'
}
```
现在直接在模板中使用三元表达式实现相同的映射逻辑。
## uni-app æ¨¡æ¿è¯­æ³•限制
### ä¸æ”¯æŒçš„语法
1. **方法调用** âŒ
   ```vue
   :class="getStatusClass(task.taskStatus)"
   ```
2. **复杂表达式** âŒ
   ```vue
   :style="{ color: getColor(item.type) }"
   ```
### æ”¯æŒçš„语法
1. **简单属性访问** âœ…
   ```vue
   :class="task.statusClass"
   ```
2. **三元运算符** âœ…
   ```vue
   :class="task.status === 'PENDING' ? 'status-pending' : 'status-default'"
   ```
3. **数组/对象字面量** âœ…
   ```vue
   :class="[task.baseClass, task.statusClass]"
   :class="{ 'active': task.isActive, 'disabled': task.isDisabled }"
   ```
4. **计算属性** âœ…
   ```vue
   :class="taskStatusClass"
   // åœ¨ computed ä¸­å®šä¹‰
   computed: {
     taskStatusClass() {
       return this.getStatusClass(this.task.taskStatus)
     }
   }
   ```
## æ›¿ä»£æ–¹æ¡ˆæ¯”较
### æ–¹æ¡ˆ1:三元运算符(已采用)
**优点:**
- æ— éœ€ä¿®æ”¹ script éƒ¨åˆ†
- é€»è¾‘直观,在模板中可见
**缺点:**
- è¡¨è¾¾å¼è¾ƒé•¿ï¼Œä»£ç å†—ä½™
- å¤šä¸ªçŠ¶æ€æ—¶å¯è¯»æ€§ç¨å·®
### æ–¹æ¡ˆ2:计算属性
```vue
<template>
  <view class="task-status" :class="statusClass">
</template>
<script>
export default {
  computed: {
    statusClass() {
      return this.getStatusClass(this.task.taskStatus)
    }
  }
}
</script>
```
**优点:**
- æ¨¡æ¿æ›´ç®€æ´
- é€»è¾‘封装在 script ä¸­
**缺点:**
- éœ€è¦ä¸ºåˆ—表中每个项目定义计算属性
- åœ¨ `v-for` ä¸­ä½¿ç”¨æ—¶å¤æ‚度较高
### æ–¹æ¡ˆ3:预处理数据
```javascript
loadTasks() {
  listTask(this.queryParams).then(response => {
    this.taskList = response.rows.map(task => ({
      ...task,
      statusClass: this.getStatusClass(task.taskStatus)
    }))
  })
}
```
**优点:**
- æ¨¡æ¿æœ€ç®€æ´
- æ€§èƒ½æœ€å¥½ï¼ˆé¢„计算一次)
**缺点:**
- éœ€è¦åœ¨æ•°æ®åŠ è½½æ—¶å¤„ç†
- å¢žåŠ äº†æ•°æ®å¯¹è±¡çš„å­—æ®µ
## æœ€ä½³å®žè·µ
### å¯¹äºŽåˆ—表渲染(推荐方案1或3)
```vue
<!-- æ–¹æ¡ˆ1:三元运算符 -->
<view v-for="task in taskList" :key="task.id">
  <view :class="task.status === 'PENDING' ? 'status-pending' : 'status-default'">
  </view>
</view>
<!-- æ–¹æ¡ˆ3:预处理数据 -->
<view v-for="task in taskList" :key="task.id">
  <view :class="task.statusClass">
  </view>
</view>
```
### å¯¹äºŽå•个元素(推荐方案2)
```vue
<!-- æ–¹æ¡ˆ2:计算属性 -->
<template>
  <view :class="taskStatusClass">
</template>
<script>
export default {
  computed: {
    taskStatusClass() {
      return this.getStatusClass(this.currentTask.taskStatus)
    }
  }
}
</script>
```
## æ³¨æ„äº‹é¡¹
1. **保留方法定义**
   - è™½ç„¶æ¨¡æ¿ä¸­ä¸èƒ½ç›´æŽ¥è°ƒç”¨ `getStatusClass` æ–¹æ³•
   - ä½†è¯¥æ–¹æ³•仍可用于其他场景(如预处理数据)
   - å»ºè®®ä¿ç•™åœ¨ä»£ç ä¸­
2. **表达式长度**
   - uni-app å¯¹æ¨¡æ¿è¡¨è¾¾å¼æœ‰é•¿åº¦é™åˆ¶
   - è¿‡é•¿çš„表达式可能导致编译警告
   - å»ºè®®ä½¿ç”¨é¢„处理数据方案
3. **性能考虑**
   - ä¸‰å…ƒè¿ç®—符在每次渲染时都会计算
   - å¤§åˆ—表建议使用预处理方案
   - è®¡ç®—属性会缓存结果
## ç›¸å…³æ–‡æ¡£
- [uni-app æ¨¡æ¿è¯­æ³•限制](https://uniapp.dcloud.net.cn/tutorial/vue-api.html#%E6%A8%A1%E6%9D%BF%E8%AF%AD%E6%B3%95)
- [Vue æ¡ä»¶æ¸²æŸ“](https://cn.vuejs.org/guide/essentials/conditional.html)
- [Vue Class ä¸Ž Style ç»‘定](https://cn.vuejs.org/guide/essentials/class-and-style.html)
## æ›´æ–°æ—¥å¿—
- **2025-01-25**: ä¿®å¤ `:class` æ–¹æ³•调用语法错误
  - æ–‡ä»¶: `app/pages/index.vue` (第57行)
  - æ–‡ä»¶: `app/pages/task/index.vue` (第115行)
  - æ–‡ä»¶: `app/pages/task/detail.vue` (第22行)
  - æ–¹æ³•: å°†æ–¹æ³•调用改为三元表达式
  - åŽŸå› : uni-app æ¨¡æ¿ä¸æ”¯æŒæ–¹æ³•调用和 `.toLowerCase()` ç­‰å­—符串方法
prd/ºǫ́ÈÎÎñ¹ÜÀí-¼±¾ÈתÔËÀ©Õ¹ÏÔʾ.md
New file
@@ -0,0 +1,387 @@
# åŽå°ä»»åŠ¡ç®¡ç† - æ€¥æ•‘转运扩展信息显示
## æ¦‚è¿°
在后台管理界面的任务管理功能中,新增对急救转运任务及福祉车任务扩展信息的展示支持,使管理员能够查看完整的任务详情。
## ä¿®æ”¹å†…容
### 1. ä»»åŠ¡è¯¦æƒ…é¡µé¢å¢žå¼º (detail.vue)
**文件**: `ruoyi-ui/src/views/task/general/detail.vue`
#### 1.1 æ·»åŠ æ€¥æ•‘è½¬è¿ä»»åŠ¡æ‰©å±•ä¿¡æ¯å±•ç¤º
在基本信息之后,根据任务类型动态显示扩展信息:
```vue
<!-- æ€¥æ•‘转运任务扩展信息 -->
<el-descriptions v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo"
                 title="急救转运信息" :column="2" border style="margin-top: 20px;">
  <el-descriptions-item label="患者姓名">{{ taskDetail.emergencyInfo.patientName }}</el-descriptions-item>
  <el-descriptions-item label="患者性别">
    <dict-tag :options="dict.type.sys_user_sex" :value="taskDetail.emergencyInfo.patientGender"/>
  </el-descriptions-item>
  <el-descriptions-item label="患者年龄">{{ taskDetail.emergencyInfo.patientAge }}</el-descriptions-item>
  <el-descriptions-item label="联系电话">{{ taskDetail.emergencyInfo.contactPhone }}</el-descriptions-item>
  <el-descriptions-item label="接送医院" :span="2">{{ taskDetail.emergencyInfo.hospitalName }}</el-descriptions-item>
  <el-descriptions-item label="就诊科室" :span="2">
    <dict-tag v-if="taskDetail.emergencyInfo.hospitalDepartment"
              :options="dict.type.hospital_department"
              :value="taskDetail.emergencyInfo.hospitalDepartment"/>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="病情描述" :span="2">
    <span v-if="taskDetail.emergencyInfo.illnessDescription">{{ taskDetail.emergencyInfo.illnessDescription }}</span>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="特殊需求" :span="2">
    <span v-if="taskDetail.emergencyInfo.specialRequirements">{{ taskDetail.emergencyInfo.specialRequirements }}</span>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="是否需要担架">
    <el-tag v-if="taskDetail.emergencyInfo.needsStretcher == 1" type="success" size="small">是</el-tag>
    <el-tag v-else type="info" size="small">否</el-tag>
  </el-descriptions-item>
  <el-descriptions-item label="是否需要轮椅">
    <el-tag v-if="taskDetail.emergencyInfo.needsWheelchair == 1" type="success" size="small">是</el-tag>
    <el-tag v-else type="info" size="small">否</el-tag>
  </el-descriptions-item>
  <el-descriptions-item label="是否需要氧气">
    <el-tag v-if="taskDetail.emergencyInfo.needsOxygen == 1" type="success" size="small">是</el-tag>
    <el-tag v-else type="info" size="small">否</el-tag>
  </el-descriptions-item>
  <el-descriptions-item label="紧急程度">
    <el-tag v-if="taskDetail.emergencyInfo.urgencyLevel === 'HIGH'" type="danger" size="small">紧急</el-tag>
    <el-tag v-else-if="taskDetail.emergencyInfo.urgencyLevel === 'MEDIUM'" type="warning" size="small">一般</el-tag>
    <el-tag v-else-if="taskDetail.emergencyInfo.urgencyLevel === 'LOW'" type="info" size="small">不急</el-tag>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="陪同人数">{{ taskDetail.emergencyInfo.companionCount || 0 }} äºº</el-descriptions-item>
  <el-descriptions-item label="预估费用">{{ taskDetail.emergencyInfo.estimatedCost || '--' }} å…ƒ</el-descriptions-item>
</el-descriptions>
```
#### 1.2 æ·»åŠ ç¦ç¥‰è½¦ä»»åŠ¡æ‰©å±•ä¿¡æ¯å±•ç¤º
```vue
<!-- ç¦ç¥‰è½¦ä»»åŠ¡æ‰©å±•ä¿¡æ¯ -->
<el-descriptions v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo"
                 title="福祉车服务信息" :column="2" border style="margin-top: 20px;">
  <el-descriptions-item label="乘客姓名">{{ taskDetail.welfareInfo.passengerName }}</el-descriptions-item>
  <el-descriptions-item label="乘客性别">
    <dict-tag :options="dict.type.sys_user_sex" :value="taskDetail.welfareInfo.passengerGender"/>
  </el-descriptions-item>
  <el-descriptions-item label="乘客年龄">{{ taskDetail.welfareInfo.passengerAge }}</el-descriptions-item>
  <el-descriptions-item label="联系电话">{{ taskDetail.welfareInfo.contactPhone }}</el-descriptions-item>
  <el-descriptions-item label="服务类型" :span="2">
    <span v-if="taskDetail.welfareInfo.serviceType">{{ taskDetail.welfareInfo.serviceType }}</span>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="特殊需求" :span="2">
    <span v-if="taskDetail.welfareInfo.specialRequirements">{{ taskDetail.welfareInfo.specialRequirements }}</span>
    <span v-else style="color: #C0C4CC;">--</span>
  </el-descriptions-item>
  <el-descriptions-item label="是否需要轮椅">
    <el-tag v-if="taskDetail.welfareInfo.needsWheelchair == 1" type="success" size="small">是</el-tag>
    <el-tag v-else type="info" size="small">否</el-tag>
  </el-descriptions-item>
  <el-descriptions-item label="陪同人数">{{ taskDetail.welfareInfo.companionCount || 0 }} äºº</el-descriptions-item>
  <el-descriptions-item label="预估费用">{{ taskDetail.welfareInfo.estimatedCost || '--' }} å…ƒ</el-descriptions-item>
  <el-descriptions-item label="实际费用">{{ taskDetail.welfareInfo.actualCost || '--' }} å…ƒ</el-descriptions-item>
</el-descriptions>
```
#### 1.3 æ›´æ–°å­—典类型
```javascript
dicts: [
  'sys_task_type',
  'sys_task_status',
  'sys_vehicle_type',
  'sys_task_vehicle_status',
  'sys_user_sex',           // âœ… æ–°å¢žï¼šæ€§åˆ«å­—å…¸
  'hospital_department'     // âœ… æ–°å¢žï¼šåŒ»é™¢ç§‘室字典
]
```
### 2. ä»»åŠ¡åˆ—è¡¨é¡µé¢ä¼˜åŒ– (index.vue)
**文件**: `ruoyi-ui/src/views/task/general/index.vue`
#### 2.1 æ·»åŠ æ€¥æ•‘è½¬è¿ä»»åŠ¡æ ‡è¯†
在任务类型列显示特殊图标标识急救转运任务:
```vue
<el-table-column label="任务类型" align="center" prop="taskType" width="120">
  <template slot-scope="scope">
    <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
    <!-- âœ… æ€¥æ•‘转运任务显示警告图标 -->
    <el-tag v-if="scope.row.taskType === 'EMERGENCY_TRANSFER'" type="danger" size="mini" style="margin-left: 5px;">
      <i class="el-icon-warning"></i>
    </el-tag>
  </template>
</el-table-column>
```
### 3. åŽç«¯æ•°æ®åŠ è½½ï¼ˆå·²å®Œæˆï¼‰
**文件**: `SysTaskServiceImpl.java`
后端的 `getTaskDetail` æ–¹æ³•已正确实现扩展信息加载:
```java
@Override
public SysTask getTaskDetail(Long taskId) {
    SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
    if (task != null) {
        // æŸ¥è¯¢å…³è”车辆
        task.setAssignedVehicles(sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId));
        // æŸ¥è¯¢é™„ä»¶
        task.setAttachments(sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId));
        // æŸ¥è¯¢æ“ä½œæ—¥å¿—
        task.setOperationLogs(sysTaskLogMapper.selectSysTaskLogByTaskId(taskId));
        // âœ… åŠ è½½æ€¥æ•‘è½¬è¿æ‰©å±•ä¿¡æ¯
        if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
            SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
            task.setEmergencyInfo(emergencyInfo);
        }
        // âœ… åŠ è½½ç¦ç¥‰è½¦æ‰©å±•ä¿¡æ¯
        else if ("WELFARE".equals(task.getTaskType())) {
            SysTaskWelfare welfareInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
            task.setWelfareInfo(welfareInfo);
        }
    }
    return task;
}
```
## åŠŸèƒ½å±•ç¤º
### æ€¥æ•‘转运任务详情页面
显示内容包括:
**基本信息**
- ä»»åŠ¡ç¼–å·ã€ç±»åž‹ã€çŠ¶æ€
- åˆ›å»ºäººã€æ‰§è¡Œäººã€éƒ¨é—¨
- å‡ºå‘地址、目的地址
- è®¡åˆ’时间、实际时间
**急救转运信息**(仅 EMERGENCY_TRANSFER ç±»åž‹æ˜¾ç¤ºï¼‰
- æ‚£è€…信息:姓名、性别、年龄、联系电话
- åŒ»ç–—信息:接送医院、就诊科室、病情描述
- ç‰¹æ®Šéœ€æ±‚:担架、轮椅、氧气
- ç´§æ€¥ç¨‹åº¦ï¼šé«˜/中/低
- é™ªåŒäººæ•°ã€é¢„估费用
**福祉车服务信息**(仅 WELFARE ç±»åž‹æ˜¾ç¤ºï¼‰
- ä¹˜å®¢ä¿¡æ¯ï¼šå§“名、性别、年龄、联系电话
- æœåŠ¡ä¿¡æ¯ï¼šæœåŠ¡ç±»åž‹ã€ç‰¹æ®Šéœ€æ±‚
- è¾…助设备:轮椅需求
- è´¹ç”¨ä¿¡æ¯ï¼šé¢„估费用、实际费用、陪同人数
**关联车辆**
- è½¦ç‰Œå·ã€è½¦è¾†ç±»åž‹ã€å“ç‰Œåž‹å·
- åˆ†é…æ—¶é—´ã€åˆ†é…äººã€çŠ¶æ€
**任务附件**
- æ–‡ä»¶åˆ—表及下载
**操作日志**
- æ—¶é—´çº¿å½¢å¼å±•示操作记录
### ä»»åŠ¡åˆ—è¡¨é¡µé¢
- ä»»åŠ¡åˆ—è¡¨å±•ç¤ºåŸºæœ¬ä¿¡æ¯
- æ€¥æ•‘转运任务带有红色警告图标标识
- æ”¯æŒæŒ‰ä»»åŠ¡ç±»åž‹ã€çŠ¶æ€ç­›é€‰
- ç‚¹å‡»ä»»åŠ¡ç¼–å·æŸ¥çœ‹è¯¦æƒ…
## ä½¿ç”¨åœºæ™¯
### åœºæ™¯1:查看急救转运任务详情
```
1. è¿›å…¥åŽå°ç®¡ç† â†’ ä»»åŠ¡ç®¡ç†
2. åœ¨åˆ—表中找到急救转运任务(带红色警告图标)
3. ç‚¹å‡»ä»»åŠ¡ç¼–å·æˆ–"查看"按钮
4. æŸ¥çœ‹å®Œæ•´çš„任务信息,包括:
   - åŸºæœ¬ä»»åŠ¡ä¿¡æ¯
   - æ‚£è€…详细信息
   - åŒ»ç–—相关信息
   - ç‰¹æ®Šéœ€æ±‚配置
   - å…³è”车辆和执行人员
   - æ“ä½œåŽ†å²è®°å½•
```
### åœºæ™¯2:筛选特定类型任务
```
1. åœ¨ä»»åŠ¡ç®¡ç†é¡µé¢
2. ä½¿ç”¨"任务类型"筛选器
3. é€‰æ‹©"急救转运"
4. æŸ¥çœ‹æ‰€æœ‰æ€¥æ•‘转运任务列表
```
### åœºæ™¯3:监控紧急任务
```
1. åœ¨ä»»åŠ¡åˆ—è¡¨ä¸­è¯†åˆ«æ€¥æ•‘è½¬è¿ä»»åŠ¡ï¼ˆçº¢è‰²è­¦å‘Šå›¾æ ‡ï¼‰
2. ç‚¹å‡»æŸ¥çœ‹è¯¦æƒ…
3. æŸ¥çœ‹"紧急程度"字段:
   - çº¢è‰²"紧急"标签 â†’ é«˜ä¼˜å…ˆçº§å¤„理
   - é»„色"一般"标签 â†’ æ­£å¸¸å¤„理
   - ç°è‰²"不急"标签 â†’ å¸¸è§„处理
4. æ ¹æ®ç´§æ€¥ç¨‹åº¦è°ƒåº¦èµ„源
```
## æ˜¾ç¤ºæ•ˆæžœ
### æ€¥æ•‘转运任务标识
- **列表**: ä»»åŠ¡ç±»åž‹æ—è¾¹æ˜¾ç¤º `红色警告图标`
- **详情**: ç‹¬ç«‹çš„"急救转运信息"卡片
### å­—段显示规则
1. **必填字段**: ç›´æŽ¥æ˜¾ç¤ºå€¼
2. **可选字段为空**: æ˜¾ç¤º `--` (灰色)
3. **布尔字段**: ä½¿ç”¨æ ‡ç­¾æ˜¾ç¤º
   - `是` â†’ ç»¿è‰²æ ‡ç­¾
   - `否` â†’ ç°è‰²æ ‡ç­¾
4. **枚举字段**: ä½¿ç”¨å­—典标签
   - æ€§åˆ«: ç”·/女
   - ç§‘室: ä½¿ç”¨åŒ»é™¢ç§‘室字典
   - ç´§æ€¥ç¨‹åº¦:
     - HIGH â†’ çº¢è‰²"紧急"
     - MEDIUM â†’ é»„色"一般"
     - LOW â†’ ç°è‰²"不急"
## æ•°æ®æµç¨‹
```
前端页面加载
    â†“
调用 getTask(taskId) API
    â†“
后端 SysTaskServiceImpl.getTaskDetail()
    â†“
查询基本任务信息 (sys_task)
    â†“
根据 task_type åˆ¤æ–­
    â”œâ”€ EMERGENCY_TRANSFER â†’ æŸ¥è¯¢ sys_task_emergency
    â””─ WELFARE â†’ æŸ¥è¯¢ sys_task_welfare
    â†“
返回完整任务对象
    â†“
前端根据 taskType æ¡ä»¶æ¸²æŸ“扩展信息
```
## æ³¨æ„äº‹é¡¹
### 1. æ•°æ®å®Œæ•´æ€§
确保扩展信息表中的数据与主任务表正确关联:
- `sys_task_emergency.task_id` = `sys_task.task_id`
- `sys_task_welfare.task_id` = `sys_task.task_id`
### 2. å­—典数据配置
需要确保以下字典类型已正确配置:
- `sys_user_sex`: æ€§åˆ«å­—典(男/女)
- `hospital_department`: åŒ»é™¢ç§‘室字典(急诊科、心内科等)
### 3. æƒé™æŽ§åˆ¶
后台管理界面已有权限控制:
```javascript
v-hasPermi="['task:general:query']"  // æŸ¥çœ‹æƒé™
v-hasPermi="['task:general:edit']"   // ç¼–辑权限
v-hasPermi="['task:general:assign']" // åˆ†é…æƒé™
```
### 4. ç©ºå€¼å¤„理
所有可选字段都做了空值判断,避免显示 `undefined` æˆ– `null`:
```vue
<span v-if="taskDetail.emergencyInfo.illnessDescription">
  {{ taskDetail.emergencyInfo.illnessDescription }}
</span>
<span v-else style="color: #C0C4CC;">--</span>
```
## ç›¸å…³æ–‡ä»¶
### å‰ç«¯æ–‡ä»¶
- `/ruoyi-ui/src/views/task/general/index.vue` - ä»»åŠ¡åˆ—è¡¨é¡µé¢
- `/ruoyi-ui/src/views/task/general/detail.vue` - ä»»åŠ¡è¯¦æƒ…é¡µé¢
### åŽç«¯æ–‡ä»¶
- `/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java` - ä»»åŠ¡æŽ§åˆ¶å™¨
- `/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java` - ä»»åŠ¡æœåŠ¡å®žçŽ°
- `/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml` - ä»»åŠ¡Mapper
- `/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml` - æ€¥æ•‘转运Mapper
- `/ruoyi-system/src/main/resources/mapper/system/SysTaskWelfareMapper.xml` - ç¦ç¥‰è½¦Mapper
### å®žä½“ç±»
- `/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java` - ä»»åŠ¡å®žä½“
- `/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java` - æ€¥æ•‘转运扩展实体
- `/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskWelfare.java` - ç¦ç¥‰è½¦æ‰©å±•实体
## æµ‹è¯•建议
### æµ‹è¯•用例1:查看急救转运任务详情
```
前置条件:系统中存在急救转运任务
步骤:
1. ç™»å½•后台管理系统
2. è¿›å…¥ä»»åŠ¡ç®¡ç†é¡µé¢
3. æ‰¾åˆ°ä¸€æ¡æ€¥æ•‘转运任务(有红色警告图标)
4. ç‚¹å‡»ä»»åŠ¡ç¼–å·æŸ¥çœ‹è¯¦æƒ…
验证:
- æ˜¾ç¤ºåŸºæœ¬ä»»åŠ¡ä¿¡æ¯
- æ˜¾ç¤º"急救转运信息"卡片
- æ‰€æœ‰æ‚£è€…信息正确显示
- åŒ»é™¢ã€ç§‘室信息正确显示
- ç‰¹æ®Šéœ€æ±‚标签正确显示
- ç´§æ€¥ç¨‹åº¦æ ‡ç­¾é¢œè‰²æ­£ç¡®
```
### æµ‹è¯•用例2:查看福祉车任务详情
```
前置条件:系统中存在福祉车任务
步骤:
1. è¿›å…¥ä»»åŠ¡ç®¡ç†é¡µé¢
2. æ‰¾åˆ°ä¸€æ¡ç¦ç¥‰è½¦ä»»åŠ¡
3. ç‚¹å‡»æŸ¥çœ‹è¯¦æƒ…
验证:
- æ˜¾ç¤ºåŸºæœ¬ä»»åŠ¡ä¿¡æ¯
- æ˜¾ç¤º"福祉车服务信息"卡片
- ä¹˜å®¢ä¿¡æ¯æ­£ç¡®æ˜¾ç¤º
- æœåŠ¡ç±»åž‹ã€è´¹ç”¨ä¿¡æ¯æ­£ç¡®æ˜¾ç¤º
```
### æµ‹è¯•用例3:空值显示
```
前置条件:创建一条只填必填字段的急救转运任务
步骤:
1. æŸ¥çœ‹ä»»åŠ¡è¯¦æƒ…
验证:
- å¯é€‰å­—段显示 "--"(灰色)
- ä¸å‡ºçް undefined æˆ– null
- é¡µé¢å¸ƒå±€æ­£å¸¸
```
## æ›´æ–°æ—¥å¿—
- **2025-01-25**: åˆå§‹ç‰ˆæœ¬
  - åŽå°ä»»åŠ¡è¯¦æƒ…é¡µé¢æ”¯æŒæ€¥æ•‘è½¬è¿æ‰©å±•ä¿¡æ¯æ˜¾ç¤º
  - åŽå°ä»»åŠ¡è¯¦æƒ…é¡µé¢æ”¯æŒç¦ç¥‰è½¦æ‰©å±•ä¿¡æ¯æ˜¾ç¤º
  - ä»»åŠ¡åˆ—è¡¨é¡µé¢æ·»åŠ æ€¥æ•‘è½¬è¿ä»»åŠ¡å›¾æ ‡æ ‡è¯†
  - æ–°å¢žæ€§åˆ«å’ŒåŒ»é™¢ç§‘室字典支持
prd/Óû§Ð­ÒéÓëÒþ˽Õþ²ßÍêÉÆËµÃ÷.md
New file
@@ -0,0 +1,552 @@
# ç”¨æˆ·åè®®ä¸Žéšç§æ”¿ç­–完善说明
## ä¸€ã€åŠŸèƒ½æ¦‚è¿°
为急救转运调度系统完善了用户协议和隐私政策功能,符合中国法律法规要求(《个人信息保护法》、《网络安全法》、《民法典》等),提升用户体验和法律合规性。
## äºŒã€å®žçް内容
### 2.1 æ–°å¢žé¡µé¢
#### 1. ç”¨æˆ·æœåŠ¡åè®®é¡µé¢
- **文件路径**: `app/pages/mine/user-agreement/index.vue`
- **路由路径**: `/pages/mine/user-agreement/index`
- **页面标题**: ç”¨æˆ·æœåŠ¡åè®®
**协议内容章节**:
1. æ¬¢è¿Žä½¿ç”¨æ€¥æ•‘转运调度系统
2. æœåŠ¡è¯´æ˜Žï¼ˆç³»ç»ŸåŠŸèƒ½ã€æœåŠ¡èŒƒå›´ï¼‰
3. è´¦å·æ³¨å†Œä¸Žä½¿ç”¨ï¼ˆè´¦å·ç®¡ç†ã€ä¿¡æ¯çœŸå®žæ€§ï¼‰
4. ç”¨æˆ·è¡Œä¸ºè§„范(法律合规、禁止行为、职业操作)
5. éšç§ä¿æŠ¤ï¼ˆä¿¡æ¯æ”¶é›†ã€ä½¿ç”¨ã€ä¿æŠ¤ï¼‰
6. çŸ¥è¯†äº§æƒï¼ˆå†…容所有权、使用限制)
7. æœåŠ¡ä¸­æ–­æˆ–ç»ˆæ­¢ï¼ˆä¸­æ–­æƒ…å½¢ã€é€šçŸ¥æœºåˆ¶ã€è´¦å·æ³¨é”€ï¼‰
8. å…è´£å£°æ˜Žï¼ˆè´£ä»»ç•Œå®šã€é£Žé™©æç¤ºï¼‰
9. åè®®å˜æ›´ï¼ˆä¿®æ”¹æœºåˆ¶ã€ç”Ÿæ•ˆæ–¹å¼ï¼‰
10. äº‰è®®è§£å†³ï¼ˆæ³•律适用、管辖法院)
11. å…¶ä»–(完整性、可分割性、解释权)
12. è”系我们(邮箱、电话、工作时间)
**页面特点**:
- ç§»åŠ¨ç«¯ä¼˜åŒ–çš„UI设计
- æ¸…晰的层级结构
- æ˜“读的排版样式
- è¿”回按钮导航
- æ»šåŠ¨æŸ¥çœ‹å®Œæ•´å†…å®¹
#### 2. éšç§æ”¿ç­–页面
- **文件路径**: `app/pages/mine/privacy-policy/index.vue`
- **路由路径**: `/pages/mine/privacy-policy/index`
- **页面标题**: éšç§æ”¿ç­–
**政策内容章节**:
1. å¼•言(法律合规、政策目的)
2. ä¿¡æ¯æ”¶é›†ä¸Žä½¿ç”¨
   - è´¦å·æ³¨å†Œä¸Žç™»å½•(手机号、姓名、部门、职位)
   - ä»»åŠ¡è°ƒåº¦æœåŠ¡ï¼ˆä½ç½®ä¿¡æ¯ã€ä»»åŠ¡ä¿¡æ¯ã€è½¦è¾†ä¿¡æ¯ï¼‰
   - æ¶ˆæ¯æŽ¨é€æœåŠ¡ï¼ˆè®¾å¤‡ä¿¡æ¯ã€æŽ¨é€token)
   - ç³»ç»Ÿå®‰å…¨ä¸Žä¼˜åŒ–(日志、网络、使用情况)
3. Cookie和同类技术(用途、管理方式)
4. ä¿¡æ¯å…±äº«ã€è½¬è®©ã€å…¬å¼€æŠ«éœ²ï¼ˆåŽŸåˆ™ã€ä¾‹å¤–æƒ…å½¢ï¼‰
5. ä¿¡æ¯å®‰å…¨ä¿æŠ¤æŽªæ–½ï¼ˆåŠ å¯†ã€è®¿é—®æŽ§åˆ¶ã€å®¡è®¡ã€åº”æ€¥å“åº”ï¼‰
6. ç”¨æˆ·æƒåˆ©ç®¡ç†ï¼ˆè®¿é—®ã€æ›´æ­£ã€åˆ é™¤ã€æ³¨é”€ã€æ’¤å›žåŒæ„ï¼‰
7. æœªæˆå¹´äººä¿æŠ¤ï¼ˆæœåŠ¡é™åˆ¶ã€ç›‘æŠ¤äººåŒæ„ï¼‰
8. è·¨å¢ƒä¼ è¾“(境内存储)
9. æ”¿ç­–更新(变更通知、生效方式)
10. è”系我们(邮箱、电话、响应时间)
11. å®šä¹‰ï¼ˆä¸ªäººä¿¡æ¯ã€æ•æ„Ÿä¸ªäººä¿¡æ¯ã€åˆ é™¤ï¼‰
**页面特点**:
- ç¬¦åˆã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》要求
- æ•æ„Ÿä¿¡æ¯é«˜äº®æ˜¾ç¤ºï¼ˆé»„色背景 + æ©™è‰²è¾¹æ¡†ï¼‰
- è¯¦ç»†çš„分类说明
- æ˜Žç¡®çš„用户权利
- ä¸“业的法律术语
### 2.2 ä¿®æ”¹é¡µé¢
#### 1. ç™»å½•页面 (`app/pages/login.vue`)
**修改内容**:
- å°†åè®®é“¾æŽ¥ä»Žå¤–部URL改为本地页面
- `handlePrivacy()` æ–¹æ³•:跳转到 `/pages/mine/privacy-policy/index`
- `handleUserAgrement()` æ–¹æ³•:跳转到 `/pages/mine/user-agreement/index`
**修改前**:
```javascript
handlePrivacy() {
  let site = this.globalConfig.appInfo.agreements[0]
  this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
}
```
**修改后**:
```javascript
handlePrivacy() {
  this.$tab.navigateTo('/pages/mine/privacy-policy/index')
}
```
#### 2. æ³¨å†Œé¡µé¢ (`app/pages/register.vue`)
**新增功能**:
1. **协议同意checkbox**
```vue
<view class="agreement-section">
  <checkbox-group @change="handleAgreementChange">
    <label class="agreement-label">
      <checkbox value="agreed" :checked="agreedToTerms" color="#007AFF" />
      <text class="agreement-text">
        æˆ‘已阅读并同意
        <text class="agreement-link" @click.stop="handleUserAgreement">《用户服务协议》</text>
        å’Œ
        <text class="agreement-link" @click.stop="handlePrivacy">《隐私政策》</text>
      </text>
    </label>
  </checkbox-group>
</view>
```
2. **数据字段**
```javascript
data() {
  return {
    agreedToTerms: false,  // æ˜¯å¦åŒæ„åè®®
    // ... å…¶ä»–字段
  }
}
```
3. **验证逻辑**
```javascript
async handleRegister() {
  // ... å…¶ä»–验证
  if (!this.agreedToTerms) {
    this.$modal.msgError("请先阅读并同意用户服务协议和隐私政策")
    return
  }
  // ... æ³¨å†Œé€»è¾‘
}
```
4. **新增方法**
```javascript
// åè®®é€‰æ‹©å˜æ›´
handleAgreementChange(e) {
  this.agreedToTerms = e.detail.value.length > 0
},
// ç”¨æˆ·åè®®
handleUserAgreement() {
  this.$tab.navigateTo('/pages/mine/user-agreement/index')
},
// éšç§æ”¿ç­–
handlePrivacy() {
  this.$tab.navigateTo('/pages/mine/privacy-policy/index')
}
```
5. **样式调整**
```scss
.agreement-section {
  margin: 30rpx 0;
  .agreement-label {
    display: flex;
    align-items: flex-start;
    checkbox {
      margin-right: 15rpx;
      transform: scale(0.9);
    }
    .agreement-text {
      flex: 1;
      font-size: 24rpx;
      color: #666;
      line-height: 1.6;
      text-align: left;
      .agreement-link {
        color: #007AFF;
        text-decoration: underline;
      }
    }
  }
}
```
#### 3. "我的"页面 (`app/pages/mine/index.vue`)
**新增菜单项**:
在"编辑资料"和"常见问题"之间插入两个菜单项:
```vue
<view class="list-cell list-cell-arrow" @click="handleUserAgreement">
  <view class="menu-item-box">
    <view class="iconfont icon-text menu-icon"></view>
    <view>用户服务协议</view>
  </view>
</view>
<view class="list-cell list-cell-arrow" @click="handlePrivacyPolicy">
  <view class="menu-item-box">
    <view class="iconfont icon-safe menu-icon"></view>
    <view>隐私政策</view>
  </view>
</view>
```
**新增方法**:
```javascript
handleUserAgreement() {
  this.$tab.navigateTo('/pages/mine/user-agreement/index')
},
handlePrivacyPolicy() {
  this.$tab.navigateTo('/pages/mine/privacy-policy/index')
}
```
### 2.3 è·¯ç”±é…ç½®
在 `app/pages.json` ä¸­å·²æ·»åŠ è·¯ç”±é…ç½®ï¼š
```json
{
  "path": "pages/mine/user-agreement/index",
  "style": {
    "navigationBarTitleText": "用户服务协议"
  }
},
{
  "path": "pages/mine/privacy-policy/index",
  "style": {
    "navigationBarTitleText": "隐私政策"
  }
}
```
## ä¸‰ã€æ³•律合规要点
### 3.1 ç¬¦åˆçš„æ³•律法规
1. **《中华人民共和国个人信息保护法》**
   - æ˜Žç¡®å‘ŠçŸ¥æ”¶é›†çš„个人信息类型
   - è¯´æ˜Žä¸ªäººä¿¡æ¯çš„使用目的
   - æ ‡æ³¨æ•æ„Ÿä¸ªäººä¿¡æ¯ï¼ˆä½ç½®ä¿¡æ¯ï¼‰
   - æ˜Žç¡®ç”¨æˆ·çš„各项权利
2. **《中华人民共和国网络安全法》**
   - ä¿¡æ¯å®‰å…¨ä¿æŠ¤æŽªæ–½
   - æ•°æ®å­˜å‚¨åœ¨å¢ƒå†…
   - å®‰å…¨äº‹ä»¶åº”急响应
3. **《中华人民共和国民法典》**
   - åˆåŒæ¡æ¬¾è§„范
   - äº‰è®®è§£å†³æœºåˆ¶
   - ç”¨æˆ·æƒç›Šä¿æŠ¤
### 3.2 å…³é”®åˆè§„内容
#### ä¿¡æ¯æ”¶é›†å‘ŠçŸ¥
- âœ… æ˜Žç¡®åˆ—出收集的信息类型
- âœ… è¯´æ˜Žæ¯ç§ä¿¡æ¯çš„用途
- âœ… æ ‡æ³¨æ•æ„Ÿä¿¡æ¯ï¼ˆä½ç½®ã€åŒ»ç–—健康)
- âœ… æä¾›æ‹’绝授权的影响说明
#### ç”¨æˆ·æƒåˆ©
- âœ… è®¿é—®å’Œæ›´æ­£ä¸ªäººä¿¡æ¯çš„æƒåˆ©
- âœ… åˆ é™¤ä¸ªäººä¿¡æ¯çš„æƒåˆ©
- âœ… æ³¨é”€è´¦å·çš„æƒåˆ©
- âœ… æ’¤å›žåŒæ„çš„æƒåˆ©
#### ä¿¡æ¯å®‰å…¨
- âœ… æ•°æ®åŠ å¯†ä¼ è¾“å’Œå­˜å‚¨
- âœ… è®¿é—®æŽ§åˆ¶å’Œæƒé™ç®¡ç†
- âœ… å®‰å…¨å®¡è®¡æœºåˆ¶
- âœ… å®‰å…¨äº‹ä»¶åº”急响应
#### ç”¨æˆ·åŒæ„
- âœ… æ³¨å†Œæ—¶å¿…须勾选同意协议
- âœ… åè®®å¯éšæ—¶æŸ¥çœ‹
- âœ… åè®®å˜æ›´æ—¶é€šçŸ¥ç”¨æˆ·
## å››ã€ä½¿ç”¨æ–¹å¼
### 4.1 ç”¨æˆ·è®¿é—®è·¯å¾„
1. **登录页面**
   - ç‚¹å‡»"《用户协议》"或"《隐私协议》"链接
   - ç›´æŽ¥è·³è½¬åˆ°å¯¹åº”页面
2. **注册页面**
   - å¿…须勾选协议同意checkbox才能注册
   - ç‚¹å‡»åè®®é“¾æŽ¥å¯æŸ¥çœ‹è¯¦ç»†å†…容
   - ä½¿ç”¨ `@click.stop` é˜²æ­¢äº‹ä»¶å†’泡
3. **"我的"页面**
   - é€šè¿‡èœå•项"用户服务协议"访问
   - é€šè¿‡èœå•项"隐私政策"访问
### 4.2 å¼€å‘集成
如需在其他页面引用协议,使用以下代码:
```javascript
// è·³è½¬åˆ°ç”¨æˆ·åè®®
this.$tab.navigateTo('/pages/mine/user-agreement/index')
// è·³è½¬åˆ°éšç§æ”¿ç­–
this.$tab.navigateTo('/pages/mine/privacy-policy/index')
```
## äº”、定制化建议
### 5.1 å¿…须修改的内容
在实际部署前,请务必修改以下内容:
1. **联系方式**(两个文件都需要修改)
   ```vue
   <!-- ç”¨æˆ·æœåŠ¡åè®® -->
   <text class="section-text">
     ç”µå­é‚®ç®±ï¼šsupport@example.com  <!-- æ”¹ä¸ºå®žé™…邮箱 -->
   </text>
   <text class="section-text">
     å®¢æœç”µè¯ï¼š400-XXX-XXXX  <!-- æ”¹ä¸ºå®žé™…电话 -->
   </text>
   <!-- éšç§æ”¿ç­– -->
   <text class="section-text">
     ç”µå­é‚®ç®±ï¼šprivacy@example.com  <!-- æ”¹ä¸ºå®žé™…邮箱 -->
   </text>
   <text class="section-text">
     å®¢æœç”µè¯ï¼š400-XXX-XXXX  <!-- æ”¹ä¸ºå®žé™…电话 -->
   </text>
   ```
2. **更新日期和生效日期**
   ```vue
   <view class="update-time">更新日期:2025å¹´1月25日</view>  <!-- æ”¹ä¸ºå®žé™…日期 -->
   <view class="effect-time">生效日期:2025å¹´1月25日</view>  <!-- æ”¹ä¸ºå®žé™…日期 -->
   ```
3. **运营主体信息**
   - å¦‚果有正式的公司名称,请在协议中添加
   - å¦‚果有营业执照信息,建议在"关于我们"中补充
### 5.2 å¯é€‰ä¼˜åŒ–内容
1. **添加版本号管理**
   - åœ¨åè®®é¡¶éƒ¨æ˜¾ç¤ºç‰ˆæœ¬å·ï¼ˆå¦‚ v1.0)
   - è®°å½•历史版本变更
2. **添加下载功能**
   - å…è®¸ç”¨æˆ·ä¸‹è½½PDF版本的协议
   - æ–¹ä¾¿ç”¨æˆ·ä¿å­˜å’ŒæŸ¥é˜…
3. **添加搜索功能**
   - å¯¹äºŽå†…容较长的协议,提供关键词搜索
   - å¿«é€Ÿå®šä½åˆ°ç›¸å…³ç« èŠ‚
4. **国际化支持**
   - å¦‚需支持多语言,可添加语言切换功能
   - å‡†å¤‡è‹±æ–‡ç‰ˆæœ¬çš„协议
### 5.3 æ³•律审核建议
**重要提示**: è™½ç„¶æˆ‘们的协议内容已尽可能符合法律要求,但仍建议:
1. **专业审核**
   - è¯·è´µå…¬å¸çš„æ³•律顾问审核协议内容
   - æ ¹æ®å®žé™…业务情况调整条款
2. **行业特殊要求**
   - åŒ»ç–—急救行业可能有特殊的法律要求
   - è¯·å’¨è¯¢åŒ»ç–—法律专家
3. **定期更新**
   - éšç€æ³•律法规的变化,定期更新协议内容
   - ç‰¹åˆ«å…³æ³¨ã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》的实施细则
## å…­ã€æŠ€æœ¯å®žçŽ°ç»†èŠ‚
### 6.1 é¡µé¢ç»“æž„
```
协议页面
├── Header(顶部导航栏)
│   â”œâ”€â”€ è¿”回按钮
│   â””── é¡µé¢æ ‡é¢˜
└── Content(内容区域)
    â”œâ”€â”€ ScrollView(可滚动容器)
    â””── åè®®å†…容
        â”œâ”€â”€ æ›´æ–°æ—¥æœŸ
        â”œâ”€â”€ ç”Ÿæ•ˆæ—¥æœŸ
        â”œâ”€â”€ ç« èЂ内容
        â”‚   â”œâ”€â”€ ç« èŠ‚æ ‡é¢˜
        â”‚   â”œâ”€â”€ å°èŠ‚æ ‡é¢˜
        â”‚   â”œâ”€â”€ æ­£æ–‡
        â”‚   â””── åˆ—表项
        â””── é¡µè„š
```
### 6.2 æ ·å¼ç³»ç»Ÿ
**响应式设计**:
- ä½¿ç”¨ `rpx` å•位,自动适配不同屏幕尺寸
- æœ€å°å­—体 `24rpx`,正文字体 `28rpx`,标题字体 `32rpx`
**颜色方案**:
- ä¸»è‰²è°ƒï¼š`#333`(深灰)
- æ¬¡è¦æ–‡å­—:`#666`(中灰)
- æç¤ºæ–‡å­—:`#999`(浅灰)
- é«˜äº®è‰²ï¼š`#007AFF`(蓝色)
- æ•æ„Ÿä¿¡æ¯èƒŒæ™¯ï¼š`#fff8e6`(淡黄)
- æ•æ„Ÿä¿¡æ¯è¾¹æ¡†ï¼š`#ff9500`(橙色)
**布局特点**:
- å†…容区域:白色背景,圆角卡片
- è¡Œé«˜ï¼š`1.8`,增强可读性
- æ®µè½é—´è·ï¼š`15rpx`,清晰分隔
- åˆ—表缩进:`40rpx`,层级明显
### 6.3 äº¤äº’设计
1. **返回导航**
   ```javascript
   goBack() {
     uni.navigateBack()
   }
   ```
2. **滚动查看**
   - ä½¿ç”¨ `scroll-view` ç»„ä»¶
   - æ”¯æŒåž‚直滚动
   - è‡ªåŠ¨éšè—æ»šåŠ¨æ¡ï¼ˆä¿æŒç¾Žè§‚ï¼‰
3. **链接点击**
   - åè®®ä¸­çš„链接使用蓝色标识
   - ç‚¹å‡»å¯è·³è½¬åˆ°å¯¹åº”页面
   - ä½¿ç”¨ `@click.stop` é˜²æ­¢äº‹ä»¶å†’泡
## ä¸ƒã€ç»´æŠ¤å’Œæ›´æ–°
### 7.1 åè®®æ›´æ–°æµç¨‹
当需要更新协议内容时:
1. **修改内容**
   - åœ¨å¯¹åº”çš„ `.vue` æ–‡ä»¶ä¸­ä¿®æ”¹åè®®æ–‡æœ¬
   - æ›´æ–°"更新日期"和"生效日期"
2. **通知用户**(建议实现)
   - åœ¨ç”¨æˆ·ä¸‹æ¬¡ç™»å½•时显示协议更新提示
   - è¦æ±‚用户重新同意协议
   - è®°å½•用户同意的协议版本号
3. **保存历史版本**(建议实现)
   - åœ¨æ•°æ®åº“中保存协议的历史版本
   - è®°å½•用户同意的是哪个版本
   - æ–¹ä¾¿è¿½æº¯å’Œå®¡è®¡
### 7.2 ç›‘控和反馈
**用户反馈收集**:
- åœ¨åè®®é¡µé¢æ·»åŠ "意见反馈"入口
- æ”¶é›†ç”¨æˆ·å¯¹åè®®å†…容的疑问
- åŠæ—¶å“åº”用户的咨询
**数据统计**:
- ç»Ÿè®¡åè®®çš„æŸ¥çœ‹æ¬¡æ•°
- åˆ†æžç”¨æˆ·çš„停留时间
- è¯†åˆ«ç”¨æˆ·å…³æ³¨çš„章节
## å…«ã€æ³¨æ„äº‹é¡¹
### 8.1 å¼€å‘注意事项
1. **字符编码**
   - ç¡®ä¿æ–‡ä»¶ä½¿ç”¨ UTF-8 ç¼–码
   - é¿å…ä¸­æ–‡ä¹±ç é—®é¢˜
2. **跨平台兼容**
   - åœ¨å¾®ä¿¡å°ç¨‹åºã€H5、App中测试
   - ç¡®ä¿æ»šåŠ¨å’Œå¯¼èˆªåŠŸèƒ½æ­£å¸¸
3. **性能优化**
   - åè®®å†…容较长,注意页面加载性能
   - å¯ä»¥è€ƒè™‘懒加载或分页显示
### 8.2 åˆè§„注意事项
1. **必须同意**
   - æ³¨å†Œæ—¶å¿…须勾选同意协议
   - ä¸èƒ½é»˜è®¤å‹¾é€‰ï¼Œå¿…须用户主动操作
2. **易于访问**
   - åè®®é“¾æŽ¥å¿…须清晰可见
   - éšæ—¶å¯ä»¥æŸ¥çœ‹å®Œæ•´åè®®
3. **明确告知**
   - æ”¶é›†æ•æ„Ÿä¿¡æ¯æ—¶å¿…须明确告知
   - è¯´æ˜Žæ‹’绝授权的影响
4. **获取同意**
   - é‡è¦æƒé™ï¼ˆå¦‚定位)需单独授权
   - ä¸èƒ½ä¸€æ¬¡æ€§æŽˆæƒæ‰€æœ‰æƒé™
## ä¹ã€åŽç»­ä¼˜åŒ–建议
1. **添加协议版本管理系统**
   - åœ¨åŽå°ç®¡ç†ç³»ç»Ÿä¸­æ·»åŠ åè®®ç‰ˆæœ¬ç®¡ç†
   - æ”¯æŒåœ¨çº¿ç¼–辑和预览
   - è‡ªåŠ¨è®°å½•æ›´æ–°åŽ†å²
2. **实现协议同意记录**
   - åœ¨æ•°æ®åº“中记录用户同意协议的时间和版本
   - å½“协议更新时,提示用户重新同意
   - ç¬¦åˆã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》的要求
3. **添加协议导出功能**
   - å…è®¸ç”¨æˆ·å¯¼å‡ºPDF版本
   - æ–¹ä¾¿ç”¨æˆ·ä¿å­˜å’Œæ‰“印
4. **优化移动端体验**
   - æ·»åŠ ç›®å½•å¯¼èˆªï¼Œå¿«é€Ÿè·³è½¬åˆ°æŒ‡å®šç« èŠ‚
   - ä¼˜åŒ–长文本的阅读体验
   - æ·»åŠ å¤œé—´æ¨¡å¼
## åã€æ–‡ä»¶æ¸…单
### æ–°å¢žæ–‡ä»¶
- `app/pages/mine/user-agreement/index.vue` - ç”¨æˆ·æœåŠ¡åè®®é¡µé¢
- `app/pages/mine/privacy-policy/index.vue` - éšç§æ”¿ç­–页面
- `prd/用户协议与隐私政策完善说明.md` - æœ¬è¯´æ˜Žæ–‡æ¡£
### ä¿®æ”¹æ–‡ä»¶
- `app/pages/login.vue` - ä¿®æ”¹åè®®é“¾æŽ¥æŒ‡å‘
- `app/pages/register.vue` - æ·»åŠ åè®®åŒæ„checkbox
- `app/pages/mine/index.vue` - æ·»åŠ åè®®èœå•å…¥å£
- `app/pages.json` - æ·»åŠ è·¯ç”±é…ç½®ï¼ˆä¹‹å‰å·²æ·»åŠ ï¼‰
## åä¸€ã€æ€»ç»“
本次完善工作实现了:
✅ **完整的用户协议和隐私政策页面**
✅ **符合中国法律法规要求**
✅ **注册时强制同意协议**
✅ **多处便捷访问入口**
✅ **移动端优化的UI设计**
✅ **敏感信息高亮提示**
✅ **清晰的内容结构**
✅ **专业的法律术语**
请在实际部署前,务必:
1. ä¿®æ”¹è”系方式为实际信息
2. æ›´æ–°æ—¥æœŸä¸ºå®žé™…日期
3. è¯·æ³•律顾问审核协议内容
4. æ ¹æ®å®žé™…业务调整条款
如有任何问题或需要进一步调整,请随时联系开发团队!
prd/Óû§Ð­ÒéÓëÒþ˽Õþ²ß˵Ã÷.md
New file
@@ -0,0 +1,332 @@
# ç”¨æˆ·åè®®ä¸Žéšç§æ”¿ç­–完善说明
## æ¦‚è¿°
为急救转运调度系统添加了完整的用户服务协议和隐私政策,确保符合中国法律法规要求,保护用户权益和个人信息安全。
## æ–°å¢žæ–‡ä»¶
### 1. ç”¨æˆ·æœåŠ¡åè®®é¡µé¢
**文件路径**: `app/pages/mine/user-agreement/index.vue`
**主要内容**:
- **服务说明**: ç³»ç»ŸåŠŸèƒ½ã€æœåŠ¡èŒƒå›´ã€åŠŸèƒ½è°ƒæ•´è¯´æ˜Ž
- **账号注册与使用**: è´¦å·ç®¡ç†è§„范、信息真实性要求
- **用户行为规范**: åˆæ³•使用要求、禁止行为列表、职业操作规范
- **隐私保护**: ä¿¡æ¯æ”¶é›†è¯´æ˜Žã€éšç§æ”¿ç­–引用
- **知识产权**: ç³»ç»Ÿå†…容归属、使用限制
- **服务中断或终止**: ä¸­æ–­æƒ…形、通知机制、账号注销
- **免责声明**: è´£ä»»èŒƒå›´ã€å‚考性说明
- **协议变更**: ä¿®æ”¹æœºåˆ¶ã€ç”¨æˆ·é€‰æ‹©æƒ
- **争议解决**: é€‚用法律、解决途径
- **联系方式**: å®¢æœé‚®ç®±ã€ç”µè¯ã€å·¥ä½œæ—¶é—´
**特色功能**:
- ðŸ“± ç§»åŠ¨ç«¯ä¼˜åŒ–å¸ƒå±€
- ðŸ“– æ¸…晰的章节结构
- ðŸŽ¨ å‹å¥½çš„视觉设计
- âœ… é‡ç‚¹å†…容突出显示
- ðŸ”™ è¿”回按钮支持
### 2. éšç§æ”¿ç­–页面
**文件路径**: `app/pages/mine/privacy-policy/index.vue`
**主要内容**:
- **引言**: éšç§ä¿æŠ¤æ‰¿è¯ºã€æ”¿ç­–适用范围
- **信息收集与使用**:
  - è´¦å·æ³¨å†Œä¿¡æ¯ï¼ˆæ‰‹æœºå·ã€å§“名、部门、职位)
  - ä»»åŠ¡è°ƒåº¦ä¿¡æ¯ï¼ˆä½ç½®ã€æ‚£è€…ä¿¡æ¯ã€è½¦è¾†ä¿¡æ¯ï¼‰
  - æ¶ˆæ¯æŽ¨é€ä¿¡æ¯ï¼ˆè®¾å¤‡ä¿¡æ¯ã€æŽ¨é€token)
  - ç³»ç»Ÿä¼˜åŒ–信息(日志、网络、使用情况)
- **Cookie和同类技术**: ä½¿ç”¨ç›®çš„、管理方式
- **信息共享、转让、公开披露**: å…±äº«æƒ…形、转让限制、披露条件
- **信息安全保护**:
  - æ•°æ®åŠ å¯†ï¼ˆSSL/TLS、敏感数据加密)
  - è®¿é—®æŽ§åˆ¶ï¼ˆæƒé™ç®¡ç†ã€å®¡æ‰¹æœºåˆ¶ï¼‰
  - å®‰å…¨å®¡è®¡ï¼ˆå®šæœŸè¯„估)
  - äººå‘˜ç®¡ç†ï¼ˆèº«ä»½è®¤è¯ï¼‰
  - åº”急响应(事件预案)
- **用户权利**:
  - è®¿é—®å’Œæ›´æ­£ä¿¡æ¯
  - åˆ é™¤ä¸ªäººä¿¡æ¯
  - æ³¨é”€è´¦å·
  - æ’¤å›žåŒæ„
- **未成年人保护**: é¢å‘对象说明、特殊保护措施
- **跨境传输**: æ•°æ®å­˜å‚¨ä½ç½®è¯´æ˜Ž
- **政策更新**: ä¿®è®¢é€šçŸ¥æœºåˆ¶
- **联系方式**: éšç§é—®é¢˜è”系渠道
- **术语定义**: ä¸ªäººä¿¡æ¯ã€æ•æ„Ÿä¿¡æ¯ç­‰å®šä¹‰
**特色功能**:
- ðŸ”’ æ•æ„Ÿä¿¡æ¯é«˜äº®æ˜¾ç¤º
- ðŸ“‹ è¯¦ç»†çš„信息类型说明
- ðŸ›¡ï¸ å®‰å…¨ä¿æŠ¤æŽªæ–½è¯¦è§£
- âš¡ ç”¨æˆ·æƒåˆ©æ˜Žç¡®åˆ—举
- ðŸ“ž å¤šç§è”系方式
## è·¯ç”±é…ç½®
已在 `app/pages.json` ä¸­æ·»åŠ è·¯ç”±é…ç½®ï¼š
```json
{
  "path": "pages/mine/user-agreement/index",
  "style": {
    "navigationBarTitleText": "用户服务协议"
  }
},
{
  "path": "pages/mine/privacy-policy/index",
  "style": {
    "navigationBarTitleText": "隐私政策"
  }
}
```
## ä½¿ç”¨æ–¹å¼
### ä»Ž"我的"页面跳转
```vue
<template>
  <view class="setting-item" @click="viewUserAgreement">
    <text>用户服务协议</text>
    <uni-icons type="arrowright" size="16"></uni-icons>
  </view>
  <view class="setting-item" @click="viewPrivacyPolicy">
    <text>隐私政策</text>
    <uni-icons type="arrowright" size="16"></uni-icons>
  </view>
</template>
<script>
export default {
  methods: {
    viewUserAgreement() {
      uni.navigateTo({
        url: '/pages/mine/user-agreement/index'
      })
    },
    viewPrivacyPolicy() {
      uni.navigateTo({
        url: '/pages/mine/privacy-policy/index'
      })
    }
  }
}
</script>
```
### åœ¨æ³¨å†Œé¡µé¢å¼•用
```vue
<template>
  <view class="agreement-tips">
    <checkbox-group @change="agreeChange">
      <label>
        <checkbox value="agree" :checked="agreedToTerms" />
        <text>我已阅读并同意</text>
        <text class="link" @click.stop="viewUserAgreement">《用户服务协议》</text>
        <text>和</text>
        <text class="link" @click.stop="viewPrivacyPolicy">《隐私政策》</text>
      </label>
    </checkbox-group>
  </view>
</template>
<script>
export default {
  data() {
    return {
      agreedToTerms: false
    }
  },
  methods: {
    agreeChange(e) {
      this.agreedToTerms = e.detail.value.includes('agree')
    },
    viewUserAgreement() {
      uni.navigateTo({
        url: '/pages/mine/user-agreement/index'
      })
    },
    viewPrivacyPolicy() {
      uni.navigateTo({
        url: '/pages/mine/privacy-policy/index'
      })
    }
  }
}
</script>
```
## æ³•律合规要点
### 1. ç¬¦åˆã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》要求
✅ **明确告知**: æ¸…楚说明收集哪些个人信息
✅ **用途说明**: è¯¦ç»†è¯´æ˜Žæ¯ç±»ä¿¡æ¯çš„使用目的
✅ **敏感信息标注**: å¯¹ä½ç½®ä¿¡æ¯ç­‰æ•æ„Ÿæ•°æ®ç‰¹åˆ«æ ‡æ³¨
✅ **用户权利**: æ˜Žç¡®ç”¨æˆ·è®¿é—®ã€æ›´æ­£ã€åˆ é™¤ç­‰æƒåˆ©
✅ **安全保护**: è¯´æ˜Žé‡‡å–的安全保护措施
### 2. ç¬¦åˆã€Šç½‘络安全法》要求
✅ **数据安全**: è¯´æ˜Žæ•°æ®åŠ å¯†ã€è®¿é—®æŽ§åˆ¶ç­‰æŽªæ–½
✅ **事件应急**: æ˜Žç¡®å®‰å…¨äº‹ä»¶çš„处理和通知机制
✅ **数据存储**: è¯´æ˜Žæ•°æ®å­˜å‚¨åœ¨å¢ƒå†…
### 3. ç¬¦åˆã€Šæ°‘法典》要求
✅ **隐私权保护**: å°Šé‡ç”¨æˆ·éšç§æƒ
✅ **个人信息保护**: åˆæ³•、正当、必要原则
✅ **未成年人保护**: ç‰¹åˆ«ä¿æŠ¤æŽªæ–½
## å®šåˆ¶åŒ–建议
### æ ¹æ®å®žé™…情况修改以下内容:
1. **联系方式**
   - ç”µå­é‚®ç®±ï¼šå°† `support@example.com` æ”¹ä¸ºå®žé™…邮箱
   - å®¢æœç”µè¯ï¼šå°† `400-XXX-XXXX` æ”¹ä¸ºå®žé™…电话
   - éšç§é‚®ç®±ï¼šå°† `privacy@example.com` æ”¹ä¸ºå®žé™…邮箱
2. **公司信息**
   - æ ¹æ®å®žé™…运营主体完善公司名称
   - æ·»åŠ å…¬å¸æ³¨å†Œåœ°å€
   - æ·»åŠ ç»Ÿä¸€ç¤¾ä¼šä¿¡ç”¨ä»£ç 
3. **数据处理**
   - æ ¹æ®å®žé™…业务调整收集的信息类型
   - è¡¥å……第三方服务商信息(如地图服务)
   - å®Œå–„数据保存期限说明
4. **特定场景**
   - æ ¹æ®å®žé™…业务补充特殊场景的隐私处理
   - æ·»åŠ å…·ä½“çš„åŒ»ç–—æ•°æ®å¤„ç†è¯´æ˜Ž
   - å®Œå–„患者信息保护细则
## æ ·å¼ç‰¹ç‚¹
### é€šç”¨æ ·å¼
- **响应式布局**: é€‚配不同屏幕尺寸
- **清晰层级**: æ ‡é¢˜ã€å°æ ‡é¢˜ã€æ­£æ–‡å±‚次分明
- **易读性**: åˆé€‚的字号、行高、间距
- **视觉引导**: ä½¿ç”¨å›¾æ ‡ã€é¢œè‰²å¼ºè°ƒé‡ç‚¹
### éšç§æ”¿ç­–特殊样式
```scss
.highlight {
  background-color: #fff8e6;  // æ·¡é»„色背景
  padding: 20rpx;
  border-left: 4rpx solid #ff9500;  // æ©™è‰²å·¦è¾¹æ¡†
  border-radius: 8rpx;
  font-weight: bold;
  color: #333;
}
```
用于突出显示敏感信息、重要提示等内容。
### åˆ—表样式
```scss
.indent {
  padding-left: 40rpx;
  position: relative;
  &::before {
    content: '';
    position: absolute;
    left: 20rpx;
    top: 18rpx;
    width: 8rpx;
    height: 8rpx;
    background-color: #666;
    border-radius: 50%;
  }
}
```
用于显示项目列表,使用圆点标记。
## ç»´æŠ¤å»ºè®®
### å®šæœŸæ›´æ–°
1. **法律法规变更时**: åŠæ—¶æ›´æ–°ç›¸å…³æ¡æ¬¾
2. **功能变更时**: æ›´æ–°åŠŸèƒ½è¯´æ˜Žå’Œä¿¡æ¯æ”¶é›†è¯´æ˜Ž
3. **安全措施升级时**: æ›´æ–°å®‰å…¨ä¿æŠ¤è¯´æ˜Ž
4. **至少每年一次**: å®¡æŸ¥å’Œæ›´æ–°æ•´ä½“内容
### ç‰ˆæœ¬ç®¡ç†
建议在文件顶部添加版本记录:
```vue
<view class="version-info">
  <text>版本:v1.0</text>
  <text>更新日期:2025å¹´1月25日</text>
  <text>生效日期:2025å¹´1月25日</text>
</view>
```
### å˜æ›´é€šçŸ¥
当协议或政策有重大变更时,应:
1. åœ¨ç³»ç»Ÿä¸­å¼¹çª—通知用户
2. è¦æ±‚用户重新同意
3. ä¿ç•™å˜æ›´è®°å½•
## æ³¨æ„äº‹é¡¹
### 1. æ³•律审核
⚠️ **重要**: å»ºè®®åœ¨æ­£å¼ä½¿ç”¨å‰ï¼Œè¯·ä¸“业律师审核协议和政策内容,确保完全符合:
- ã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》
- ã€Šç½‘络安全法》
- ã€Šæ°‘法典》
- ã€Šæ•°æ®å®‰å…¨æ³•》
- ç›¸å…³è¡Œä¸šè§„范(医疗行业)
### 2. åŒ»ç–—数据特殊性
由于涉及医疗急救业务,可能需要补充:
- æ‚£è€…医疗数据的特殊保护措施
- åŒ»ç–—信息脱敏处理
- åŒ»ç–—数据访问权限管理
- ç¬¦åˆåŒ»ç–—行业数据安全规范
### 3. æ•æ„Ÿæƒé™è¯´æ˜Ž
对于位置信息等敏感权限,需要:
- åœ¨é¦–次使用时弹窗说明
- æä¾›æ‹’绝选项
- è¯´æ˜Žæ‹’绝后的影响
- å…è®¸éšæ—¶æ’¤å›žæŽˆæƒ
### 4. æœªæˆå¹´äººä¿æŠ¤
如果系统可能被未成年人使用,需要:
- æ·»åŠ å¹´é¾„éªŒè¯æœºåˆ¶
- è¦æ±‚监护人同意
- ç‰¹æ®Šçš„隐私保护措施
## ç›¸å…³æ–‡ä»¶
- `/app/pages/mine/user-agreement/index.vue` - ç”¨æˆ·æœåŠ¡åè®®é¡µé¢
- `/app/pages/mine/privacy-policy/index.vue` - éšç§æ”¿ç­–页面
- `/app/pages.json` - è·¯ç”±é…ç½®æ–‡ä»¶
## æ›´æ–°æ—¥å¿—
- **2025-01-25**: åˆå§‹ç‰ˆæœ¬
  - åˆ›å»ºç”¨æˆ·æœåŠ¡åè®®é¡µé¢
  - åˆ›å»ºéšç§æ”¿ç­–页面
  - æ·»åŠ è·¯ç”±é…ç½®
  - å®Œå–„法律合规内容
prd/µÇ¼ע²áЭÒéÁ´½ÓÓÅ»¯ËµÃ÷.md
New file
@@ -0,0 +1,407 @@
# ç™»å½•注册协议链接优化说明
## é—®é¢˜æè¿°
用户反馈登录界面的隐私协议和用户协议链接:
1. ä½ç½®å¤ªé ä¸Šï¼Œå®¹æ˜“被其他元素遮挡
2. ç‚¹å‡»åŒºåŸŸå¤ªå°ï¼Œä¸å®¹æ˜“点击
3. ç‚¹å‡»å¯èƒ½æ— å“åº”
## ä¼˜åŒ–方案
### ä¸€ã€ç™»å½•页面 (`app/pages/login.vue`)
#### 1.1 æ¨¡æ¿ä¼˜åŒ–
**修改前**:
```vue
<view class="xieyi text-center">
  <text class="text-grey1">登录即代表同意</text>
  <text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
  <text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
</view>
```
**修改后**:
```vue
<view class="xieyi text-center">
  <text class="text-grey1">登录即代表同意</text>
  <text @click.stop="handleUserAgrement" class="text-blue agreement-link">《用户协议》</text>
  <text class="text-grey1">和</text>
  <text @click.stop="handlePrivacy" class="text-blue agreement-link">《隐私协议》</text>
</view>
```
**优化点**:
- âœ… æ·»åŠ  `@click.stop` é˜»æ­¢äº‹ä»¶å†’泡
- âœ… æ·»åŠ  `agreement-link` ç±»åï¼Œå¢žåŠ ç‚¹å‡»åŒºåŸŸ
- âœ… åœ¨ä¸¤ä¸ªåè®®ä¹‹é—´æ·»åŠ "和"字,更符合语义
#### 1.2 æ ·å¼ä¼˜åŒ–
**修改前**:
```scss
.reg, .xieyi {
  margin: 20rpx 0;
  .text-grey1 {
    color: #888;
  }
  .text-blue {
    margin: 0 10rpx;
    color: #007AFF;
  }
}
```
**修改后**:
```scss
.reg {
  margin: 20rpx 0;
  .text-grey1 {
    color: #888;
  }
  .text-blue {
    margin: 0 10rpx;
    color: #007AFF;
  }
}
.xieyi {
  margin: 50rpx 0 30rpx 0;  // å‘下移动,增加上边距
  padding: 20rpx 0;          // å¢žåŠ å†…è¾¹è·
  line-height: 2;            // å¢žåŠ è¡Œé«˜
  .text-grey1 {
    color: #888;
    font-size: 24rpx;
  }
  .agreement-link {
    color: #007AFF;
    font-size: 24rpx;
    padding: 10rpx 8rpx;     // å¢žåŠ ç‚¹å‡»åŒºåŸŸ
    margin: 0 5rpx;
    display: inline-block;
    position: relative;
    z-index: 10;             // ç¡®ä¿åœ¨æœ€ä¸Šå±‚
  }
}
```
**优化点**:
- âœ… **向下移动**: `margin-top: 50rpx`(原来20rpx)
- âœ… **增加点击区域**: `padding: 10rpx 8rpx`
- âœ… **提高层级**: `z-index: 10`
- âœ… **增加行高**: `line-height: 2`,防止文字拥挤
- âœ… **分离样式**: å°† `.reg` å’Œ `.xieyi` åˆ†å¼€ï¼Œç‹¬ç«‹æŽ§åˆ¶
### äºŒã€æ³¨å†Œé¡µé¢ (`app/pages/register.vue`)
#### 2.1 æ¨¡æ¿ï¼ˆå·²æ­£ç¡®ï¼‰
```vue
<view class="agreement-section">
  <checkbox-group @change="handleAgreementChange">
    <label class="agreement-label">
      <checkbox value="agreed" :checked="agreedToTerms" color="#007AFF" />
      <text class="agreement-text">
        æˆ‘已阅读并同意
        <text class="agreement-link" @click.stop="handleUserAgreement">《用户服务协议》</text>
        å’Œ
        <text class="agreement-link" @click.stop="handlePrivacy">《隐私政策》</text>
      </text>
    </label>
  </checkbox-group>
</view>
```
已包含 `@click.stop`,正确阻止事件冒泡。
#### 2.2 æ ·å¼ä¼˜åŒ–
**修改前**:
```scss
.agreement-section {
  margin: 30rpx 0;
  .agreement-label {
    display: flex;
    align-items: flex-start;
    checkbox {
      margin-right: 15rpx;
      transform: scale(0.9);
    }
    .agreement-text {
      flex: 1;
      font-size: 24rpx;
      color: #666;
      line-height: 1.6;
      text-align: left;
      .agreement-link {
        color: #007AFF;
        text-decoration: underline;
      }
    }
  }
}
```
**修改后**:
```scss
.agreement-section {
  margin: 30rpx 0;
  .agreement-label {
    display: flex;
    align-items: flex-start;
    checkbox {
      margin-right: 15rpx;
      transform: scale(0.9);
      flex-shrink: 0;          // é˜²æ­¢checkbox被压缩
    }
    .agreement-text {
      flex: 1;
      font-size: 26rpx;        // å¢žå¤§å­—体(原24rpx)
      color: #666;
      line-height: 2;          // å¢žåŠ è¡Œé«˜ï¼ˆåŽŸ1.6)
      text-align: left;
      .agreement-link {
        color: #007AFF;
        text-decoration: underline;
        padding: 8rpx 5rpx;    // å¢žåŠ ç‚¹å‡»åŒºåŸŸ
        display: inline-block;
        position: relative;
        z-index: 10;           // ç¡®ä¿åœ¨æœ€ä¸Šå±‚
      }
    }
  }
}
```
**优化点**:
- âœ… **防止压缩**: checkbox添加 `flex-shrink: 0`
- âœ… **增大字体**: `font-size: 26rpx`(原24rpx)
- âœ… **增加行高**: `line-height: 2`(原1.6)
- âœ… **增加点击区域**: `padding: 8rpx 5rpx`
- âœ… **提高层级**: `z-index: 10`
## ä¼˜åŒ–效果对比
### ç™»å½•页面
| é¡¹ç›® | ä¼˜åŒ–前 | ä¼˜åŒ–后 |
|------|--------|--------|
| ä¸Šè¾¹è· | 20rpx | 50rpx |
| å†…边距 | æ—  | 20rpx 0 |
| è¡Œé«˜ | é»˜è®¤ | 2 |
| ç‚¹å‡»åŒºåŸŸ | ä»…文字 | æ–‡å­— + padding(10rpx 8rpx) |
| z-index | é»˜è®¤ | 10 |
| äº‹ä»¶å†’泡 | å¯èƒ½å†’泡 | å·²é˜»æ­¢(@click.stop) |
### æ³¨å†Œé¡µé¢
| é¡¹ç›® | ä¼˜åŒ–前 | ä¼˜åŒ–后 |
|------|--------|--------|
| å­—体大小 | 24rpx | 26rpx |
| è¡Œé«˜ | 1.6 | 2 |
| ç‚¹å‡»åŒºåŸŸ | ä»…文字 | æ–‡å­— + padding(8rpx 5rpx) |
| z-index | é»˜è®¤ | 10 |
| checkbox压缩 | å¯èƒ½ | å·²é˜²æ­¢(flex-shrink: 0) |
## æŠ€æœ¯è¦ç‚¹
### 1. é˜»æ­¢äº‹ä»¶å†’泡
使用 `@click.stop` æ›¿ä»£ `@click`:
```vue
<!-- é”™è¯¯ -->
<text @click="handlePrivacy">《隐私协议》</text>
<!-- æ­£ç¡® -->
<text @click.stop="handlePrivacy">《隐私协议》</text>
```
**原因**:
- åœ¨uni-app中,特别是在微信小程序环境下,点击事件可能会被父元素捕获
- ä½¿ç”¨ `.stop` ä¿®é¥°ç¬¦å¯ä»¥é˜»æ­¢äº‹ä»¶å†’泡,确保点击只触发当前元素的事件
### 2. å¢žåŠ ç‚¹å‡»çƒ­åŒº
通过 `padding` å¢žåŠ å¯ç‚¹å‡»åŒºåŸŸï¼š
```scss
.agreement-link {
  padding: 10rpx 8rpx;
  display: inline-block;  // å¿…须是块级或行内块级元素
}
```
**效果**:
- ç‚¹å‡»åŒºåŸŸä»Ž "文字宽度" æ‰©å¤§åˆ° "文字宽度 + padding"
- æå‡ç§»åŠ¨ç«¯ç”¨æˆ·ä½“éªŒ
### 3. ç¡®ä¿å…ƒç´ å±‚级
使用 `z-index` å’Œ `position: relative`:
```scss
.agreement-link {
  position: relative;
  z-index: 10;
}
```
**原因**:
- é˜²æ­¢è¢«å…¶ä»–元素(如微信登录按钮)遮挡
- ç¡®ä¿ç‚¹å‡»äº‹ä»¶èƒ½å¤Ÿæ­£å¸¸è§¦å‘
### 4. è§†è§‰åˆ†ç¦»
通过增加间距和行高:
```scss
.xieyi {
  margin: 50rpx 0 30rpx 0;  // å‘下移动
  padding: 20rpx 0;
  line-height: 2;
}
```
**效果**:
- åè®®åŒºåŸŸä¸Žä¸Šæ–¹æŒ‰é’®ä¿æŒè¶³å¤Ÿè·ç¦»
- æ–‡å­—不会拥挤,更易阅读
## æµ‹è¯•要点
### æµ‹è¯•环境
- âœ… å¾®ä¿¡å°ç¨‹åº
- âœ… H5
- âœ… Android App
- âœ… iOS App
### æµ‹è¯•步骤
#### ç™»å½•页面测试
1. æ‰“开登录页面
2. å‘下滚动,查看协议区域是否向下移动
3. ç‚¹å‡»"《用户协议》"链接
4. éªŒè¯æ˜¯å¦è·³è½¬åˆ°ç”¨æˆ·åè®®é¡µé¢
5. è¿”回登录页面
6. ç‚¹å‡»"《隐私协议》"链接
7. éªŒè¯æ˜¯å¦è·³è½¬åˆ°éšç§æ”¿ç­–页面
8. åœ¨ä¸åŒå±å¹•尺寸下测试(大屏、小屏)
#### æ³¨å†Œé¡µé¢æµ‹è¯•
1. æ‰“开注册页面
2. ç‚¹å‡»åè®®checkbox
3. ç‚¹å‡»"《用户服务协议》"链接
4. éªŒè¯æ˜¯å¦è·³è½¬åˆ°ç”¨æˆ·åè®®é¡µé¢ï¼ˆcheckbox状态保持)
5. è¿”回注册页面
6. ç‚¹å‡»"《隐私政策》"链接
7. éªŒè¯æ˜¯å¦è·³è½¬åˆ°éšç§æ”¿ç­–页面
8. éªŒè¯ä¸å‹¾é€‰checkbox时是否能注册
### é¢„期结果
- âœ… åè®®é“¾æŽ¥ä½ç½®å‘下移动,不被其他元素遮挡
- âœ… ç‚¹å‡»åè®®é“¾æŽ¥å“åº”灵敏,无需精确点击文字
- âœ… è·³è½¬æ­£ç¡®ï¼Œèƒ½æ­£å¸¸æŸ¥çœ‹åè®®å†…容
- âœ… æ³¨å†Œé¡µé¢çš„checkbox与协议链接互不干扰
- âœ… å„平台表现一致
## å¯èƒ½çš„问题和解决方案
### é—®é¢˜1: åœ¨æŸäº›è®¾å¤‡ä¸Šç‚¹å‡»ä»ä¸å“åº”
**排查步骤**:
1. æ£€æŸ¥æµè§ˆå™¨æŽ§åˆ¶å°æ˜¯å¦æœ‰é”™è¯¯
2. æ£€æŸ¥è·¯ç”±é…ç½®æ˜¯å¦æ­£ç¡®
3. æ£€æŸ¥åè®®é¡µé¢æ–‡ä»¶æ˜¯å¦å­˜åœ¨
**解决方案**:
```javascript
// æ·»åŠ è°ƒè¯•æ—¥å¿—
handlePrivacy() {
  console.log('点击隐私协议')
  this.$tab.navigateTo('/pages/mine/privacy-policy/index')
}
```
### é—®é¢˜2: ç‚¹å‡»åŒºåŸŸå¤ªå¤§ï¼Œè¯¯è§¦
**解决方案**:
调整 `padding` å€¼ï¼š
```scss
.agreement-link {
  padding: 5rpx 5rpx;  // å‡å°padding
}
```
### é—®é¢˜3: åœ¨å°å±è®¾å¤‡ä¸Šåè®®æ–‡å­—换行显示不美观
**解决方案**:
```scss
.xieyi {
  font-size: 22rpx;  // å‡å°å­—体
  line-height: 1.8;  // è°ƒæ•´è¡Œé«˜
}
```
## åŽç»­ä¼˜åŒ–建议
1. **添加点击反馈**
   ```scss
   .agreement-link {
     &:active {
       opacity: 0.7;
     }
   }
   ```
2. **添加下划线动画**
   ```scss
   .agreement-link {
     position: relative;
     &::after {
       content: '';
       position: absolute;
       bottom: 0;
       left: 0;
       width: 100%;
       height: 1px;
       background-color: #007AFF;
       transform: scaleX(0);
       transition: transform 0.3s;
     }
     &:active::after {
       transform: scaleX(1);
     }
   }
   ```
3. **考虑无障碍访问**
   - æ·»åŠ  `aria-label` å±žæ€§
   - ç¡®ä¿è¶³å¤Ÿçš„颜色对比度
   - æ”¯æŒé”®ç›˜å¯¼èˆª
## æ€»ç»“
本次优化主要解决了:
1. âœ… **位置问题**: åè®®åŒºåŸŸå‘下移动50rpx,避免被遮挡
2. âœ… **点击问题**: å¢žåŠ padding扩大点击热区,添加z-index确保可点击
3. âœ… **交互问题**: ä½¿ç”¨@click.stop阻止事件冒泡,确保点击响应
4. âœ… **视觉问题**: å¢žåŠ è¡Œé«˜å’Œé—´è·ï¼Œæå‡å¯è¯»æ€§
所有修改已经过语法检查,可直接使用。建议在实际设备上进行充分测试,确保各平台表现一致。
prd/°ó¶¨³µÁ¾²¿ÃŹýÂË-ÒÑʵÏÖ.md
New file
@@ -0,0 +1,327 @@
# ç»‘定车辆部门过滤功能说明
## åŠŸèƒ½æ¦‚è¿°
用户绑定车辆时,系统自动限制只能绑定与自己同一分公司的车辆,确保车辆管理的规范性和数据隔离。
## å®žçŽ°çŠ¶æ€
### âœ… å·²å®žçŽ°åŠŸèƒ½
#### 1. å‰ç«¯éƒ¨é—¨è¿‡æ»¤
**文件**: [`app/pages/bind-vehicle.vue`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\app\pages\bind-vehicle.vue)
**核心逻辑**:
```javascript
loadVehicleList() {
  this.loading = true
  // âœ… èŽ·å–å½“å‰ç”¨æˆ·çš„éƒ¨é—¨ID
  const deptId = this.currentUser.deptId
  // âœ… ä¸¥æ ¼éªŒè¯ï¼šéƒ¨é—¨ID不存在时,不加载车辆
  if (!deptId) {
    this.loading = false
    console.error('无法获取用户部门信息')
    this.$modal.showToast('无法获取用户部门信息')
    return
  }
  // âœ… ä½¿ç”¨ç”¨æˆ·å®žé™…部门ID查询车辆
  listAvailableVehicles(deptId, 'GENERAL').then(response => {
    // ...
  })
}
```
**关键特性**:
- âœ… ä¸ä½¿ç”¨é»˜è®¤å€¼ï¼Œä¸¥æ ¼æ£€æŸ¥ [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96)
- âœ… [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96) ä¸ºç©ºæ—¶ï¼Œç»™å‡ºå‹å¥½æç¤º
- âœ… æ— å¯ç”¨è½¦è¾†æ—¶ï¼Œæ˜¾ç¤ºæ˜Žç¡®æç¤ºä¿¡æ¯
- âœ… è®°å½•详细日志便于调试
#### 2. åŽç«¯éƒ¨é—¨è¿‡æ»¤
**接口**: `GET /task/vehicle/available`
**文件**: [`SysTaskVehicleController.java`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-admin\src\main\java\com\ruoyi\web\controller\task\SysTaskVehicleController.java)
```java
@GetMapping("/available")
public AjaxResult getAvailableVehicles(
    @RequestParam Long deptId,           // âœ… å¿…填参数
    @RequestParam(required = false) String taskType) {
    List<SysTaskVehicle> list = sysTaskService.getAvailableVehicles(deptId, taskType);
    return success(list);
}
```
**Service层过滤**:
- âœ… æ ¹æ® [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96) æŸ¥è¯¢è½¦è¾†
- âœ… è¿‡æ»¤ `status='0'` çš„æ­£å¸¸è½¦è¾†
- âœ… è¿‡æ»¤ `car_id` å’Œ `dept_id` ä¸ä¸ºç©ºçš„车辆
## ä¸šåŠ¡æµç¨‹
### åœºæ™¯1:深圳分公司用户绑定车辆
```
用户登录 (deptId: 101)
    â†“
打开绑定车辆页面
    â†“
系统检查 deptId = 101
    â†“
调用 API: /task/vehicle/available?deptId=101&taskType=GENERAL
    â†“
后端查询: SELECT * FROM tb_vehicle_info WHERE dept_id=101 AND status='0'
    â†“
返回结果:
  - ç²¤A12345 (深圳分公司)
  - ç²¤A67890 (深圳分公司)
    â†“
前端显示: ä»…显示深圳分公司的车辆
    â†“
用户选择并绑定
```
### åœºæ™¯2:用户无部门信息
```
用户登录 (deptId: null)
    â†“
打开绑定车辆页面
    â†“
系统检查 deptId = null
    â†“
❌ ç»ˆæ­¢åŠ è½½ï¼Œæ˜¾ç¤ºæç¤ºï¼š"无法获取用户部门信息"
    â†“
车辆列表为空,用户无法绑定
```
### åœºæ™¯3:分公司暂无车辆
```
用户登录 (deptId: 103)
    â†“
打开绑定车辆页面
    â†“
系统检查 deptId = 103
    â†“
调用 API: /task/vehicle/available?deptId=103&taskType=GENERAL
    â†“
后端查询: SELECT * FROM tb_vehicle_info WHERE dept_id=103 AND status='0'
    â†“
返回结果: [] (空数组)
    â†“
前端显示提示:"当前分公司暂无可用车辆"
```
## æ•°æ®éš”离示例
### éƒ¨é—¨ç»“æž„
```
100 (总公司)
├── 101 (深圳分公司)
│   â”œâ”€â”€ ç²¤A12345
│   â”œâ”€â”€ ç²¤A67890
│   â””── ç²¤A11111
├── 102 (广州分公司)
│   â”œâ”€â”€ ç²¤B12345
│   â”œâ”€â”€ ç²¤B67890
│   â””── ç²¤B22222
└── 103 (北京分公司)
    â”œâ”€â”€ äº¬A12345
    â””── äº¬A67890
```
### ç”¨æˆ·å¯è§è½¦è¾†
| ç”¨æˆ· | éƒ¨é—¨ID | å¯è§è½¦è¾† | ä¸å¯è§è½¦è¾† |
|------|--------|---------|-----------|
| å¼ ä¸‰ | 101 (深圳) | ç²¤A12345, ç²¤A67890, ç²¤A11111 | ç²¤B*, äº¬A* |
| æŽå›› | 102 (广州) | ç²¤B12345, ç²¤B67890, ç²¤B22222 | ç²¤A*, äº¬A* |
| çŽ‹äº” | 103 (北京) | äº¬A12345, äº¬A67890 | ç²¤A*, ç²¤B* |
| èµµå…­ | null (无部门) | (无) | (全部) |
## å®‰å…¨æ€§ä¿éšœ
### 1. å‰ç«¯éªŒè¯
- âœ… æ£€æŸ¥ç”¨æˆ·éƒ¨é—¨ä¿¡æ¯æ˜¯å¦å­˜åœ¨
- âœ… ä¸ä½¿ç”¨é»˜è®¤å€¼ 100
- âœ… ç©ºå€¼æ—¶ç»ˆæ­¢åŠ è½½
### 2. åŽç«¯éªŒè¯
- âœ… [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96) ä½œä¸ºå¿…填参数
- âœ… æ•°æ®åº“查询时强制添加部门条件
- âœ… è¿‡æ»¤æ— æ•ˆè½¦è¾†ï¼ˆcar_id、dept_id ä¸ºç©ºï¼‰
### 3. å»ºè®®å¢žå¼ºï¼ˆå¯é€‰ï¼‰
可以在后端Controller中添加权限校验:
```java
@GetMapping("/available")
public AjaxResult getAvailableVehicles(@RequestParam Long deptId, @RequestParam(required = false) String taskType) {
    // âœ… éªŒè¯è¯·æ±‚çš„ deptId æ˜¯å¦ä¸Žç”¨æˆ·çš„ deptId ä¸€è‡´
    LoginUser loginUser = SecurityUtils.getLoginUser();
    Long userDeptId = loginUser.getUser().getDeptId();
    if (!deptId.equals(userDeptId)) {
        return error("无权查询其他部门的车辆");
    }
    List<SysTaskVehicle> list = sysTaskService.getAvailableVehicles(deptId, taskType);
    return success(list);
}
```
## ç›¸å…³æŽ¥å£
### 1. æŸ¥è¯¢å¯ç”¨è½¦è¾†
**接口**: `GET /task/vehicle/available`
**请求参数**:
```
deptId: 101         (必填) éƒ¨é—¨ID
taskType: GENERAL   (可选) ä»»åŠ¡ç±»åž‹
```
**响应示例**:
```json
{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "vehicleId": 1,
      "vehicleNo": "粤A12345",
      "vehicleType": "救护车",
      "vehicleBrand": "福特",
      "vehicleModel": "全顺",
      "deptId": 101,
      "status": "0"
    }
  ]
}
```
**无车辆时**:
```json
{
  "code": 200,
  "msg": "查询成功",
  "data": []
}
```
### 2. ç»‘定车辆
**接口**: `POST /system/vehicle/bind`
**请求体**:
```json
{
  "userId": 1,
  "vehicleId": 123
}
```
### 3. æŸ¥è¯¢ç”¨æˆ·ç»‘定车辆
**接口**: `GET /system/vehicle/user/bound/{userId}`
**响应示例**:
```json
{
  "code": 200,
  "msg": "查询成功",
  "data": {
    "vehicleId": 123,
    "vehicleNumber": "粤A12345",
    "deptId": 101,
    "bindTime": "2025-10-25 10:30:00"
  }
}
```
## ç”¨æˆ·ä½“验优化
### å‹å¥½æç¤ºä¿¡æ¯
| åœºæ™¯ | æç¤ºå†…容 |
|------|---------|
| æ— éƒ¨é—¨ä¿¡æ¯ | "无法获取用户部门信息" |
| æ— å¯ç”¨è½¦è¾† | "当前分公司暂无可用车辆" |
| åŠ è½½å¤±è´¥ | "加载车辆列表失败" |
| é‡å¤ç»‘定 | "当前已绑定此车辆,无需重复绑定" |
| å¼ºåˆ¶ç»‘定确认 | "您当前已绑定车辆:粤A12345,确认要解绑旧车辆并绑定新车辆:粤A67890 å—?" |
### æ—¥å¿—记录
```javascript
// æˆåŠŸåŠ è½½
console.log(`加载了 ${vehicleList.length} è¾†è½¦è¾†ï¼ˆéƒ¨é—¨ID: ${deptId})`)
// æ— éƒ¨é—¨ä¿¡æ¯
console.error('无法获取用户部门信息')
// æ— å¯ç”¨è½¦è¾†
console.log('当前分公司暂无可用车辆')
// åŠ è½½å¤±è´¥
console.error('加载车辆列表失败:', error)
```
## æµ‹è¯•场景
### 1. æ­£å¸¸ç»‘定
- [x] æ·±åœ³ç”¨æˆ·åªèƒ½çœ‹åˆ°æ·±åœ³çš„车辆
- [x] å¹¿å·žç”¨æˆ·åªèƒ½çœ‹åˆ°å¹¿å·žçš„车辆
- [x] ç”¨æˆ·å¯ä»¥æˆåŠŸç»‘å®šæœ¬åˆ†å…¬å¸çš„è½¦è¾†
### 2. è¾¹ç•Œæƒ…况
- [x] ç”¨æˆ·æ— éƒ¨é—¨ä¿¡æ¯ï¼Œæ˜¾ç¤ºæç¤º
- [x] åˆ†å…¬å¸æ— è½¦è¾†ï¼Œæ˜¾ç¤ºæç¤º
- [x] ç½‘络异常,显示错误提示
### 3. æ•°æ®éš”离
- [x] æ·±åœ³ç”¨æˆ·çœ‹ä¸åˆ°å¹¿å·žçš„车辆
- [x] å¹¿å·žç”¨æˆ·çœ‹ä¸åˆ°æ·±åœ³çš„车辆
- [x] ä¸åŒåˆ†å…¬å¸ç”¨æˆ·æ•°æ®å®Œå…¨éš”离
### 4. é‡å¤ç»‘定
- [x] ç»‘定同一车辆,提示已绑定
- [x] ç»‘定其他车辆,提示是否解绑旧车辆
## ç›¸å…³æ–‡ä»¶
### å‰ç«¯
- [`app/pages/bind-vehicle.vue`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\app\pages\bind-vehicle.vue) - ç»‘定车辆页面
- [`app/api/vehicle.js`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\app\api\vehicle.js) - è½¦è¾†API
### åŽç«¯
- [`SysTaskVehicleController.java`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-admin\src\main\java\com\ruoyi\web\controller\task\SysTaskVehicleController.java) - è½¦è¾†Controller
- [`SysTaskServiceImpl.java`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysTaskServiceImpl.java) - ä»»åŠ¡Service
- [`VehicleInfoMapper.xml`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\resources\mapper\system\VehicleInfoMapper.xml) - è½¦è¾†Mapper
### æ–‡æ¡£
- [绑定车辆部门过滤优化.md](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\prd\绑定车辆部门过滤优化.md)
- [车辆绑定解绑功能说明.md](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\prd\车辆绑定解绑功能说明.md)
## æ€»ç»“
✅ **已完成**: ç»‘定车辆时已经实现了部门过滤功能
✅ **前端验证**: ä¸¥æ ¼æ£€æŸ¥ç”¨æˆ·éƒ¨é—¨ä¿¡æ¯ï¼Œä¸ä½¿ç”¨é»˜è®¤å€¼
✅ **后端过滤**: æ ¹æ®éƒ¨é—¨ID查询车辆,确保数据隔离
✅ **用户体验**: æä¾›å‹å¥½çš„æç¤ºä¿¡æ¯å’Œæ—¥å¿—记录
💡 **建议**: å¯ä»¥åœ¨åŽç«¯å¢žåŠ æƒé™æ ¡éªŒï¼ŒéªŒè¯è¯·æ±‚çš„ [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96) æ˜¯å¦ä¸Žç”¨æˆ·çš„ [deptId](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\java\com\ruoyi\system\domain\SysTask.java#L95-L96) ä¸€è‡´ï¼Œè¿›ä¸€æ­¥æé«˜å®‰å…¨æ€§ã€‚
---
**更新时间**: 2025-10-25
**版本**: v1.0
**状态**: âœ… å·²å®žçް
prd/³µÁ¾Í¬²½²¿ÃŲéѯÐÞ¸´ËµÃ÷.md
New file
@@ -0,0 +1,273 @@
# è½¦è¾†åŒæ­¥éƒ¨é—¨æŸ¥è¯¢ä¿®å¤è¯´æ˜Ž
## é—®é¢˜æè¿°
在 `VehicleSyncServiceImpl.findDeptByDispatchOrderClass()` æ–¹æ³•中,虽然设置了 `query.setDispatchOrderClass(dispatchOrderClass)`,但在 `SysDeptMapper.xml` ä¸­çš„ `selectDeptList` æŸ¥è¯¢æ²¡æœ‰å¯¹åº”çš„ `dispatchOrderClass` å’Œ `serviceOrderClass` å­—段条件判断,导致无法正确查询到部门。
## ä¿®å¤å†…容
### 1. ä¿®å¤ SysDeptMapper.xml
**文件**: `ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml`
在 `selectDeptList` æ–¹æ³•中添加了 `serviceOrderClass` å’Œ `dispatchOrderClass` çš„æŸ¥è¯¢æ¡ä»¶ï¼š
```xml
<select id="selectDeptList" parameterType="SysDept" resultMap="SysDeptResult">
    <include refid="selectDeptVo"/>
    where d.del_flag = '0'
    <!-- ... å…¶ä»–条件 ... -->
    <!-- âœ… æ–°å¢žï¼šæœåŠ¡å•ç¼–ç æŸ¥è¯¢ -->
    <if test="serviceOrderClass != null and serviceOrderClass != ''">
        AND service_order_class = #{serviceOrderClass}
    </if>
    <!-- âœ… æ–°å¢žï¼šè°ƒåº¦å•编码查询 -->
    <if test="dispatchOrderClass != null and dispatchOrderClass != ''">
        AND dispatch_order_class = #{dispatchOrderClass}
    </if>
    <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
    ${params.dataScope}
    order by d.parent_id, d.order_num
</select>
```
### 2. ä¼˜åŒ– VehicleSyncServiceImpl
**文件**: `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java`
修改 `parseDeptIdFromCarOrdClass()` æ–¹æ³•,使其在找到部门后自动转换为分公司ID:
**修改前**:
```java
private Long parseDeptIdFromCarOrdClass(String carOrdClass) {
    // ... æŸ¥æ‰¾éƒ¨é—¨é€»è¾‘ ...
    SysDept dept = findDeptByDispatchOrderClass(code);
    if (dept != null) {
        return dept.getDeptId();  // âŒ ç›´æŽ¥è¿”回部门ID
    }
}
```
**修改后**:
```java
private Long parseDeptIdFromCarOrdClass(String carOrdClass) {
    // ... æŸ¥æ‰¾éƒ¨é—¨é€»è¾‘ ...
    SysDept dept = findDeptByDispatchOrderClass(code);
    if (dept != null) {
        // âœ… å°†éƒ¨é—¨ID转换为分公司ID
        Long branchCompanyId = sysDeptMapper.selectBranchCompanyIdByDeptId(dept.getDeptId());
        if (branchCompanyId != null) {
            log.debug("将部门ID {} è½¬æ¢ä¸ºåˆ†å…¬å¸ID: {}", dept.getDeptId(), branchCompanyId);
            return branchCompanyId;
        } else {
            log.warn("部门ID {} æ— æ³•转换为分公司ID,可能是总公司或数据异常", dept.getDeptId());
            return null;
        }
    }
}
```
## ä¿®å¤åŽŸç†
### ä¿®å¤å‰çš„问题流程
```
1. VehicleSyncServiceImpl è®¾ç½®æŸ¥è¯¢æ¡ä»¶
   â”œâ”€ query.setDispatchOrderClass("ZB")
   â””─ sysDeptMapper.selectDeptList(query)
2. SysDeptMapper.xml æ‰§è¡ŒæŸ¥è¯¢
   â”œâ”€ WHERE del_flag = '0'
   â”œâ”€ AND dept_id = ? (如果有)
   â”œâ”€ AND parent_id = ? (如果有)
   â””─ âŒ æ²¡æœ‰ dispatch_order_class æ¡ä»¶
3. ç»“果:查询到所有部门,不是期望的结果
```
### ä¿®å¤åŽçš„æ­£ç¡®æµç¨‹
```
1. VehicleSyncServiceImpl è®¾ç½®æŸ¥è¯¢æ¡ä»¶
   â”œâ”€ query.setDispatchOrderClass("ZB")
   â””─ sysDeptMapper.selectDeptList(query)
2. SysDeptMapper.xml æ‰§è¡ŒæŸ¥è¯¢
   â”œâ”€ WHERE del_flag = '0'
   â”œâ”€ âœ… AND dispatch_order_class = 'ZB'
   â””─ æ‰¾åˆ°åŒ¹é…çš„部门
3. è½¬æ¢ä¸ºåˆ†å…¬å¸ID
   â”œâ”€ è°ƒç”¨ selectBranchCompanyIdByDeptId(deptId)
   â”œâ”€ å¦‚果是分公司,直接返回
   â””─ å¦‚果是子部门,从ancestors中查找分公司ID
4. ç»“果:正确的分公司ID
```
## ä½¿ç”¨åœºæ™¯
### åœºæ™¯1:车辆同步时解析部门
从旧系统同步车辆数据时,根据 `CarOrdClass` å­—段(如 "ZB", "HB.TI")查找对应的分公司:
```java
// CarOrdClass = "ZB"
Long branchCompanyId = parseDeptIdFromCarOrdClass("ZB");
// æµç¨‹ï¼š
// 1. æ‹†åˆ† "ZB" â†’ ["ZB"]
// 2. æŸ¥è¯¢ dispatch_order_class = 'ZB' çš„部门 â†’ æ‰¾åˆ°éƒ¨é—¨201
// 3. å°†éƒ¨é—¨201转换为分公司ID â†’ 101
// 4. è¿”回分公司ID: 101
```
### åœºæ™¯2:多段编码解析
处理包含多个编码的情况:
```java
// CarOrdClass = "HB.TI"
Long branchCompanyId = parseDeptIdFromCarOrdClass("HB.TI");
// æµç¨‹ï¼š
// 1. æ‹†åˆ† "HB.TI" â†’ ["HB", "TI"]
// 2. å…ˆæŸ¥è¯¢ dispatch_order_class = 'HB' â†’ æ‰¾åˆ°éƒ¨é—¨202
// 3. å°†éƒ¨é—¨202转换为分公司ID â†’ 102
// 4. è¿”回分公司ID: 102
```
## æ•°æ®ç¤ºä¾‹
### éƒ¨é—¨è¡¨æ•°æ®
```sql
-- sys_dept è¡¨æ•°æ®ç¤ºä¾‹
dept_id | parent_id | dept_name   | dispatch_order_class | ancestors
--------|-----------|-------------|---------------------|------------
100     | 0         | æ€»å…¬å¸      | NULL                | 0
101     | 100       | åŒ—京分公司   | NULL                | 0,100
102     | 100       | ä¸Šæµ·åˆ†å…¬å¸   | NULL                | 0,100
201     | 101       | åŒ—京急救部   | ZB                  | 0,100,101
202     | 102       | ä¸Šæµ·æ€¥æ•‘部   | HB                  | 0,100,102
203     | 102       | ä¸Šæµ·è½¬è¿éƒ¨   | TI                  | 0,100,102
```
### æŸ¥è¯¢ç¤ºä¾‹
#### ç¤ºä¾‹1:查询 dispatch_order_class = 'ZB' çš„部门
**修复前(查询条件无效)**:
```sql
SELECT * FROM sys_dept WHERE del_flag = '0'
-- è¿”回所有部门(错误)
```
**修复后(正确查询)**:
```sql
SELECT * FROM sys_dept
WHERE del_flag = '0'
  AND dispatch_order_class = 'ZB'
-- è¿”回部门201(正确)
```
#### ç¤ºä¾‹2:将部门ID转换为分公司ID
```java
// è¾“入:deptId = 201 (北京急救部)
Long branchCompanyId = sysDeptMapper.selectBranchCompanyIdByDeptId(201L);
// è¿”回:101 (北京分公司)
// SQL执行逻辑:
// 1. æ£€æŸ¥ dept_id=201 çš„ parent_id æ˜¯å¦ä¸º 100 â†’ å¦ï¼ˆparent_id=101)
// 2. æŸ¥è¯¢ ancestors="0,100,101"
// 3. ä½¿ç”¨ FIND_IN_SET æŸ¥æ‰¾ parent_id=100 çš„部门ID
// 4. æ‰¾åˆ° dept_id=101,返回
```
## æµ‹è¯•验证
### æµ‹è¯•用例1:精确匹配单个编码
```java
// CarOrdClass = "ZB"
Long result = parseDeptIdFromCarOrdClass("ZB");
// é¢„期:101 (北京分公司)
```
### æµ‹è¯•用例2:多段编码匹配
```java
// CarOrdClass = "HB.TI"
Long result = parseDeptIdFromCarOrdClass("HB.TI");
// é¢„期:102 (上海分公司)
```
### æµ‹è¯•用例3:空值处理
```java
// CarOrdClass = null
Long result = parseDeptIdFromCarOrdClass(null);
// é¢„期:null
```
### æµ‹è¯•用例4:未匹配的编码
```java
// CarOrdClass = "UNKNOWN"
Long result = parseDeptIdFromCarOrdClass("UNKNOWN");
// é¢„期:null
// æ—¥å¿—:警告 "未找到匹配CarOrdClass='UNKNOWN' çš„部门"
```
## æ³¨æ„äº‹é¡¹
### 1. éƒ¨é—¨æ•°æ®å®Œæ•´æ€§
确保 `sys_dept` è¡¨ä¸­ï¼š
- `dispatch_order_class` å­—段已正确配置
- åˆ†å…¬å¸çš„ `parent_id = 100`
- å­éƒ¨é—¨çš„ `ancestors` å­—段正确维护
### 2. æ—¥å¿—监控
方法中添加了详细的日志输出:
```java
// è°ƒè¯•日志
log.debug("通过dispatch_order_class='{}' æ‰¾åˆ°éƒ¨é—¨: {} (ID={})", code, dept.getDeptName(), dept.getDeptId());
log.debug("将部门ID {} è½¬æ¢ä¸ºåˆ†å…¬å¸ID: {}", dept.getDeptId(), branchCompanyId);
// è­¦å‘Šæ—¥å¿—
log.warn("部门ID {} æ— æ³•转换为分公司ID,可能是总公司或数据异常", dept.getDeptId());
log.warn("未找到匹配CarOrdClass='{}' çš„部门", carOrdClass);
```
建议在生产环境开启 DEBUG çº§åˆ«æ—¥å¿—,便于排查问题。
### 3. æ€§èƒ½è€ƒè™‘
如果车辆同步量大,建议:
- å¯¹ `dispatch_order_class` å­—段添加索引
- å¯¹ `service_order_class` å­—段添加索引
```sql
CREATE INDEX idx_dispatch_order_class ON sys_dept(dispatch_order_class);
CREATE INDEX idx_service_order_class ON sys_dept(service_order_class);
```
## ç›¸å…³æ–‡ä»¶
- `/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml` - æ·»åŠ æŸ¥è¯¢æ¡ä»¶
- `/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java` - ä¼˜åŒ–转换逻辑
- `/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java` - ä½¿ç”¨ selectBranchCompanyIdByDeptId æ–¹æ³•
- `/prd/部门分公司ID获取方法说明.md` - åˆ†å…¬å¸ID转换方法文档
## æ›´æ–°æ—¥å¿—
- **2025-01-25**: ä¿®å¤ SysDeptMapper.xml ä¸­ç¼ºå°‘查询条件的问题
- **2025-01-25**: ä¼˜åŒ– parseDeptIdFromCarOrdClass æ–¹æ³•,自动转换为分公司ID
- **目的**: ç¡®ä¿è½¦è¾†åŒæ­¥æ—¶èƒ½æ­£ç¡®åŒ¹é…éƒ¨é—¨å¹¶è½¬æ¢ä¸ºåˆ†å…¬å¸ID
prd/³µÁ¾²éѯ²¿ÃÅ×Ô¶¯Æ¥Å书ÄÜ˵Ã÷.md
New file
@@ -0,0 +1,347 @@
# è½¦è¾†æŸ¥è¯¢éƒ¨é—¨è‡ªåŠ¨åŒ¹é…åŠŸèƒ½è¯´æ˜Ž
## åŠŸèƒ½æ¦‚è¿°
在车辆查询时,无论用户传入的是分公司ID还是子部门ID(如技术部、业务部),系统都会自动查找其所属的分公司,并返回该分公司的车辆。
## ä¸šåŠ¡èƒŒæ™¯
### éƒ¨é—¨å±‚级结构
```
100 (总公司)
├── 101 (深圳分公司) â† è½¦è¾†å½’属于分公司
│   â”œâ”€â”€ 201 (技术部)  â† ç”¨æˆ·å¯èƒ½å±žäºŽå­éƒ¨é—¨
│   â”œâ”€â”€ 202 (业务部)
│   â””── 203 (财务部)
├── 102 (广州分公司)
│   â”œâ”€â”€ 204 (技术部)
│   â”œâ”€â”€ 205 (业务部)
│   â””── 206 (财务部)
└── 103 (北京分公司)
    â”œâ”€â”€ 207 (技术部)
    â””── 208 (业务部)
```
### é—®é¢˜åœºæ™¯
**原有逻辑**:
- ç”¨æˆ·A(技术部,deptId=201)查询车辆
- ç³»ç»ŸæŸ¥è¯¢ï¼š`WHERE dept_id = 201`
- ç»“果:❌ æŸ¥ä¸åˆ°è½¦è¾†ï¼ˆå› ä¸ºè½¦è¾†çš„dept_id=101,不是201)
**期望逻辑**:
- ç”¨æˆ·A(技术部,deptId=201)查询车辆
- ç³»ç»Ÿè‡ªåŠ¨æ‰¾åˆ°åˆ†å…¬å¸ï¼š201 â†’ 101(深圳分公司)
- ç³»ç»ŸæŸ¥è¯¢ï¼š`WHERE dept_id = 101`
- ç»“果:✅ æŸ¥åˆ°æ·±åœ³åˆ†å…¬å¸çš„æ‰€æœ‰è½¦è¾†
## å®žçŽ°æ–¹æ¡ˆ
### SQL查询逻辑
**文件**:[`VehicleInfoMapper.xml`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\resources\mapper\system\VehicleInfoMapper.xml)
```xml
<!-- éƒ¨é—¨è¿‡æ»¤ï¼šè‡ªåŠ¨æŸ¥æ‰¾ä¼ å…¥éƒ¨é—¨æ‰€å±žçš„åˆ†å…¬å¸ï¼ˆparent_id=100) -->
<if test="deptId != null">
    and v.dept_id = (
        <!-- å¦‚果传入的就是分公司(parent_id=100),直接返回 -->
        select case
            when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100)
            then #{deptId}
            else (
                <!-- å¦åˆ™ä»Ž ancestors ä¸­æŸ¥æ‰¾åˆ†å…¬å¸ID -->
                select d.dept_id
                from sys_dept d
                where d.parent_id = 100
                and FIND_IN_SET(d.dept_id, (
                    select ancestors from sys_dept where dept_id = #{deptId}
                ))
                limit 1
            )
        end
    )
</if>
```
### æŸ¥è¯¢é€»è¾‘说明
#### æ­¥éª¤1:判断传入的deptId是否为分公司
```sql
when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100)
```
- å¦‚果传入的 `deptId` çš„ `parent_id = 100`,说明传入的就是分公司
- ç›´æŽ¥ä½¿ç”¨è¯¥ `deptId` æŸ¥è¯¢
#### æ­¥éª¤2:如果不是分公司,从ancestors中查找
```sql
select d.dept_id
from sys_dept d
where d.parent_id = 100
and FIND_IN_SET(d.dept_id, (
    select ancestors from sys_dept where dept_id = #{deptId}
))
```
**原理**:
- æ¯ä¸ªéƒ¨é—¨çš„ `ancestors` å­—段存储了所有上级部门ID(用逗号分隔)
- ä¾‹å¦‚:技术部(201)的 `ancestors` å¯èƒ½æ˜¯ `"100,101,201"`
- ä½¿ç”¨ `FIND_IN_SET` åœ¨ ancestors ä¸­æŸ¥æ‰¾ `parent_id=100` çš„部门
- æ‰¾åˆ°çš„就是分公司ID
## ä½¿ç”¨ç¤ºä¾‹
### ç¤ºä¾‹1:传入分公司ID
**输入**:
```javascript
deptId: 101  // æ·±åœ³åˆ†å…¬å¸
```
**SQL执行**:
```sql
-- æ£€æŸ¥ï¼š101 çš„ parent_id = 100 âœ…
-- ç›´æŽ¥ä½¿ç”¨ï¼šdept_id = 101
WHERE v.dept_id = 101
```
**结果**:✅ è¿”回深圳分公司的所有车辆
### ç¤ºä¾‹2:传入子部门ID
**输入**:
```javascript
deptId: 201  // æ·±åœ³åˆ†å…¬å¸-技术部
```
**数据**:
```sql
-- sys_dept è¡¨æ•°æ®
dept_id | parent_id | ancestors
101     | 100       | 100,101
201     | 101       | 100,101,201
```
**SQL执行**:
```sql
-- 1. æ£€æŸ¥ï¼š201 çš„ parent_id = 100 âŒ
-- 2. æŸ¥è¯¢ ancestors:select ancestors from sys_dept where dept_id = 201
--    ç»“果:"100,101,201"
-- 3. åœ¨ ancestors ä¸­æŸ¥æ‰¾ parent_id=100 çš„部门
--    FIND_IN_SET(d.dept_id, "100,101,201") and d.parent_id = 100
--    æ‰¾åˆ°ï¼š101
-- 4. ä½¿ç”¨ï¼šdept_id = 101
WHERE v.dept_id = 101
```
**结果**:✅ è¿”回深圳分公司的所有车辆
### ç¤ºä¾‹3:传入孙部门ID
**输入**:
```javascript
deptId: 301  // æ·±åœ³åˆ†å…¬å¸-技术部-开发组
```
**数据**:
```sql
-- sys_dept è¡¨æ•°æ®
dept_id | parent_id | ancestors
101     | 100       | 100,101
201     | 101       | 100,101,201
301     | 201       | 100,101,201,301
```
**SQL执行**:
```sql
-- 1. æ£€æŸ¥ï¼š301 çš„ parent_id = 100 âŒ
-- 2. æŸ¥è¯¢ ancestors:"100,101,201,301"
-- 3. åœ¨ ancestors ä¸­æŸ¥æ‰¾ parent_id=100 çš„部门
--    æ‰¾åˆ°ï¼š101
-- 4. ä½¿ç”¨ï¼šdept_id = 101
WHERE v.dept_id = 101
```
**结果**:✅ è¿”回深圳分公司的所有车辆
## åº”用场景
### åœºæ™¯1:绑定车辆
**用户**:技术部员工(deptId=201)
```javascript
// å‰ç«¯è°ƒç”¨
listAvailableVehicles(201, 'GENERAL')
// åŽç«¯æŸ¥è¯¢
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
    -- è‡ªåŠ¨æ‰¾åˆ°åˆ†å…¬å¸ï¼š201 â†’ 101
    ...
)
```
**结果**:显示深圳分公司的所有车辆
### åœºæ™¯2:创建任务
**用户**:业务部员工(deptId=202)
```javascript
// å‰ç«¯è°ƒç”¨
listAvailableVehicles(202, 'EMERGENCY')
// åŽç«¯æŸ¥è¯¢
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
    -- è‡ªåŠ¨æ‰¾åˆ°åˆ†å…¬å¸ï¼š202 â†’ 101
    ...
)
```
**结果**:显示深圳分公司的所有车辆
## æ•°æ®æµç¨‹å›¾
```mermaid
sequenceDiagram
    participant User as ç”¨æˆ·(技术部)
    participant Page as å‰ç«¯é¡µé¢
    participant API as åŽç«¯API
    participant DB as æ•°æ®åº“
    User->>Page: æ‰“开绑定车辆页面
    Page->>Page: èŽ·å–ç”¨æˆ·éƒ¨é—¨ID: 201
    Page->>API: listAvailableVehicles(201, 'GENERAL')
    API->>DB: SELECT dept_id FROM sys_dept WHERE dept_id=201
    DB-->>API: parent_id=101 (不是100)
    API->>DB: SELECT ancestors FROM sys_dept WHERE dept_id=201
    DB-->>API: "100,101,201"
    API->>DB: FIND_IN_SET in ancestors WHERE parent_id=100
    DB-->>API: æ‰¾åˆ°åˆ†å…¬å¸ID: 101
    API->>DB: SELECT * FROM tb_vehicle_info WHERE dept_id=101
    DB-->>API: æ·±åœ³åˆ†å…¬å¸çš„车辆列表
    API-->>Page: è¿”回车辆数据
    Page-->>User: æ˜¾ç¤ºæ·±åœ³åˆ†å…¬å¸çš„车辆
```
## å…¼å®¹æ€§
### âœ… æ”¯æŒçš„场景
| è¾“å…¥deptId | éƒ¨é—¨ç±»åž‹ | æŸ¥è¯¢ç»“æžœ |
|-----------|---------|---------|
| 101 | åˆ†å…¬å¸ | 101的车辆 âœ… |
| 201 | å­éƒ¨é—¨ | 101的车辆 âœ… |
| 301 | å­™éƒ¨é—¨ | 101的车辆 âœ… |
| 401 | æ›¾å­™éƒ¨é—¨ | 101的车辆 âœ… |
### âš ï¸ ç‰¹æ®Šæƒ…况
| è¾“å…¥deptId | è¯´æ˜Ž | æŸ¥è¯¢ç»“æžœ |
|-----------|------|---------|
| 100 | æ€»å…¬å¸ | âŒ æŸ¥ä¸åˆ°ï¼ˆè½¦è¾†å¿…须归属于分公司) |
| null | ç©ºå€¼ | âŒ ä¸æ‰§è¡Œéƒ¨é—¨è¿‡æ»¤ |
## æ€§èƒ½ä¼˜åŒ–
### ç´¢å¼•建议
为了提高查询性能,建议在 `sys_dept` è¡¨æ·»åŠ ç´¢å¼•ï¼š
```sql
-- éƒ¨é—¨è¡¨ç´¢å¼•
CREATE INDEX idx_parent_id ON sys_dept(parent_id);
CREATE INDEX idx_ancestors ON sys_dept(ancestors(100));
-- è½¦è¾†è¡¨ç´¢å¼•(已存在)
CREATE INDEX idx_dept_id ON tb_vehicle_info(dept_id);
```
### æŸ¥è¯¢ä¼˜åŒ–
- âœ… ä½¿ç”¨ `CASE WHEN` å‡å°‘子查询次数
- âœ… ä½¿ç”¨ `LIMIT 1` é™åˆ¶ç»“果集
- âœ… `FIND_IN_SET` åˆ©ç”¨ç´¢å¼•查询
## æµ‹è¯•验证
### æµ‹è¯•场景1:分公司用户
```sql
-- æ¨¡æ‹Ÿè¾“入:deptId = 101
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
    select case
        when exists(select 1 from sys_dept where dept_id = 101 and parent_id = 100)
        then 101
        else (...)
    end
)
-- ç»“果:dept_id = 101
```
### æµ‹è¯•场景2:子部门用户
```sql
-- æ¨¡æ‹Ÿè¾“入:deptId = 201
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
    select case
        when exists(select 1 from sys_dept where dept_id = 201 and parent_id = 100)
        then 201
        else (
            select d.dept_id
            from sys_dept d
            where d.parent_id = 100
            and FIND_IN_SET(d.dept_id, (
                select ancestors from sys_dept where dept_id = 201
            ))
            limit 1
        )
    end
)
-- ç»“果:dept_id = 101
```
## å½±å“èŒƒå›´
### ä¿®æ”¹çš„æ–‡ä»¶
- [`VehicleInfoMapper.xml`](file://d:\project\急救转运\code\Api\RuoYi-Vue-master\ruoyi-system\src\main\resources\mapper\system\VehicleInfoMapper.xml) - è½¦è¾†æŸ¥è¯¢Mapper
### å½±å“çš„功能
1. âœ… ç»‘定车辆 - è‡ªåŠ¨æ˜¾ç¤ºåˆ†å…¬å¸è½¦è¾†
2. âœ… åˆ›å»ºä»»åŠ¡ - è‡ªåŠ¨æ˜¾ç¤ºåˆ†å…¬å¸è½¦è¾†
3. âœ… è½¦è¾†ç®¡ç† - è‡ªåŠ¨æŒ‰åˆ†å…¬å¸è¿‡æ»¤
4. âœ… æ‰€æœ‰è°ƒç”¨ `selectVehicleInfoList` çš„地方
### å‘后兼容
- âœ… ä¼ å…¥åˆ†å…¬å¸ID仍然正常工作
- âœ… ä¼ å…¥å­éƒ¨é—¨ID自动转换为分公司ID
- âœ… ä¸å½±å“å…¶ä»–查询条件
## æ€»ç»“
### âœ… ä¼˜åŠ¿
1. **自动匹配** - æ— è®ºç”¨æˆ·åœ¨å“ªä¸ªå±‚级的部门,都能看到分公司的车辆
2. **用户友好** - ç”¨æˆ·ä¸éœ€è¦å…³å¿ƒè‡ªå·±æ˜¯åœ¨å“ªä¸ªå­éƒ¨é—¨
3. **数据隔离** - ä¾ç„¶ä¿æŒåˆ†å…¬å¸ä¹‹é—´çš„æ•°æ®éš”离
4. **向后兼容** - ä¸å½±å“çŽ°æœ‰åŠŸèƒ½
### ðŸ“ æ³¨æ„äº‹é¡¹
1. **ancestors字段** - ä¾èµ– `sys_dept` è¡¨çš„ `ancestors` å­—段正确维护
2. **性能** - å»ºè®®æ·»åŠ ç´¢å¼•ä»¥æé«˜æŸ¥è¯¢æ€§èƒ½
3. **总公司** - ä¼ å…¥æ€»å…¬å¸ID(100)不会返回车辆
---
**更新时间**: 2025-10-25
**版本**: v1.0
**状态**: âœ… å·²å®žçް
prd/²¿ÃÅ·Ö¹«Ë¾ID»ñÈ¡·½·¨ËµÃ÷.md
New file
@@ -0,0 +1,231 @@
# éƒ¨é—¨åˆ†å…¬å¸ID获取方法说明
## æ¦‚è¿°
新增了独立的方法 `selectBranchCompanyIdByDeptId`,用于获取指定部门ID对应的分公司ID(parent_id=100的部门)。
## æ–¹æ³•定义
### Mapper接口
**文件**: `SysDeptMapper.java`
```java
/**
 * èŽ·å–æŒ‡å®šéƒ¨é—¨ID的分公司ID(parent_id=100的部门)
 * å¦‚果传入的就是分公司,直接返回;否则从ancestors中查找分公司ID
 *
 * @param deptId éƒ¨é—¨ID
 * @return åˆ†å…¬å¸ID,如果找不到则返回null
 */
public Long selectBranchCompanyIdByDeptId(@Param("deptId") Long deptId);
```
### SQL实现
**文件**: `SysDeptMapper.xml`
```xml
<!-- èŽ·å–æŒ‡å®šéƒ¨é—¨ID的分公司ID(parent_id=100的部门) -->
<select id="selectBranchCompanyIdByDeptId" parameterType="Long" resultType="Long">
    select case
        -- å¦‚果传入的就是分公司(parent_id=100),直接返回
        when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100 and del_flag = '0')
        then #{deptId}
        else (
            -- å¦åˆ™ä»Ž ancestors ä¸­æŸ¥æ‰¾åˆ†å…¬å¸ID
            select d.dept_id
            from sys_dept d
            where d.parent_id = 100
            and d.del_flag = '0'
            and FIND_IN_SET(d.dept_id, (
                select ancestors from sys_dept where dept_id = #{deptId} and del_flag = '0'
            ))
            limit 1
        )
    end
</select>
```
## ä½¿ç”¨ç¤ºä¾‹
### åœ¨Service层中使用
```java
@Autowired
private SysDeptMapper deptMapper;
public void someMethod(Long deptId) {
    // èŽ·å–åˆ†å…¬å¸ID
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(deptId);
    if (branchCompanyId != null) {
        // ä½¿ç”¨åˆ†å…¬å¸ID进行后续操作
        System.out.println("分公司ID: " + branchCompanyId);
    } else {
        // æ‰¾ä¸åˆ°åˆ†å…¬å¸ï¼ˆå¯èƒ½æ˜¯æ€»å…¬å¸æˆ–数据异常)
        System.out.println("未找到分公司ID");
    }
}
```
### åœ¨MyBatis XML中使用
可以在其他Mapper的SQL中作为子查询使用:
```xml
<select id="someQuery" resultType="SomeType">
    SELECT * FROM some_table
    WHERE dept_id = (
        SELECT CASE
            WHEN EXISTS(SELECT 1 FROM sys_dept WHERE dept_id = #{deptId} AND parent_id = 100 AND del_flag = '0')
            THEN #{deptId}
            ELSE (
                SELECT d.dept_id
                FROM sys_dept d
                WHERE d.parent_id = 100
                AND d.del_flag = '0'
                AND FIND_IN_SET(d.dept_id, (
                    SELECT ancestors FROM sys_dept WHERE dept_id = #{deptId} AND del_flag = '0'
                ))
                LIMIT 1
            )
        END
    )
</select>
```
## å·¥ä½œåŽŸç†
### éƒ¨é—¨ç»“构示例
```
总公司 (dept_id=100, parent_id=0, ancestors="0")
├── åŒ—京分公司 (dept_id=101, parent_id=100, ancestors="0,100")
│   â”œâ”€â”€ æŠ€æœ¯éƒ¨ (dept_id=201, parent_id=101, ancestors="0,100,101")
│   â””── ä¸šåŠ¡éƒ¨ (dept_id=202, parent_id=101, ancestors="0,100,101")
└── ä¸Šæµ·åˆ†å…¬å¸ (dept_id=102, parent_id=100, ancestors="0,100")
    â””── å¸‚场部 (dept_id=203, parent_id=102, ancestors="0,100,102")
```
### æŸ¥è¯¢é€»è¾‘
1. **传入分公司ID** (如: deptId=101)
   - æ£€æŸ¥ `parent_id = 100` âœ…
   - ç›´æŽ¥è¿”回: `101`
2. **传入子部门ID** (如: deptId=201)
   - æ£€æŸ¥ `parent_id = 100` âŒ
   - æŸ¥è¯¢ `ancestors = "0,100,101"`
   - ä½¿ç”¨ `FIND_IN_SET` æŸ¥æ‰¾ `parent_id=100` çš„部门
   - æ‰¾åˆ°åŒ¹é…: `101`
   - è¿”回: `101`
3. **传入总公司ID** (如: deptId=100)
   - æ£€æŸ¥ `parent_id = 100` âŒ (parent_id=0)
   - ancestors中没有parent_id=100的部门
   - è¿”回: `null`
## åº”用场景
### 1. è½¦è¾†æŸ¥è¯¢
用户在任意部门,查询时自动定位到所属分公司的车辆:
```java
// åŽŸå§‹å®žçŽ°ï¼ˆVehicleInfoMapper.xml)
Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(userDeptId);
List<VehicleInfo> vehicles = vehicleMapper.selectByDeptId(branchCompanyId);
```
### 2. æ•°æ®æƒé™è¿‡æ»¤
限制用户只能查看所属分公司的数据:
```java
public List<SomeData> getDataList(Long userDeptId) {
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(userDeptId);
    return someMapper.selectByBranchCompany(branchCompanyId);
}
```
### 3. æŠ¥è¡¨ç»Ÿè®¡
按分公司维度统计数据:
```java
public Map<String, Object> getStatistics(Long deptId) {
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(deptId);
    return statisticsService.getByBranchCompany(branchCompanyId);
}
```
## æ€§èƒ½ä¼˜åŒ–建议
### 1. æ·»åŠ ç´¢å¼•
确保以下字段有索引:
```sql
-- å·²æœ‰çš„索引
CREATE INDEX idx_parent_id ON sys_dept(parent_id);
CREATE INDEX idx_del_flag ON sys_dept(del_flag);
-- å»ºè®®æ·»åŠ å¤åˆç´¢å¼•
CREATE INDEX idx_parent_del ON sys_dept(parent_id, del_flag);
```
### 2. ç»“果缓存
对于频繁查询的场景,可以考虑缓存结果:
```java
@Cacheable(value = "branchCompany", key = "#deptId")
public Long getBranchCompanyId(Long deptId) {
    return deptMapper.selectBranchCompanyIdByDeptId(deptId);
}
```
## æ³¨æ„äº‹é¡¹
1. **返回值可能为null**
   - æ€»å…¬å¸ï¼ˆdept_id=100)查询时会返回null
   - éƒ¨é—¨æ•°æ®å¼‚常时也会返回null
   - ä½¿ç”¨æ—¶éœ€è¦åšç©ºå€¼åˆ¤æ–­
2. **只查询正常部门**
   - SQL中已过滤 `del_flag = '0'`
   - è¢«åˆ é™¤çš„部门不会被查询到
3. **分公司定义**
   - åˆ†å…¬å¸å¿…须满足 `parent_id = 100`
   - å¦‚果组织架构调整,需要确保这个规则仍然适用
4. **ancestors字段维护**
   - éƒ¨é—¨å±‚级变更时必须更新ancestors字段
   - ancestors格式必须是逗号分隔的ID列表
## æµ‹è¯•场景
### æµ‹è¯•用例1: ä¼ å…¥åˆ†å…¬å¸ID
```
输入: deptId = 101 (北京分公司)
预期输出: 101
```
### æµ‹è¯•用例2: ä¼ å…¥å­éƒ¨é—¨ID
```
输入: deptId = 201 (技术部)
预期输出: 101 (北京分公司)
```
### æµ‹è¯•用例3: ä¼ å…¥æ€»å…¬å¸ID
```
输入: deptId = 100 (总公司)
预期输出: null
```
### æµ‹è¯•用例4: ä¼ å…¥å¤šçº§å­éƒ¨é—¨ID
```
输入: deptId = 301 (假设技术部下的小组,ancestors="0,100,101,201")
预期输出: 101 (北京分公司)
```
## æ›´æ–°æ—¥å¿—
- **2025-01-25**: åˆ›å»ºç‹¬ç«‹æ–¹æ³• `selectBranchCompanyIdByDeptId`
- ç›®çš„: ç®€åŒ–分公司ID查询逻辑,提高代码复用性
prd/Òþ˽Õþ²ßºÍÓû§Ð­ÒéÄäÃû·ÃÎÊÅäÖÃ.md
New file
@@ -0,0 +1,449 @@
# éšç§æ”¿ç­–和用户协议匿名访问配置说明
## ä¸€ã€éœ€æ±‚背景
根据法律法规和用户体验要求:
- ç”¨æˆ·åœ¨æ³¨å†Œ/登录前应能查看《隐私政策》和《用户服务协议》
- è¿™ä¸¤ä¸ªé¡µé¢éœ€è¦æ”¯æŒ**匿名访问**(无需登录)
- ç”¨æˆ·å¯ä»¥å……分了解协议内容后再决定是否注册
## äºŒã€å®žçŽ°æ–¹æ¡ˆ
### 2.1 ä¿®æ”¹å†…容
**文件**: `app/permission.js`
**修改前**:
```javascript
// é¡µé¢ç™½åå•
const whiteList = [
  '/pages/login', '/pages/register', '/pages/common/webview/index'
]
```
**修改后**:
```javascript
// é¡µé¢ç™½åå•
const whiteList = [
  '/pages/login',
  '/pages/register',
  '/pages/common/webview/index',
  '/pages/mine/privacy-policy/index',  // éšç§æ”¿ç­–(匿名访问)
  '/pages/mine/user-agreement/index'   // ç”¨æˆ·åè®®ï¼ˆåŒ¿åè®¿é—®ï¼‰
]
```
### 2.2 å·¥ä½œåŽŸç†
**权限拦截机制**:
1. **拦截所有页面跳转**
   - `navigateTo`: ä¿ç•™å½“前页面,跳转到新页面
   - `redirectTo`: å…³é—­å½“前页面,跳转到新页面
   - `reLaunch`: å…³é—­æ‰€æœ‰é¡µé¢ï¼Œæ‰“开到应用内的某个页面
   - `switchTab`: è·³è½¬åˆ° tabBar é¡µé¢
2. **检查用户登录状态**
   ```javascript
   if (getToken()) {
     // å·²ç™»å½•:允许访问
     return true
   }
   ```
3. **未登录时检查白名单**
   ```javascript
   if (checkWhite(to.url)) {
     // åœ¨ç™½åå•中:允许访问
     return true
   } else {
     // ä¸åœ¨ç™½åå•:跳转到登录页
     uni.reLaunch({ url: loginPage })
     return false
   }
   ```
## ä¸‰ã€ç™½åå•页面列表
| é¡µé¢è·¯å¾„ | è¯´æ˜Ž | ç”¨é€” |
|---------|------|------|
| `/pages/login` | ç™»å½•页面 | ç”¨æˆ·ç™»å½•入口 |
| `/pages/register` | æ³¨å†Œé¡µé¢ | ç”¨æˆ·æ³¨å†Œå…¥å£ |
| `/pages/common/webview/index` | WebView页面 | åŠ è½½å¤–éƒ¨ç½‘é¡µ |
| `/pages/mine/privacy-policy/index` | éšç§æ”¿ç­– | å±•示隐私保护政策(新增) |
| `/pages/mine/user-agreement/index` | ç”¨æˆ·åè®® | å±•示服务协议(新增) |
## å››ã€ä½¿ç”¨åœºæ™¯
### åœºæ™¯1: ç™»å½•页面查看协议
**用户操作**:
```
登录页面 â†’ ç‚¹å‡»ã€Šéšç§åè®®ã€‹æˆ–《用户协议》
           â†“
         æŸ¥çœ‹åè®®å†…容(无需登录)
           â†“
         è¿”回登录页面
```
**代码实现**:
```vue
<!-- app/pages/login.vue -->
<view class="xieyi text-center">
  <text class="text-grey1">登录即代表同意</text>
  <text @click.stop="handleUserAgrement" class="text-blue">《用户协议》</text>
  <text class="text-grey1">和</text>
  <text @click.stop="handlePrivacy" class="text-blue">《隐私协议》</text>
</view>
<script>
methods: {
  handlePrivacy() {
    // âœ… å¯ä»¥ç›´æŽ¥è·³è½¬ï¼Œæ— éœ€ç™»å½•
    this.$tab.navigateTo('/pages/mine/privacy-policy/index')
  },
  handleUserAgrement() {
    // âœ… å¯ä»¥ç›´æŽ¥è·³è½¬ï¼Œæ— éœ€ç™»å½•
    this.$tab.navigateTo('/pages/mine/user-agreement/index')
  }
}
</script>
```
### åœºæ™¯2: æ³¨å†Œé¡µé¢æŸ¥çœ‹åè®®
**用户操作**:
```
注册页面 â†’ ç‚¹å‡»åè®®é“¾æŽ¥
           â†“
         æŸ¥çœ‹åè®®å†…容(无需登录)
           â†“
         è¿”回注册页面 â†’ å‹¾é€‰åŒæ„ â†’ å®Œæˆæ³¨å†Œ
```
**代码实现**:
```vue
<!-- app/pages/register.vue -->
<view class="agreement-section">
  <checkbox-group @change="handleAgreementChange">
    <label class="agreement-label">
      <checkbox value="agreed" :checked="agreedToTerms" color="#007AFF" />
      <text class="agreement-text">
        æˆ‘已阅读并同意
        <text class="agreement-link" @click.stop="handleUserAgreement">《用户服务协议》</text>
        å’Œ
        <text class="agreement-link" @click.stop="handlePrivacy">《隐私政策》</text>
      </text>
    </label>
  </checkbox-group>
</view>
<script>
methods: {
  handlePrivacy() {
    // âœ… å¯ä»¥ç›´æŽ¥è·³è½¬ï¼Œæ— éœ€ç™»å½•
    this.$tab.navigateTo('/pages/mine/privacy-policy/index')
  },
  handleUserAgreement() {
    // âœ… å¯ä»¥ç›´æŽ¥è·³è½¬ï¼Œæ— éœ€ç™»å½•
    this.$tab.navigateTo('/pages/mine/user-agreement/index')
  }
}
</script>
```
### åœºæ™¯3: å·²ç™»å½•用户查看协议
**用户操作**:
```
我的页面 â†’ ç‚¹å‡»"用户服务协议"或"隐私政策"菜单
           â†“
         æŸ¥çœ‹åè®®å†…容
           â†“
         è¿”回我的页面
```
**代码实现**:
```vue
<!-- app/pages/mine/index.vue -->
<view class="list-cell list-cell-arrow" @click="handleUserAgreement">
  <view class="menu-item-box">
    <view class="iconfont icon-text menu-icon"></view>
    <view>用户服务协议</view>
  </view>
</view>
<script>
methods: {
  handleUserAgreement() {
    // âœ… å·²ç™»å½•用户也可访问
    this.$tab.navigateTo('/pages/mine/user-agreement/index')
  }
}
</script>
```
## äº”、权限控制流程图
```
用户跳转页面
    â†“
检查是否已登录?
    â†“
  æ˜¯ â†’ å…è®¸è®¿é—®æ‰€æœ‰é¡µé¢
    â†“
  å¦ â†’ æ£€æŸ¥æ˜¯å¦åœ¨ç™½åå•?
         â†“
       æ˜¯ â†’ å…è®¸è®¿é—®
         â†“
       å¦ â†’ å¼ºåˆ¶è·³è½¬åˆ°ç™»å½•页
```
## å…­ã€æµ‹è¯•验证
### æµ‹è¯•步骤
#### æµ‹è¯•1: æœªç™»å½•状态访问协议(核心测试)
1. **清除登录状态**
   ```javascript
   // åœ¨æŽ§åˆ¶å°æ‰§è¡Œ
   uni.removeStorageSync('token')
   uni.removeStorageSync('user')
   ```
2. **重启小程序**
   - å¾®ä¿¡å¼€å‘者工具 â†’ ç¼–译
3. **测试登录页面**
   - åº”该自动跳转到登录页面
   - ç‚¹å‡»ã€Šç”¨æˆ·åè®®ã€‹é“¾æŽ¥
   - âœ… åº”该能成功跳转到协议页面(不会被拦截)
   - æŸ¥çœ‹åè®®å†…容
   - ç‚¹å‡»è¿”回按钮
   - âœ… åº”该返回到登录页面
4. **测试注册页面**
   - ä»Žç™»å½•页点击"立即注册"
   - ç‚¹å‡»åè®®é“¾æŽ¥
   - âœ… åº”该能成功跳转到协议页面
   - è¿”回注册页面
   - âœ… checkbox状态保持
#### æµ‹è¯•2: å·²ç™»å½•状态访问协议
1. **正常登录**
   - è´¦å·: admin
   - å¯†ç : admin123
2. **从"我的"页面访问**
   - è¿›å…¥"我的"页面
   - ç‚¹å‡»"用户服务协议"
   - âœ… åº”该能成功跳转
   - è¿”回
   - ç‚¹å‡»"隐私政策"
   - âœ… åº”该能成功跳转
#### æµ‹è¯•3: ç›´æŽ¥è®¿é—®åè®®é¡µé¢
在浏览器中直接输入地址(H5调试):
```
http://localhost:9090/#/pages/mine/privacy-policy/index
http://localhost:9090/#/pages/mine/user-agreement/index
```
✅ åº”该能直接访问,不会跳转到登录页
### é¢„期结果
| æµ‹è¯•场景 | é¢„期结果 |
|---------|---------|
| æœªç™»å½•访问登录页 | âœ… å…è®¸è®¿é—® |
| æœªç™»å½•访问注册页 | âœ… å…è®¸è®¿é—® |
| æœªç™»å½•访问隐私政策 | âœ… å…è®¸è®¿é—®ï¼ˆæ–°å¢žï¼‰ |
| æœªç™»å½•访问用户协议 | âœ… å…è®¸è®¿é—®ï¼ˆæ–°å¢žï¼‰ |
| æœªç™»å½•访问首页 | âŒ è·³è½¬åˆ°ç™»å½•页 |
| æœªç™»å½•访问任务页 | âŒ è·³è½¬åˆ°ç™»å½•页 |
| å·²ç™»å½•访问所有页面 | âœ… å…è®¸è®¿é—® |
## ä¸ƒã€å¸¸è§é—®é¢˜
### é—®é¢˜1: ç‚¹å‡»åè®®é“¾æŽ¥åŽä»è·³è½¬åˆ°ç™»å½•页
**原因**: ç™½åå•路径配置错误
**检查**:
```javascript
// app/permission.js
// ç¡®ä¿è·¯å¾„完全匹配
'/pages/mine/privacy-policy/index'  // âœ… æ­£ç¡®
'/pages/mine/privacy-policy'        // âŒ é”™è¯¯ï¼ˆç¼ºå°‘/index)
```
**解决**: ç¡®ä¿è·¯å¾„与pages.json中的配置一致
---
### é—®é¢˜2: ä»Žåè®®é¡µé¢è¿”回后,登录页或注册页状态丢失
**原因**: ä½¿ç”¨äº†é”™è¯¯çš„跳转方法
**解决**:
```javascript
// âœ… æ­£ç¡®ï¼šä½¿ç”¨navigateTo,保留当前页面
this.$tab.navigateTo('/pages/mine/privacy-policy/index')
// âŒ é”™è¯¯ï¼šä½¿ç”¨redirectTo会关闭当前页面
this.$tab.redirectTo('/pages/mine/privacy-policy/index')
```
---
### é—®é¢˜3: H5环境下刷新协议页面后跳转到登录页
**原因**: H5刷新会重新执行路由守卫
**验证**: è¿™æ˜¯æ­£å¸¸çŽ°è±¡ï¼Œç§»åŠ¨ç«¯ä¸å­˜åœ¨åˆ·æ–°æ“ä½œ
**解决**: å¦‚需H5支持刷新,需要额外配置路由守卫
---
## å…«ã€å®‰å…¨è€ƒè™‘
### 8.1 ç™½åå•范围控制
**原则**: åªå°†å¿…要的页面加入白名单
**当前白名单**:
- âœ… ç™»å½•/注册页面:必须匿名访问
- âœ… åè®®é¡µé¢ï¼šæ³•律要求匿名访问
- âœ… WebView页面:用于显示外部协议链接
**不应加入白名单的页面**:
- âŒ é¦–页
- âŒ ä»»åŠ¡é¡µé¢
- âŒ æ¶ˆæ¯é¡µé¢
- âŒ ä¸ªäººä¿¡æ¯é¡µé¢
- âŒ å…¶ä»–业务功能页面
### 8.2 æ•°æ®å®‰å…¨
**协议页面特点**:
- âœ… çº¯å±•示内容,无敏感数据
- âœ… ä¸æ¶‰åŠAPI调用
- âœ… ä¸éœ€è¦ç”¨æˆ·èº«ä»½éªŒè¯
- âœ… ä¸ä¼šæ³„露系统信息
**安全措施**:
```vue
<!-- åè®®é¡µé¢åªåŒ…含静态内容 -->
<template>
  <view class="agreement-container">
    <!-- åªæœ‰æ–‡æœ¬å†…容,无用户数据 -->
    <view class="agreement-content">
      <text>协议内容...</text>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {}  // æ— æ•æ„Ÿæ•°æ®
  },
  methods: {
    goBack() {
      uni.navigateBack()  // åªæœ‰è¿”回功能
    }
  }
}
</script>
```
## ä¹ã€åŽç»­ä¼˜åŒ–建议
### 9.1 æ·»åŠ åè®®ç‰ˆæœ¬ç®¡ç†
```javascript
// app/config.js
module.exports = {
  agreements: {
    privacyPolicy: {
      version: '1.0',
      lastUpdate: '2025-01-25',
      path: '/pages/mine/privacy-policy/index'
    },
    userAgreement: {
      version: '1.0',
      lastUpdate: '2025-01-25',
      path: '/pages/mine/user-agreement/index'
    }
  }
}
```
### 9.2 è®°å½•用户同意状态
```javascript
// ç”¨æˆ·é¦–次访问时
localStorage.setItem('agreement_accepted', JSON.stringify({
  privacyPolicy: { version: '1.0', acceptedAt: '2025-01-25' },
  userAgreement: { version: '1.0', acceptedAt: '2025-01-25' }
}))
// åè®®æ›´æ–°æ—¶ï¼Œæç¤ºç”¨æˆ·é‡æ–°é˜…读
if (currentVersion !== acceptedVersion) {
  // æ˜¾ç¤ºåè®®æ›´æ–°æç¤º
}
```
### 9.3 æ·»åŠ è®¿é—®ç»Ÿè®¡
```javascript
// ç»Ÿè®¡åè®®é¡µé¢è®¿é—®é‡
onLoad() {
  // ä¸ŠæŠ¥ç»Ÿè®¡æ•°æ®
  uni.request({
    url: '/api/statistics/agreement-view',
    method: 'POST',
    data: {
      type: 'privacy-policy',
      timestamp: new Date().getTime()
    }
  })
}
```
## åã€æ€»ç»“
### å®Œæˆçš„工作
✅ **权限配置**: å·²å°†éšç§æ”¿ç­–和用户协议页面加入白名单
✅ **匿名访问**: ç”¨æˆ·æ— éœ€ç™»å½•即可查看协议内容
✅ **法律合规**: æ»¡è¶³ã€Šä¸ªäººä¿¡æ¯ä¿æŠ¤æ³•》等法规要求
✅ **用户体验**: ç”¨æˆ·å¯åœ¨æ³¨å†Œå‰å……分了解协议
### ä¿®æ”¹çš„æ–‡ä»¶
- âœ… `app/permission.js` - æ·»åŠ åè®®é¡µé¢åˆ°ç™½åå•
### å½±å“çš„页面
- âœ… `app/pages/login.vue` - ç™»å½•页协议链接可正常访问
- âœ… `app/pages/register.vue` - æ³¨å†Œé¡µåè®®é“¾æŽ¥å¯æ­£å¸¸è®¿é—®
- âœ… `app/pages/mine/index.vue` - å·²ç™»å½•用户也可访问
- âœ… `app/pages/mine/privacy-policy/index.vue` - æ”¯æŒåŒ¿åè®¿é—®
- âœ… `app/pages/mine/user-agreement/index.vue` - æ”¯æŒåŒ¿åè®¿é—®
### æµ‹è¯•建议
1. âœ… æ¸…除登录状态,测试未登录访问
2. âœ… ä»Žç™»å½•页点击协议链接测试
3. âœ… ä»Žæ³¨å†Œé¡µç‚¹å‡»åè®®é“¾æŽ¥æµ‹è¯•
4. âœ… ç™»å½•后从"我的"页面访问测试
5. âœ… åœ¨ä¸åŒå¹³å°æµ‹è¯•(H5、微信小程序、App)
---
配置完成!现在用户可以在未登录状态下查看隐私政策和用户协议了。🎉
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -132,4 +132,13 @@
     * @return éƒ¨é—¨ä¿¡æ¯
     */
    public SysDept selectDeptByDepartmentIdAndParentId(@Param("departmentId") Integer departmentId, @Param("parentId") Long parentId);
    /**
     * èŽ·å–æŒ‡å®šéƒ¨é—¨ID的分公司ID(parent_id=100的部门)
     * å¦‚果传入的就是分公司,直接返回;否则从ancestors中查找分公司ID
     *
     * @param deptId éƒ¨é—¨ID
     * @return åˆ†å…¬å¸ID,如果找不到则返回null
     */
    public Long selectBranchCompanyIdByDeptId(@Param("deptId") Long deptId);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -694,6 +694,7 @@
            VehicleInfo queryParam = new VehicleInfo();
            queryParam.setStatus("0"); // 0表示正常状态
            // ä¸è®¾ç½®deptId,查询所有部门的车辆
            queryParam.setDeptId(deptId);
            
            List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
            
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java
@@ -231,12 +231,12 @@
    }
    /**
     * ä»ŽCarOrdClass解析部门ID
     * ä»Ž CarOrdClass è§£æžéƒ¨é—¨ID,并转换为分公司ID
     * CarOrdClass格式可能是:ZB、HB.TI等
     * éœ€è¦æ‹†åˆ†å¹¶åœ¨sys_dept中匹配dispatch_order_class字段
     * 
     * @param carOrdClass è½¦è¾†å•据类型编码
     * @return éƒ¨é—¨ID,如果未找到返回null
     * @return åˆ†å…¬å¸ID,如果未找到返回null
     */
    private Long parseDeptIdFromCarOrdClass(String carOrdClass)
    {
@@ -264,7 +264,19 @@
            {
                log.debug("通过dispatch_order_class='{}' æ‰¾åˆ°éƒ¨é—¨: {} (ID={})", 
                        code, dept.getDeptName(), dept.getDeptId());
                return dept.getDeptId();
                // å°†éƒ¨é—¨ID转换为分公司ID
                Long branchCompanyId = sysDeptMapper.selectBranchCompanyIdByDeptId(dept.getDeptId());
                if (branchCompanyId != null)
                {
                    log.debug("将部门ID {} è½¬æ¢ä¸ºåˆ†å…¬å¸ID: {}", dept.getDeptId(), branchCompanyId);
                    return branchCompanyId;
                }
                else
                {
                    log.warn("部门ID {} æ— æ³•转换为分公司ID,可能是总公司或数据异常", dept.getDeptId());
                    return null;
                }
            }
        }
        
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -45,6 +45,12 @@
        <if test="status != null and status != ''">
            AND status = #{status}
        </if>
        <if test="serviceOrderClass != null and serviceOrderClass != ''">
            AND service_order_class = #{serviceOrderClass}
        </if>
        <if test="dispatchOrderClass != null and dispatchOrderClass != ''">
            AND dispatch_order_class = #{dispatchOrderClass}
        </if>
        <!-- æ•°æ®èŒƒå›´è¿‡æ»¤ -->
        ${params.dataScope}
        order by d.parent_id, d.order_num
@@ -184,4 +190,24 @@
        limit 1
    </select>
    <!-- èŽ·å–æŒ‡å®šéƒ¨é—¨ID的分公司ID(parent_id=100的部门) -->
    <select id="selectBranchCompanyIdByDeptId" parameterType="Long" resultType="Long">
        select case
            -- å¦‚果传入的就是分公司(parent_id=100),直接返回
            when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100 and del_flag = '0')
            then #{deptId}
            else (
                -- å¦åˆ™ä»Ž ancestors ä¸­æŸ¥æ‰¾åˆ†å…¬å¸ID
                select d.dept_id
                from sys_dept d
                where d.parent_id = 100
                and d.del_flag = '0'
                and FIND_IN_SET(d.dept_id, (
                    select ancestors from sys_dept where dept_id = #{deptId} and del_flag = '0'
                ))
                limit 1
            )
        end
    </select>
</mapper> 
ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
@@ -39,7 +39,25 @@
            <if test="vehicleModel != null  and vehicleModel != ''"> and v.vehicle_model = #{vehicleModel}</if>
            <if test="status != null  and status != ''"> and v.status = #{status}</if>
            <if test="platformCode != null  and platformCode != ''"> and v.platform_code = #{platformCode}</if>
            <if test="deptId != null"> and v.dept_id = #{deptId}</if>
            <!-- éƒ¨é—¨è¿‡æ»¤ï¼šè‡ªåŠ¨æŸ¥æ‰¾ä¼ å…¥éƒ¨é—¨æ‰€å±žçš„åˆ†å…¬å¸ï¼ˆparent_id=100) -->
            <if test="deptId != null">
                and v.dept_id = (
                    <!-- å¦‚果传入的就是分公司(parent_id=100),直接返回 -->
                    select case
                        when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100) then #{deptId}
                        else (
                            <!-- å¦åˆ™ä»Ž ancestors ä¸­æŸ¥æ‰¾åˆ†å…¬å¸ID -->
                            select d.dept_id
                            from sys_dept d
                            where d.parent_id = 100
                            and FIND_IN_SET(d.dept_id, (
                                select ancestors from sys_dept where dept_id = #{deptId}
                            ))
                            limit 1
                        )
                    end
                )
            </if>
            <!-- ä»»åŠ¡è½¦è¾†é€‰æ‹©å¿…é¡»è¿‡æ»¤ï¼šåªæ˜¾ç¤ºcar_id和dept_id都不为空的车辆 -->
            and v.car_id is not null and v.car_id != ''
            and v.dept_id is not null
ruoyi-ui/src/views/task/general/detail.vue
@@ -30,6 +30,74 @@
        <el-descriptions-item label="备注" :span="2">{{ taskDetail.remark }}</el-descriptions-item>
      </el-descriptions>
      <!-- æ€¥æ•‘转运任务扩展信息 -->
      <el-descriptions v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo" title="急救转运信息" :column="2" border style="margin-top: 20px;">
        <el-descriptions-item label="患者姓名">{{ taskDetail.emergencyInfo.patientName }}</el-descriptions-item>
        <el-descriptions-item label="患者性别">
          <dict-tag :options="dict.type.sys_user_sex" :value="taskDetail.emergencyInfo.patientGender"/>
        </el-descriptions-item>
        <el-descriptions-item label="患者年龄">{{ taskDetail.emergencyInfo.patientAge }}</el-descriptions-item>
        <el-descriptions-item label="联系电话">{{ taskDetail.emergencyInfo.contactPhone }}</el-descriptions-item>
        <el-descriptions-item label="接送医院" :span="2">{{ taskDetail.emergencyInfo.hospitalName }}</el-descriptions-item>
        <el-descriptions-item label="就诊科室" :span="2">
          <dict-tag v-if="taskDetail.emergencyInfo.hospitalDepartment" :options="dict.type.hospital_department" :value="taskDetail.emergencyInfo.hospitalDepartment"/>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="病情描述" :span="2">
          <span v-if="taskDetail.emergencyInfo.illnessDescription">{{ taskDetail.emergencyInfo.illnessDescription }}</span>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="特殊需求" :span="2">
          <span v-if="taskDetail.emergencyInfo.specialRequirements">{{ taskDetail.emergencyInfo.specialRequirements }}</span>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="是否需要担架">
          <el-tag v-if="taskDetail.emergencyInfo.needsStretcher == 1" type="success" size="small">是</el-tag>
          <el-tag v-else type="info" size="small">否</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="是否需要轮椅">
          <el-tag v-if="taskDetail.emergencyInfo.needsWheelchair == 1" type="success" size="small">是</el-tag>
          <el-tag v-else type="info" size="small">否</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="是否需要氧气">
          <el-tag v-if="taskDetail.emergencyInfo.needsOxygen == 1" type="success" size="small">是</el-tag>
          <el-tag v-else type="info" size="small">否</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="紧急程度">
          <el-tag v-if="taskDetail.emergencyInfo.urgencyLevel === 'HIGH'" type="danger" size="small">紧急</el-tag>
          <el-tag v-else-if="taskDetail.emergencyInfo.urgencyLevel === 'MEDIUM'" type="warning" size="small">一般</el-tag>
          <el-tag v-else-if="taskDetail.emergencyInfo.urgencyLevel === 'LOW'" type="info" size="small">不急</el-tag>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="陪同人数">{{ taskDetail.emergencyInfo.companionCount || 0 }} äºº</el-descriptions-item>
        <el-descriptions-item label="预估费用">{{ taskDetail.emergencyInfo.estimatedCost || '--' }} å…ƒ</el-descriptions-item>
      </el-descriptions>
      <!-- ç¦ç¥‰è½¦ä»»åŠ¡æ‰©å±•ä¿¡æ¯ -->
      <el-descriptions v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo" title="福祉车服务信息" :column="2" border style="margin-top: 20px;">
        <el-descriptions-item label="乘客姓名">{{ taskDetail.welfareInfo.passengerName }}</el-descriptions-item>
        <el-descriptions-item label="乘客性别">
          <dict-tag :options="dict.type.sys_user_sex" :value="taskDetail.welfareInfo.passengerGender"/>
        </el-descriptions-item>
        <el-descriptions-item label="乘客年龄">{{ taskDetail.welfareInfo.passengerAge }}</el-descriptions-item>
        <el-descriptions-item label="联系电话">{{ taskDetail.welfareInfo.contactPhone }}</el-descriptions-item>
        <el-descriptions-item label="服务类型" :span="2">
          <span v-if="taskDetail.welfareInfo.serviceType">{{ taskDetail.welfareInfo.serviceType }}</span>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="特殊需求" :span="2">
          <span v-if="taskDetail.welfareInfo.specialRequirements">{{ taskDetail.welfareInfo.specialRequirements }}</span>
          <span v-else style="color: #C0C4CC;">--</span>
        </el-descriptions-item>
        <el-descriptions-item label="是否需要轮椅">
          <el-tag v-if="taskDetail.welfareInfo.needsWheelchair == 1" type="success" size="small">是</el-tag>
          <el-tag v-else type="info" size="small">否</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="陪同人数">{{ taskDetail.welfareInfo.companionCount || 0 }} äºº</el-descriptions-item>
        <el-descriptions-item label="预估费用">{{ taskDetail.welfareInfo.estimatedCost || '--' }} å…ƒ</el-descriptions-item>
        <el-descriptions-item label="实际费用">{{ taskDetail.welfareInfo.actualCost || '--' }} å…ƒ</el-descriptions-item>
      </el-descriptions>
      <!-- æ“ä½œæŒ‰é’® -->
      <div style="margin-top: 20px; text-align: center;">
        <el-button type="primary" @click="handleEdit" v-hasPermi="['task:general:edit']">编辑任务</el-button>
@@ -299,7 +367,7 @@
export default {
  name: "TaskDetail",
  dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status'],
  dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status', 'sys_user_sex', 'hospital_department'],
  data() {
    return {
      // ä»»åŠ¡è¯¦æƒ…
ruoyi-ui/src/views/task/general/index.vue
@@ -103,9 +103,12 @@
          >{{ scope.row.taskCode }}</el-button>
        </template>
      </el-table-column>
      <el-table-column label="任务类型" align="center" prop="taskType">
      <el-table-column label="任务类型" align="center" prop="taskType" width="120">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
          <el-tag v-if="scope.row.taskType === 'EMERGENCY_TRANSFER'" type="danger" size="mini" style="margin-left: 5px;">
            <i class="el-icon-warning"></i>
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="任务状态" align="center" prop="taskStatus">