wlzboy
2025-12-26 c10b1e130ccbc94e6481a43e8e2d35cfc8fcf83b
feat:显示问题
15个文件已修改
443 ■■■■ 已修改文件
app/api/map.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/index.vue 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/qylogin.vue 133 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pages/task/index.vue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pagesTask/components/DepartmentSelector.vue 69 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pagesTask/components/DepartureSelector.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pagesTask/components/HospitalSelector.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pagesTask/create-emergency.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/pagesTask/edit-emergency.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/utils/request.js 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/QyWechatAccessTokenServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskDispatchSyncUtilService.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/qy_wechat_config.sql 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/map.js
@@ -1,7 +1,7 @@
import request from '@/utils/request'
// 地图地址搜索API
export function searchAddress(keyword, region) {
export function searchTianDiTuAddress(keyword, region) {
  // 参数验证
  if (!keyword) {
    return Promise.reject(new Error('参数不完整,缺少关键词'))
@@ -12,7 +12,7 @@
    url: '/system/gps/tianditu/place/suggestion',
    method: 'get',
    params: {
      keyword: keyword,
      keyWord: keyword,
      region: region || '广州'
    }
  })
app/pages/index.vue
@@ -153,7 +153,7 @@
               
                <view class="info-item">
                  <view class="label">执行人员:</view>
                  <view class="value">{{ task.assignee }}</view>
                  <view class="value">{{ getAssigneesDisplay(task) }}</view>
                </view>
              </view>
            </view>
@@ -607,18 +607,44 @@
    // 获取目的地显示内容(转运任务显示转入医院名称或详细地址)
    getEndLocationDisplay(task) {
      // 如果是转运任务且有emergencyInfo信息
      // console.log("get end location display",task.taskType,task.emergencyInfo.hospitalInAddress,task.showTaskCode);
      if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo) {
        // console.log('转运任务 - 紧急信息:', task.emergencyInfo)
        // 优先显示转入医院名称
        if (task.emergencyInfo.hospitalInName) {
          if(task.emergencyInfo.hospitalInName.includes("家中")){
            return task.emergencyInfo.destinationAddress;
          }
          return task.emergencyInfo.hospitalInName;
        }
        // console.log("get end local",task.emergencyInfo.hospitalInAddress);
        return task.emergencyInfo.hospitalInAddress;
        // if (task.emergencyInfo.hospitalInName) {
        //   if(task.emergencyInfo.hospitalInName.includes("家中")){
        //     return task.emergencyInfo.destinationAddress;
        //   }
        //   return task.emergencyInfo.hospitalInName;
        // }
        // // 如果没有转入医院名称,但有转入医院地址,则显示地址
        // if (task.emergencyInfo.hospitalInAddress) {
        //   return task.emergencyInfo.hospitalInAddress;
        // }
      }
      // 其他情况使用原来的endLocation
      return this.formatAddress(task.endLocation || "未设置");
    },
    // 获取执行人员显示(从 assignees 数组中提取 userName)
    getAssigneesDisplay(task) {
      // 如果有 assignees 数组且不为空
      if (task.assignees && task.assignees.length > 0) {
        // 提取所有 userName,过滤掉空值
        const userNames = task.assignees
          .map(assignee => assignee.userName)
          .filter(name => name); // 过滤掉 null/undefined/空字符串
        // 如果有有效的用户名,用逗号连接
        if (userNames.length > 0) {
          return userNames.join('、');
        }
      }
      // 如果没有 assignees 数组,使用旧的 assigneeName 或 assignee 字段
      return task.assigneeName || task.assignee || '未分配';
    },
    // 转换状态格式(将数据库状态转换为UI使用的状态)
@@ -1394,6 +1420,10 @@
                font-size: 26rpx;
                flex: 1;
                word-break: break-all;
                overflow-wrap: break-word;
                line-height: 1.5;
                max-height: none;
                overflow: visible;
              }
            }
          }
app/pages/qylogin.vue
@@ -38,6 +38,10 @@
    try {
      // 保存页面参数
      this.pageOptions = options || {};
      // 打印环境信息
      this.logEnvironmentInfo();
      // 页面加载时执行免登流程
      this.qyWechatAutoLogin();
    } catch (e) {
@@ -49,6 +53,49 @@
  },
  methods: {
    /**
     * 打印环境信息(调试用)
     */
    logEnvironmentInfo() {
      // #ifdef MP-WEIXIN
      console.log('========== 环境信息 ==========');
      console.log('wx 是否存在:', typeof wx !== 'undefined');
      console.log('wx.qy 是否存在:', typeof wx !== 'undefined' && typeof wx.qy !== 'undefined');
      if (typeof wx !== 'undefined') {
        console.log('wx.login 是否存在:', typeof wx.login === 'function');
        if (typeof wx.qy !== 'undefined') {
          console.log('wx.qy.login 是否存在:', typeof wx.qy.login === 'function');
          console.log('wx.qy 对象:', wx.qy);
        } else {
          console.warn('⚠️ wx.qy 不存在!');
          console.warn('可能原因:');
          console.warn('1. 当前在开发者工具中,wx.qy API 可能不可用');
          console.warn('2. 需要在真机上调试');
          console.warn('3. appid 配置可能不正确');
        }
        // 获取系统信息
        try {
          const systemInfo = wx.getSystemInfoSync();
          console.log('系统信息:', systemInfo);
        } catch (e) {
          console.error('获取系统信息失败:', e);
        }
        // 获取账号信息
        try {
          const accountInfo = wx.getAccountInfoSync();
          console.log('账号信息:', accountInfo);
        } catch (e) {
          console.error('获取账号信息失败:', e);
        }
      }
      console.log('==============================');
      // #endif
    },
    /**
     * 企业微信免登流程
     */
@@ -135,26 +182,80 @@
    },
    /**
     * 等待 wx.qy 对象初始化
     */
    waitForWxQy(timeout = 5000) {
      return new Promise((resolve, reject) => {
        const startTime = Date.now();
        let checkCount = 0;
        const checkWxQy = () => {
          checkCount++;
          const elapsed = Date.now() - startTime;
          if (typeof wx !== 'undefined' && typeof wx.qy !== 'undefined' && typeof wx.qy.login === 'function') {
            console.log(`✅ wx.qy 已初始化 (耗时: ${elapsed}ms, 检查次数: ${checkCount})`);
            resolve(true);
          } else if (elapsed > timeout) {
            console.error(`❌ 等待 wx.qy 初始化超时 (${timeout}ms)`);
            console.error('当前状态:', {
              wx存在: typeof wx !== 'undefined',
              'wx.qy存在': typeof wx !== 'undefined' && typeof wx.qy !== 'undefined',
              检查次数: checkCount
            });
            // 提供更详细的错误信息
            const errorMsg = '企业微信环境初始化超时。\n\n' +
                           '可能的原因:\n' +
                           '1. 当前在开发者工具中,wx.qy API 不可用\n' +
                           '2. 请使用真机预览或真机调试\n' +
                           '3. 检查小程序 appid 是否配置正确';
            reject(new Error(errorMsg));
          } else {
            if (checkCount % 10 === 1) {
              console.log(`⏳ 等待 wx.qy 初始化... (${elapsed}ms, 第${checkCount}次检查)`);
            }
            setTimeout(checkWxQy, 100);
          }
        };
        checkWxQy();
      });
    },
    /**
     * 获取企业微信登录code
     */
    getLoginCode() {
      return new Promise((resolve, reject) => {
      return new Promise(async (resolve, reject) => {
        // #ifdef MP-WEIXIN
        // 使用企业微信小程序API获取code
        wx.qy.login({
          success: (res) => {
            if (res.code) {
              console.log("企业微信小程序 ---> code:", res.code);
              resolve(res.code);
            } else {
              reject(new Error("获取code失败:" + res.errMsg));
            }
          },
          fail: (err) => {
            console.error("wx.qy.login调用失败:", err);
            reject(new Error("企业微信登录接口调用失败:" + err.errMsg));
          },
        });
        try {
          // 检查是否在企业微信小程序环境
          console.log('检查企业微信环境,wx.qy 是否存在:', typeof wx !== 'undefined' && typeof wx.qy !== 'undefined');
          // 等待 wx.qy 初始化完成
          await this.waitForWxQy();
          // 使用企业微信小程序API获取code
          console.log('使用 wx.qy.login 获取code');
          wx.qy.login({
            success: (res) => {
              if (res.code) {
                console.log("企业微信小程序 ---> code:", res.code);
                resolve(res.code);
              } else {
                reject(new Error("获取code失败:" + (res.errMsg || '未知错误')));
              }
            },
            fail: (err) => {
              console.error("wx.qy.login调用失败:", err);
              reject(new Error("企业微信登录接口调用失败:" + (err.errMsg || '未知错误')));
            },
          });
        } catch (error) {
          console.error('获取登录code异常:', error);
          reject(error);
        }
        // #endif
        
        // #ifndef MP-WEIXIN
app/pages/task/index.vue
@@ -188,7 +188,7 @@
                <view class="info-row">
                  <view class="info-item">
                    <view class="label">执行人员:</view>
                    <view class="value">{{ task.assignee }}</view>
                    <view class="value">{{ getAssigneesDisplay(task) }}</view>
                  </view>
                </view>
              </view>
@@ -663,13 +663,36 @@
        // 优先显示转入医院名称
        if (task.emergencyInfo.hospitalInName) {
          if(task.emergencyInfo.hospitalInName.includes("家中")){
            return task.emergencyInfo.destinationAddress;
            return task.emergencyInfo.hospitalInAddress;
          }
          return task.emergencyInfo.hospitalInName;
        }
        }
        // 如果没有转入医院名称,但有转入医院地址,则显示地址
        if (task.emergencyInfo.hospitalInAddress) {
          return task.emergencyInfo.hospitalInAddress;
        }
      }
      // 其他情况使用原来的endLocation
      return this.formatAddress(task.endLocation || "未设置");
    },
    // 获取执行人员显示(从 assignees 数组中提取 userName)
    getAssigneesDisplay(task) {
      // 如果有 assignees 数组且不为空
      if (task.assignees && task.assignees.length > 0) {
        // 提取所有 userName,过滤掉空值
        const userNames = task.assignees
          .map(assignee => assignee.userName)
          .filter(name => name); // 过滤掉 null/undefined/空字符串
        // 如果有有效的用户名,用逗号连接
        if (userNames.length > 0) {
          return userNames.join('、');
        }
      }
      // 如果没有 assignees 数组,使用旧的 assigneeName 或 assignee 字段
      return task.assigneeName || task.assignee || '未分配';
    },
    // 切换查询界面显示/隐藏
@@ -1434,6 +1457,10 @@
              font-size: 26rpx;
              flex: 1;
              word-break: break-all;
              overflow-wrap: break-word;
              line-height: 1.5;
              max-height: none;
              overflow: visible;
            }
          }
        }
app/pagesTask/components/DepartmentSelector.vue
@@ -1,26 +1,24 @@
<template>
  <view class="form-item">
    <view class="form-label" :class="{ required: required }">{{ label }}</view>
    <!-- 调试信息 -->
    <view v-if="false" style="font-size: 24rpx; color: #999; margin-bottom: 10rpx;">
      isHome: {{ isHome }}, options.length: {{ departmentOptions.length }}
    </view>
    <picker 
      v-if="!isHome && departmentOptions.length > 0"
      v-if="!isHome"
      mode="selector" 
      :range="departmentOptions" 
      range-key="text" 
      :value="selectedIndex"
      @change="onDepartmentChange"
      :disabled="departmentOptions.length === 0"
    >
      <view class="form-input picker-input">
      <view class="form-input picker-input" :class="{ disabled: departmentOptions.length === 0 }">
        {{ displayText }}
        <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
      </view>
    </picker>
    <input
      v-else-if="!isHome"
      class="form-input"
      placeholder="请输入科室"
      :value="value"
      @input="onDepartmentInput"
    />
    <view v-else class="form-input picker-input disabled">
      其它
    </view>
@@ -72,6 +70,9 @@
  },
  computed: {
    displayText() {
      if (this.departmentOptions.length === 0) {
        return '加载中...'
      }
      if (this.selectedIndex >= 0 && this.selectedIndex < this.departmentOptions.length) {
        return this.departmentOptions[this.selectedIndex].text
      }
@@ -82,6 +83,7 @@
    value: {
      immediate: true,
      handler(newVal) {
        console.log('DepartmentSelector: value changed:', newVal)
        if (newVal) {
          this.updateSelectedIndex(newVal)
        } else {
@@ -92,6 +94,7 @@
    departmentId: {
      immediate: true,
      handler(newVal) {
        console.log('DepartmentSelector: departmentId changed:', newVal)
        if (newVal) {
          this.updateSelectedIndexById(newVal)
        }
@@ -100,6 +103,8 @@
    departmentOptions: {
      immediate: true,
      handler() {
        console.log('DepartmentSelector: departmentOptions changed, length=', this.departmentOptions.length)
        console.log('DepartmentSelector: 当前显示条件 - isHome:', this.isHome, 'departmentOptions.length:', this.departmentOptions.length, '显示picker:', !this.isHome && this.departmentOptions.length > 0)
        // 优先使用科室ID进行匹配,如果没有科室ID再使用科室名称
        if (this.departmentId) {
          this.updateSelectedIndexById(this.departmentId)
@@ -107,23 +112,46 @@
          this.updateSelectedIndex(this.value)
        }
      }
    },
    isHome: {
      immediate: true,
      handler(newVal) {
        console.log('DepartmentSelector: isHome changed:', newVal)
        // 当变为"家中"时,自动选择"其它"科室
        if (newVal && this.departmentOptions.length > 0) {
          this.autoSelectOtherDepartment()
        }
      }
    }
  },
  mounted() {
    console.log('DepartmentSelector: 组件已挂载, isHome=', this.isHome, 'value=', this.value, 'departmentId=', this.departmentId)
    this.loadDepartments()
  },
  methods: {
    // 加载科室数据
    loadDepartments() {
      console.log('DepartmentSelector: 开始加载科室数据')
      getHospitalDepartments().then(response => {
        console.log('DepartmentSelector: 科室接口响应:', response)
        const list = response.data || []
        console.log('DepartmentSelector: 科室数据条数:', list.length)
        if (list.length > 0) {
          console.log('DepartmentSelector: 科室数据示例:', list.slice(0, 3))
        }
        this.departmentOptions = list.map(item => ({
          id: item.vID,
          text: item.vtext,
          dictValue: item.vtext
        }))
        console.log('DepartmentSelector: 处理后的科室选项:', this.departmentOptions.length)
        // 如果当前是"家中",自动选择"其它"
        if (this.isHome) {
          this.autoSelectOtherDepartment()
        }
      }).catch(error => {
        console.error('加载科室数据失败:', error)
        console.error('DepartmentSelector: 加载科室数据失败:', error)
        this.departmentOptions = []
      })
    },
@@ -185,6 +213,27 @@
        department: department,
        departmentId: null
      })
    },
    // 自动选择"其它"科室(当isHome为true时)
    autoSelectOtherDepartment() {
      // 查找"其它"科室
      const otherDept = this.departmentOptions.find(d => d.text === '其它')
      if (otherDept) {
        console.log('DepartmentSelector: 自动选择"其它"科室, ID:', otherDept.id)
        // 更新选中索引
        const index = this.departmentOptions.findIndex(d => d.id === otherDept.id)
        this.selectedIndex = index
        // 触发change事件,传递departmentId
        this.$emit('input', otherDept.text)
        this.$emit('change', {
          department: otherDept.text,
          departmentId: otherDept.id
        })
      } else {
        console.warn('DepartmentSelector: 未找到"其它"科室')
      }
    }
  }
}
app/pagesTask/components/DepartureSelector.vue
@@ -43,7 +43,7 @@
</template>
<script>
import { baiduPlaceSuggestion, reverseGeocoder } from "@/api/map"
import { baiduPlaceSuggestion, reverseGeocoder ,searchTianDiTuAddress} from "@/api/map"
export default {
  name: 'DepartureSelector',
@@ -153,7 +153,7 @@
    
    // 搜索地址建议
    searchAddress(query) {
      baiduPlaceSuggestion(query, this.region).then(response => {
      searchTianDiTuAddress(query, this.region).then(response => {
        if (response.code === 200 && response.data) {
          this.addressSuggestions = response.data
          this.showAddressSuggestions = true
app/pagesTask/components/HospitalSelector.vue
@@ -45,7 +45,7 @@
            @click="selectAddressSuggestion(item)"
          >
            <view class="suggestion-name">{{ item.name }}</view>
            <view class="suggestion-address">{{ item.district }}{{ item.address }}</view>
            <view class="suggestion-address">{{ (item.district || '') + (item.address || '') }}</view>
          </view>
        </view>
      </view>
@@ -58,7 +58,7 @@
<script>
import { searchHospitals } from "@/api/hospital"
import { baiduPlaceSuggestion } from "@/api/map"
import { searchTianDiTuAddress } from "@/api/map"
export default {
  name: 'HospitalSelector',
@@ -294,7 +294,7 @@
        
    // 搜索地址建议
    searchAddress(query) {
      baiduPlaceSuggestion(query, this.region).then(response => {
      searchTianDiTuAddress(query, this.region).then(response => {
        if (response.code === 200 && response.data) {
          this.addressSuggestions = response.data
          this.showAddressSuggestions = true
@@ -318,7 +318,7 @@
        
    // 选择地址建议
    selectAddressSuggestion(item) {
      const fullAddress = item.district + item.address
      const fullAddress = (item.district || '') + (item.address || '')
      this.$emit('input', {
        ...this.value,
        address: fullAddress
app/pagesTask/create-emergency.vue
@@ -567,11 +567,7 @@
      console.log('转出医院变化:', hospitalData)
      // 组件已经通过 v-model 更新了 taskForm.hospitalOut
      
      // 如果选择的是"家中",自动设置科室为"其它"
      if (hospitalData.name === '家中') {
        this.taskForm.hospitalOut.department = '其它'
        this.taskForm.hospitalOut.departmentId = null
      }
      // 科室的设置由 DepartmentSelector 组件自动处理(通过 isHome 属性)
      
      // 如果转入地址已填写,自动计算距离
      if (this.taskForm.hospitalIn.address) {
@@ -597,11 +593,7 @@
      console.log('转入医院变化:', hospitalData)
      // 组件已经通过 v-model 更新了 taskForm.hospitalIn
      
      // 如果选择的是"家中",自动设置科室为"其它"
      if (hospitalData.name === '家中') {
        this.taskForm.hospitalIn.department = '其它'
        this.taskForm.hospitalIn.departmentId = null
      }
      // 科室的设置由 DepartmentSelector 组件自动处理(通过 isHome 属性)
      
      // 如果转出地址已填写,自动计算距离
      if (this.taskForm.hospitalOut.address) {
@@ -813,6 +805,18 @@
        return false
      }
      
      // 如果转入医院是“家中”,必须填写地址
      if (this.taskForm.hospitalIn.name === '家中' && !this.taskForm.hospitalIn.address) {
        this.$modal.showToast('请输入转入地址(家中)')
        return false
      }
      // 如果转出医院是“家中”,必须填写地址
      if (this.taskForm.hospitalOut.name === '家中' && !this.taskForm.hospitalOut.address) {
        this.$modal.showToast('请输入转出地址(家中)')
        return false
      }
      if (!this.taskForm.transferDistance) {
        this.$modal.showToast('请输入转运公里数')
        return false
@@ -847,6 +851,10 @@
        }
      }
      
      // 调试日志:检查转入医院地址
      console.log('构建提交数据 - 转入医院:', this.taskForm.hospitalIn.name)
      console.log('构建提交数据 - 转入医院地址:', this.taskForm.hospitalIn.address)
      const submitData = {
        taskType: 'EMERGENCY_TRANSFER',
        deptId: this.selectedOrganizationId, // 归属机构ID(部门ID)
app/pagesTask/edit-emergency.vue
@@ -998,8 +998,10 @@
        return false
      }
      
      // 转出医院地址验证:如果是“家中”必须填写地址,其他医院也必须有地址
      if (!this.taskForm.hospitalOut.address) {
        this.$modal.showToast('请选择转出医院地址')
        const msg = this.taskForm.hospitalOut.name === '家中' ? '请输入转出地址(家中)' : '请选择转出医院地址'
        this.$modal.showToast(msg)
        return false
      }
      
@@ -1013,8 +1015,10 @@
        return false
      }
      
      // 转入医院地址验证:如果是“家中”必须填写地址,其他医院也必须有地址
      if (!this.taskForm.hospitalIn.address) {
        this.$modal.showToast('请选择转入医院地址')
        const msg = this.taskForm.hospitalIn.name === '家中' ? '请输入转入地址(家中)' : '请选择转入医院地址'
        this.$modal.showToast(msg)
        return false
      }
      
app/utils/request.js
@@ -39,6 +39,10 @@
        }
        const code = res.data.code || 200
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        // 特殊处理:checkDuplicate 接口即使返回错误码也要进入 then 分支
        const isCheckDuplicateApi = config.url && config.url.includes('/task/checkDuplicate')
        if (code === 401) {
          showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
            if (res.confirm) {
@@ -49,10 +53,26 @@
          })
          reject('无效的会话,或者会话已过期,请重新登录。')
        } else if (code === 500) {
          toast(msg)
          // checkDuplicate 接口不显示 toast,让业务代码自己处理
          if (!isCheckDuplicateApi) {
            toast(msg)
          }
          // checkDuplicate 接口返回完整响应,不 reject
          if (isCheckDuplicateApi) {
            resolve(res.data)
            return
          }
          reject('500')
        } else if (code !== 200) {
          toast(msg)
          // checkDuplicate 接口不显示 toast,让业务代码自己处理
          if (!isCheckDuplicateApi) {
            toast(msg)
          }
          // checkDuplicate 接口返回完整响应,不 reject
          if (isCheckDuplicateApi) {
            resolve(res.data)
            return
          }
          reject(code)
        }
        resolve(res.data)
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
@@ -1304,15 +1304,15 @@
            if (count == null) {
                count = 10;
            }
            // 构建天地图普通搜索API URL
            //{"keyWord":"广州天河棠下","level":12,"mapBound":"116.02524,39.83833,116.65592,39.99185","queryType":1,"start":0,"count":10}
            // 构建天地图普通搜索API URL http://api.tianditu.gov.cn/v2/search
            String url = "http://api.tianditu.gov.cn/v2/search";
            StringBuilder paramsBuilder = new StringBuilder();
            paramsBuilder.append("postStr={\"keyWord\":\"").append(keyWord).append("\"");
            // 硬编码中国地图范围
            paramsBuilder.append(",\"mapBound\":\"").append("73.66,3.86,135.05,53.55").append("\"");
            // 默认级别为18
            paramsBuilder.append(",\"level\":\"").append("18").append("\"");
            paramsBuilder.append(",\"level\":\"").append("12").append("\"");
            // 默认查询类型为普通搜索
            paramsBuilder.append(",\"queryType\":\"").append("1").append("\"");
            // 默认起始位置为0
@@ -1320,12 +1320,12 @@
            paramsBuilder.append(",\"count\":\"").append(count).append("\"");
            
            // 添加可选参数
            if (region != null && !region.trim().isEmpty()) {
                paramsBuilder.append(",\"specify\":\"").append(region).append("\"");
            }
            if (city != null && !city.trim().isEmpty()) {
                paramsBuilder.append(",\"dataTypes\":\"").append(city).append("\"");
            }
//            if (region != null && !region.trim().isEmpty()) {
//                paramsBuilder.append(",\"specify\":\"").append(region).append("\"");
//            }
//            if (city != null && !city.trim().isEmpty()) {
//                paramsBuilder.append(",\"dataTypes\":\"").append(city).append("\"");
//            }
            
            paramsBuilder.append("}");
            paramsBuilder.append("&type=query");
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
@@ -504,11 +504,20 @@
                }
            }
            createTaskVo.setPatient(patientInfo);
            //1000公里,提取数字
            //1000公里,提取数字(支持小数)
            String ServiceOrdTraDistance=MapValueUtils.getStringValue(order, "ServiceOrdTraDistance");
            if(ServiceOrdTraDistance!=null){
                ServiceOrdTraDistance=ServiceOrdTraDistance.replaceAll("[^0-9]", "");
                createTaskVo.setTransferDistance(new BigDecimal(ServiceOrdTraDistance));
                // 保留数字和小数点,移除其他字符
                ServiceOrdTraDistance=ServiceOrdTraDistance.replaceAll("[^0-9.]", "");
                // 处理多个小数点的情况,只保留第一个
                int firstDotIndex = ServiceOrdTraDistance.indexOf('.');
                if (firstDotIndex != -1) {
                    ServiceOrdTraDistance = ServiceOrdTraDistance.substring(0, firstDotIndex + 1)
                        + ServiceOrdTraDistance.substring(firstDotIndex + 1).replace(".", "");
                }
                if (!ServiceOrdTraDistance.isEmpty() && !ServiceOrdTraDistance.equals(".")) {
                    createTaskVo.setTransferDistance(new BigDecimal(ServiceOrdTraDistance));
                }
            }
            
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/QyWechatAccessTokenServiceImpl.java
@@ -152,7 +152,7 @@
            // 检查服务是否启用
            if (!isEnabled()) {
                log.info("企业微信服务已禁用,无法获取小程序AccessToken");
                log.error("企业微信服务已禁用,无法获取小程序AccessToken");
                return null;
            }
@@ -251,7 +251,7 @@
            String enabled = configService.selectConfigByKey("qy_wechat.enable");
            return !"false".equals(enabled); // 默认启用
        } catch (Exception e) {
            log.warn("获取企业微信服务启用状态失败,使用默认值(true)", e);
            log.error("获取企业微信服务启用状态失败,使用默认值(true)", e);
            return true;
        }
    }
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskDispatchSyncUtilService.java
@@ -15,6 +15,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@@ -322,9 +323,10 @@
            // 获取任务的执行人员信息列表(包含角色类型) //TODO 如果有两个司机就要 设置 Entourage_1和Entourage_2
            //两个护士就要设置 Entourage_4和Entourage_6
            //两个医生要设置 Entourage_3和Entourage_5
            List<TaskCreateVO.AssigneeInfo> assignees = getTaskAssignees(task.getTaskId());
            if (assignees == null || assignees.isEmpty()) {
            List<TaskCreateVO.AssigneeInfo> assignees = getTaskAssignees(task.getTaskId());
            log.info("任务的执行人员:{}",assignees.stream().map(TaskCreateVO.AssigneeInfo::getUserName).collect(Collectors.joining(",")));
            if (assignees.isEmpty()) {
                log.warn("任务无执行人员,任务ID: {}", task.getTaskId());
                // 设置默认空值
                params.put("EntourageLeadID", "");
@@ -342,13 +344,16 @@
            String driverOaId = "";      // 司机的OA_UserID
            String doctorOaId = "";      // 医生的OA_UserID
            String nurseOaId = "";       // 护士的OA_UserID
            String driverOaId2="";
            String nurseOaId2="";
            String doctorOaId2="";
            // 遍历执行人员,根据角色类型分配到对应的Entourage参数
            for (int i = 0; i < assignees.size(); i++) {
                TaskCreateVO.AssigneeInfo assignee = assignees.get(i);
                Long userId = assignee.getUserId();
                String userType = assignee.getUserType(); // 直接使用前端传递的角色类型
                log.info("人员同步,用户ID:{},类型:{}",userId,userType);
                if (userId == null) {
                    continue;
                }
@@ -361,11 +366,15 @@
                }
                String oaUserId = user.getOaUserId().toString();
                log.info("人员同步 22222,用户ID:{},类型:{}",userId,userType);
                // 根据用户类型分配到对应的Entourage参数
                if ("driver".equals(userType)) {
                    if (driverOaId.isEmpty()) {
                        driverOaId = oaUserId;
                        if(driverOaId.isEmpty()){
                            driverOaId = oaUserId;
                        }
                        if(driverOaId2.isEmpty()){
                            driverOaId2 = oaUserId;
                        }
                        if(params.get("Entourage_1")==null) {
                            params.put("Entourage_1", oaUserId);
                        }else{
@@ -375,10 +384,14 @@
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "1"; // 司机对应Entourage_1
                        }
                    }
                } else if ("doctor".equals(userType)) {
                    if (doctorOaId.isEmpty()) {
                        doctorOaId = oaUserId;
                    }
                    if(doctorOaId2.isEmpty()){
                        doctorOaId2 = oaUserId;
                    }
                        if(params.get("Entourage_3")==null) {
                            params.put("Entourage_3", oaUserId);
                        }else{
@@ -388,10 +401,14 @@
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "3"; // 医生对应Entourage_3
                        }
                    }
                } else if ("nurse".equals(userType)) {
                    if (nurseOaId.isEmpty()) {
                        nurseOaId = oaUserId;
                    }
                    if(nurseOaId2.isEmpty()){
                        nurseOaId2 = oaUserId;
                    }
                        if(params.get("Entourage_4")==null) {
                            params.put("Entourage_4", oaUserId);
                        }else{
@@ -401,7 +418,7 @@
                        if (i == 0 && leadEntourageId.isEmpty()) {
                            leadEntourageId = "4"; // 护士对应Entourage_4
                        }
                    }
                }
            }
@@ -410,9 +427,9 @@
//            params.put("Entourage_1", driverOaId);  // 司机
//            params.put("Entourage_3", doctorOaId);  // 医生
//            params.put("Entourage_4", nurseOaId);   // 护士
//            log.info("任务执行人员同步成功,任务ID: {}, 领队ID: {}, 司机: {}, 医生: {}, 护士: {}",
//                task.getTaskId(), leadEntourageId, driverOaId, doctorOaId, nurseOaId);
            log.info("执行人员:{}", params);
            log.info("任务执行人员同步成功,任务ID: {}, 领队ID: {}, 司机: {}, 医生: {}, 护士: {}",
                task.getTaskId(), leadEntourageId, driverOaId, doctorOaId, nurseOaId);
        } catch (Exception e) {
            log.error("同步任务执行人员异常,任务ID: {}", task.getTaskId(), e);
sql/qy_wechat_config.sql
@@ -6,14 +6,16 @@
    'qy_wechat.enable',
    'qy_wechat.corp_id',
    'qy_wechat.corp_secret',
    'qy_wechat.agent_id'
    'qy_wechat.agent_id',
    'qy_wechat.miniprogram_secret'
);
-- 插入企业微信配置项
INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark) VALUES
('企业微信服务启用状态', 'qy_wechat.enable', 'false', 'Y', 'admin', SYSDATE(), '', NULL, '企业微信服务是否启用,true-启用,false-禁用'),
('企业微信服务启用状态', 'qy_wechat.enable', 'true', 'Y', 'admin', SYSDATE(), '', NULL, '企业微信服务是否启用,true-启用,false-禁用'),
('企业微信CorpID', 'qy_wechat.corp_id', 'wx248505bfbab6d0c1', 'N', 'admin', SYSDATE(), '', NULL, '企业微信企业ID'),
('企业微信CorpSecret', 'qy_wechat.corp_secret', '2MCilqWYC0FWjOQ894sbb-s7Lb5sVH4HHuJgOsd9l1k', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用密钥'),
('企业微信AgentId', 'qy_wechat.agent_id', '21', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用AgentId');
('企业微信AgentId', 'qy_wechat.agent_id', '21', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用AgentId'),
('企业微信小程序Secret', 'qy_wechat.miniprogram_secret', 'YOUR_MINIPROGRAM_SECRET_HERE', 'N', 'admin', SYSDATE(), '', NULL, '企业微信小程序密钥,用于小程序登录');
COMMIT;