vue3: bingmap using typescript

news2025/6/8 23:41:19

项目结构:

<template>
    <div class="bing-map-market">
      <!-- 加载遮罩层 -->
      <div class="loading-overlay" v-show="isLoading || errorMessage">
        <div class="spinner-container">
          <div class="spinner-border text-primary" role="status"></div>
          <p>{{ isLoading ? '加载地图中...' : errorMessage }}</p>
        </div>
      </div>
    
      <!-- 调试信息 -->
      <div class="debug-info" v-show="debugMode">
        <p>isLoading: {{ isLoading }}</p>
        <p>mapLoaded: {{ mapLoaded }}</p>
        <p>mapSize: {{ mapSize.width }} x {{ mapSize.height }}</p>
        <p>error: {{ errorMessage }}</p>
      </div>
    
      <div class="container">        
        <div class="stats">
          <div class="stat-card">
            <h3><i class="fa fa-map-marker text-primary"></i> 总位置数</h3>
            <p class="stat-value">{{ locations.length }}</p>
          </div>
          <div class="stat-card">
            <h3><i class="fa fa-users text-success"></i> 覆盖人群</h3>
            <p class="stat-value">1,250,000+</p>
          </div>
          <div class="stat-card">
            <h3><i class="fa fa-line-chart text-warning"></i> 转化率</h3>
            <p class="stat-value">8.2%</p>
          </div>
          <div class="stat-card">
            <h3><i class="fa fa-calendar text-info"></i> 更新日期</h3>
            <p class="stat-value">2025-06-01</p>
          </div>
        </div>
          
        <!-- 使用固定高度容器,防止尺寸变化 -->
        <div ref="mapContainer" class="map-container"></div>
          
        <div class="chart-container">
          <h3>区域表现分析</h3>
          <canvas id="performanceChart" height="100"></canvas>
        </div>
          
        <div class="location-list">
          <h3>重点关注位置</h3>
          <div v-if="!locations.length" class="text-center text-muted py-5">
            <i class="fa fa-spinner fa-spin fa-3x"></i>
            <p>加载位置数据中...</p>
          </div>
          <div
            v-for="location in locations"
            :key="location.name"
            class="location-item"
            @click="focusOnLocation(location)"
          >
            <h4><i :class="getLocationIconClass(location)"></i> {{ location.name }}</h4>
            <p>{{ location.address || '未提供地址' }}</p>
            <div class="location-stats">
              <span :class="getTrafficBadgeClass(location.traffic)">人流量: {{ location.traffic }}</span>
              <span :class="getConversionBadgeClass(location.conversionRate)">转化率: {{ location.conversionRate }}%</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </template>
    
  <script lang="ts" setup>
  import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue';
  import locationsData from '@/data/city.json';
    
  // 类型定义
  interface Location {
    lat: number;
    lng: number;
    name: string;
    category: 'office' | 'store';
    traffic: '极低' | '低' | '中' | '高' | '极高';
    conversionRate: string;
    address?: string;
    population?: string;
    hours?: string;
    phone?: string;
  }
    
  // 状态管理
  const isLoading = ref(true);
  const errorMessage = ref('');
  const locations = ref<Location[]>([]);
  const map = ref<any>(null);
  const infoBox = ref<any>(null);
  const mapContainer = ref<HTMLElement | null>(null);
  const mapLoaded = ref(false);
  const mapInitialized = ref(false);
  const mapSize = ref({ width: 0, height: 0 });
  const debugMode = ref(true);
  const resizeObserver = ref<ResizeObserver | null>(null);
  const mapResizeHandler = ref<() => void | null>(null);
    
  // 全局API加载Promise
  let bingMapsApiPromise: Promise<void> | null = null;
    
  // 加载Bing Maps API
  const loadBingMapsApi = () => {
    if (bingMapsApiPromise) {
      return bingMapsApiPromise;
    }
      
    bingMapsApiPromise = new Promise<void>((resolve, reject) => {
      console.log('开始加载 Bing Maps API...');
        
      const script = document.createElement('script');
      script.src = 'https://www.bing.com/api/maps/mapcontrol?callback=bingMapsCallback&mkt=zh-cn';
      script.async = true;
      script.defer = true;
        
      window.bingMapsCallback = () => {
        console.log('Bing Maps API 加载完成');
          
        if (!window.Microsoft || !Microsoft.Maps) {
          reject(new Error('Bing Maps API 加载但未正确初始化'));
          return;
        }
          
        resolve();
      };
        
      script.onerror = () => reject(new Error('Bing Maps API 加载失败'));
      document.head.appendChild(script);
        
      // 设置超时
      setTimeout(() => {
        if (!window.Microsoft || !Microsoft.Maps) {
          reject(new Error('Bing Maps API 加载超时'));
        }
      }, 10000);
    });
      
    return bingMapsApiPromise;
  };
    
  // 初始化地图
  const initializeMap = async () => {
    try {
      if (!mapContainer.value) {
        throw new Error('地图容器不存在');
      }
        
      // 确保API已加载
      await loadBingMapsApi();
        
      // 创建地图实例
      map.value = new Microsoft.Maps.Map(mapContainer.value, {
        credentials: '你的KYE',
        center: new Microsoft.Maps.Location(35.8617, 104.1954), // 中国中心点
        zoom: 4,
        culture: 'zh-CN',
        region: 'cn',
        mapTypeId: Microsoft.Maps.MapTypeId.road,
        showMapTypeSelector: true,
        enableSearchLogo: false,
        showBreadcrumb: false,
        animate: false, // 禁用初始动画
        // 防止地图自动调整视图
        suppressInfoWindows: true,
        disableBirdseye: true,
        showScalebar: false
      });
        
      mapInitialized.value = true;
      console.log('地图实例已创建');
        
      // 记录地图容器尺寸
      updateMapSize();
        
      // 添加地图加载完成事件
      await new Promise((resolve) => {
        if (!map.value) {
          resolve(null);
          return;
        }
          
        // 快速检测
        if (map.value.getRootElement()) {
          console.log('地图已加载(快速检测)');
          mapLoaded.value = true;
          resolve(null);
          return;
        }
          
        // 事件监听
        Microsoft.Maps.Events.addHandler(map.value, 'load', () => {
          console.log('地图加载完成(事件触发)');
          mapLoaded.value = true;
          resolve(null);
        });
          
        // 超时处理
        setTimeout(() => {
          console.log('地图加载超时,使用备用方案');
          mapLoaded.value = true;
          resolve(null);
        }, 5000);
      });
        
      // 添加位置点并调整视野
      addLocationsToMap();
        
      // 初始化图表
      initializeChart();
        
      // 添加容器尺寸变化监听
      setupResizeObserver();
        
      // 隐藏加载状态
      isLoading.value = false;
    } catch (error: any) {
      console.error('初始化地图时出错:', error);
      errorMessage.value = error.message || '地图初始化失败';
      isLoading.value = false;
    }
  };
    
  // 添加位置到地图
  const addLocationsToMap = () => {
    if (!map.value || !locations.value.length) {
      console.warn('地图未初始化或位置数据为空');
      return;
    }
      
    try {
      const layer = new Microsoft.Maps.Layer();
      if (!layer || typeof layer.add !== 'function') {
        throw new Error('无法创建地图图层');
      }
        
      map.value.layers.insert(layer);
        
      locations.value.forEach((location) => {
        try {
          const pin = new Microsoft.Maps.Pushpin(
            new Microsoft.Maps.Location(location.lat, location.lng),
            {
              title: location.name,
              subTitle: location.category === "office" ? "办公地点" : "零售门店",
              //color: location.category === "office" ? "#0066cc" : "#cc0000", //颜色标记
              icon: location.category === "office" ? '3.png':'21.png', //自定义图片
              text: location.category === "office" ? "公" : "店",
              textOffset: new Microsoft.Maps.Point(0, 5),
              anchor: new Microsoft.Maps.Point(12, 39),
              enableClickedStyle: true
            }
          );
            
          if (!pin) {
            console.error('无法创建标记:', location.name);
            return;
          }
            
          (pin as any).locationData = location;
            
          if (Microsoft.Maps.Events && typeof Microsoft.Maps.Events.addHandler === 'function') {
            Microsoft.Maps.Events.addHandler(pin, 'click', (e: any) => {
              const locationData = (e.target as any).locationData;
              if (locationData) {
                showInfoWindow(locationData);
              }
            });
          }
            
          layer.add(pin);
            
        } catch (error) {
          console.error(`添加位置 ${location.name} 时出错:`, error);
        }
      });
        
      console.log(`成功添加 ${locations.value.length} 个标记`);
        
      // 延迟调整视野,避免闪烁
      setTimeout(() => {
        adjustMapView();
      }, 1000);
    } catch (error) {
      console.error('添加位置到地图时出错:', error);
      errorMessage.value = '地图标记加载失败';
    }
  };
    
  // 调整地图视野
  const adjustMapView = () => {
    if (!map.value || !locations.value.length) return;
      
    try {
      const locationsArray = locations.value.map(loc =>
        new Microsoft.Maps.Location(loc.lat, loc.lng)
      );
        
      const minLat = Math.min(...locationsArray.map(loc => loc.latitude));
      const maxLat = Math.max(...locationsArray.map(loc => loc.latitude));
      const minLng = Math.min(...locationsArray.map(loc => loc.longitude));
      const maxLng = Math.max(...locationsArray.map(loc => loc.longitude));
        
      const latRange = maxLat - minLat;
      const lngRange = maxLng - minLng;
      const paddedMinLat = Math.max(minLat - latRange * 0.2, -85);
      const paddedMaxLat = Math.min(maxLat + latRange * 0.2, 85);
      const paddedMinLng = minLng - lngRange * 0.2;
      const paddedMaxLng = maxLng + lngRange * 0.2;
        
      const bounds = Microsoft.Maps.LocationRect.fromEdges(
        paddedMaxLat, paddedMaxLng, paddedMinLat, paddedMinLng
      );
        
      // 仅在必要时调整视图
      if (map.value && bounds) {
        // 保存当前中心点和缩放级别
        const currentView = map.value.getView();
          
        // 检查新边界是否明显不同
        const newCenter = bounds.getCenter();
        const centerDistance = Math.sqrt(
          Math.pow(currentView.center.latitude - newCenter.latitude, 2) +
          Math.pow(currentView.center.longitude - newCenter.longitude, 2)
        );
          
        // 如果中心点变化超过阈值或缩放级别变化超过1级,则调整视图
        if (centerDistance > 0.1 || Math.abs(currentView.zoom - bounds.getZoomLevel()) > 1) {
          map.value.setView({
            bounds,
            animate: true,
            duration: 1000
          });
        }
      }
    } catch (error) {
      console.error('调整地图视野时出错:', error);
    }
  };
    
  // 聚焦到特定位置
  const focusOnLocation = (location: Location) => {
    if (!map.value) return;
      
    map.value.setView({
      center: new Microsoft.Maps.Location(location.lat, location.lng),
      zoom: 12,
      animate: true
    });
      
    showInfoWindow(location);
  };
    
  // 显示信息窗口
  const showInfoWindow = (location: Location) => {
    if (!map.value) return;
      
    try {
      if (infoBox.value) {
        map.value.entities.remove(infoBox.value);
      }
        
      infoBox.value = new Microsoft.Maps.Infobox(
        new Microsoft.Maps.Location(location.lat, location.lng),
        {
          title: location.name,
          description: `
            <div class="custom-infobox">
              <div class="infobox-header">${location.name}</div>
              <div class="infobox-content">
                <p><strong>类型:</strong> ${location.category === "office" ? "办公地点" : "零售门店"}</p>
                <p><strong>人流量:</strong> <span class="${getTrafficBadgeClass(location.traffic)}">${location.traffic}</span></p>
                <p><strong>转化率:</strong> ${location.conversionRate}%</p>
                <p><strong>地址:</strong> ${location.address || '未提供'}</p>
                <p><strong>周边人口:</strong> ${location.population || '未提供'}</p>
              </div>
              <div class="infobox-footer">
                <button class="btn btn-primary btn-sm">查看详情</button>
              </div>
            </div>
          `,
          showCloseButton: true,
          maxWidth: 350,
          offset: new Microsoft.Maps.Point(0, 20)
        }
      );
        
      map.value.entities.push(infoBox.value);
    } catch (error) {
      console.error('显示信息窗口时出错:', error);
    }
  };
    
  // 更新地图尺寸
  const updateMapSize = () => {
    if (mapContainer.value) {
      mapSize.value = {
        width: mapContainer.value.offsetWidth,
        height: mapContainer.value.offsetHeight
      };
      console.log('地图容器尺寸更新:', mapSize.value);
    }
  };
    
  // 设置尺寸变化监听
  const setupResizeObserver = () => {
    if (!mapContainer.value || typeof ResizeObserver === 'undefined') return;
      
    // 移除现有监听器
    if (resizeObserver.value) {
      resizeObserver.value.disconnect();
    }
      
    // 创建新的尺寸监听器
    resizeObserver.value = new ResizeObserver((entries) => {
      for (const entry of entries) {
        if (entry.target === mapContainer.value) {
          updateMapSize();
            
          // 防止地图在尺寸变化时变黑
          if (map.value) {
            // 延迟调整,避免频繁触发
            if (mapResizeHandler.value) clearTimeout(mapResizeHandler.value);
            mapResizeHandler.value = setTimeout(() => {
              map.value.setView({ animate: false }); // 强制地图重绘
            }, 300);
          }
        }
      }
    });
      
    resizeObserver.value.observe(mapContainer.value);
  };
    
  // 初始化图表
  const initializeChart = () => {
    try {
      const ctx = document.getElementById('performanceChart') as HTMLCanvasElement;
      if (!ctx) return;
        
      const cities = locations.value.slice(0, 10).map(loc => loc.name);
      const trafficValues = locations.value.slice(0, 10).map(loc => {
        const trafficMap = { '极低': 1, '低': 2, '中': 3, '高': 4, '极高': 5 };
        return trafficMap[loc.traffic] || 3;
      });
      const conversionRates = locations.value.slice(0, 10).map(loc => parseFloat(loc.conversionRate));
        
      new Chart(ctx, {
        type: 'bar',
        data: {
          labels: cities,
          datasets: [
            {
              label: '人流量 (相对值)',
              data: trafficValues,
              backgroundColor: 'rgba(54, 162, 235, 0.5)',
              borderColor: 'rgba(54, 162, 235, 1)',
              borderWidth: 1
            },
            {
              label: '转化率 (%)',
              data: conversionRates,
              backgroundColor: 'rgba(75, 192, 192, 0.5)',
              borderColor: 'rgba(75, 192, 192, 1)',
              borderWidth: 1,
              type: 'line',
              yAxisID: 'y1'
            }
          ]
        },
        options: {
          responsive: true,
          scales: {
            y: {
              beginAtZero: true,
              title: { display: true, text: '人流量' },
              ticks: { callback: (value) => ['极低', '低', '中', '高', '极高'][value - 1] || value }
            },
            y1: {
              beginAtZero: true,
              position: 'right',
              title: { display: true, text: '转化率 (%)' },
              grid: { drawOnChartArea: false }
            }
          }
        }
      });
    } catch (error) {
      console.error('初始化图表时出错:', error);
    }
  };
    
  // 工具方法
  const getTrafficBadgeClass = (traffic: string) => {
    const classes = {
      '极低': 'badge bg-success',
      '低': 'badge bg-info',
      '中': 'badge bg-primary',
      '高': 'badge bg-warning',
      '极高': 'badge bg-danger'
    };
    return classes[traffic] || 'badge bg-secondary';
  };
    
  const getConversionBadgeClass = (conversionRate: string) => {
    const rate = parseFloat(conversionRate);
    return rate >= 8 ? 'badge bg-success' :
           rate >= 6 ? 'badge bg-warning' : 'badge bg-danger';
  };
    
  const getLocationIconClass = (location: Location) => {
    return location.category === 'office' ? 'fa fa-building' : 'fa fa-shopping-bag';
  };
    
  // 生命周期钩子
  onMounted(() => {
    console.log('组件已挂载,加载位置数据...');
    locations.value = locationsData;
    initializeMap();
  });
    
  onUnmounted(() => {
    console.log('组件卸载,清理资源...');
      
    // 清理地图资源
    if (map.value) {
      map.value.dispose();
      map.value = null;
    }
      
    if (infoBox.value) {
      infoBox.value = null;
    }
      
    // 移除尺寸监听器
    if (resizeObserver.value) {
      resizeObserver.value.disconnect();
      resizeObserver.value = null;
    }
      
    // 清除定时器
    if (mapResizeHandler.value) {
      clearTimeout(mapResizeHandler.value);
      mapResizeHandler.value = null;
    }
  });
    
  // 监听地图容器尺寸变化
  watch(mapSize, (newSize, oldSize) => {
    if (newSize.width !== oldSize.width || newSize.height !== oldSize.height) {
      console.log('地图尺寸变化,重绘地图...');
      if (map.value) {
        map.value.setView({ animate: false });
      }
    }
  });
  </script>
    
  <style scoped>
  body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    margin: 0;
    padding: 0;
  }
    
  .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
  }
    
  .stats {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    margin-bottom: 20px;
  }
    
  .stat-card {
    flex: 1 1 200px;
    background: #ffffff;
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    transition: transform 0.3s ease;
  }
    
  .stat-card:hover {
    transform: translateY(-5px);
  }
    
  .map-container {
    /* 使用固定高度,防止尺寸变化导致黑屏 */
    height: 600px;
    width: 100%;
    background-color: #f8f9fa; /* 防止初始化黑屏 */
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    margin-bottom: 20px;
    overflow: hidden;
    /* 防止父容器尺寸变化影响地图 */
    min-height: 600px;
  }
    
  .chart-container {
    background: #ffffff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    margin-bottom: 20px;
  }
    
  .location-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 15px;
  }
    
  .location-item {
    background: #ffffff;
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    cursor: pointer;
    transition: all 0.3s ease;
  }
    
  .location-item:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    transform: translateY(-3px);
  }
    
  .location-stats {
    display: flex;
    gap: 10px;
    margin-top: 10px;
  }
    
  .badge {
    display: inline-block;
    padding: 0.35em 0.65em;
    font-size: 0.75em;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    text-align: center;
    white-space: nowrap;
    vertical-align: baseline;
    border-radius: 0.25rem;
  }
    
  .loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(255, 255, 255, 0.9);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
  }
    
  .spinner-container {
    text-align: center;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  }
    
  .spinner-border {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    vertical-align: -0.125em;
    border: 0.25em solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spinner-border 0.75s linear infinite;
  }
    
  @keyframes spinner-border {
    to {
      transform: rotate(360deg);
    }
  }
    
  .debug-info {
    position: fixed;
    bottom: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    padding: 10px;
    font-size: 12px;
    z-index: 1000;
    max-width: 300px;
  }
    
  .custom-infobox {
    font-family: Arial, sans-serif;
    line-height: 1.5;
  }
    
  .infobox-header {
    background-color: #0078d4;
    color: white;
    padding: 8px 15px;
    font-size: 16px;
    font-weight: bold;
    border-radius: 4px 4px 0 0;
  }
    
  .infobox-content {
    padding: 10px 15px;
  }
    
  .infobox-footer {
    padding: 10px 15px;
    border-top: 1px solid #eee;
    text-align: right;
  }
    
  .btn {
    display: inline-block;
    padding: 6px 12px;
    margin-bottom: 0;
    font-size: 14px;
    font-weight: 400;
    line-height: 1.42857143;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    border: 1px solid transparent;
    border-radius: 4px;
  }
    
  .btn-primary {
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
  }
  </style>

输出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2404709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超大规模芯片验证:基于AMD VP1902的S8-100原型验证系统实测性能翻倍

引言&#xff1a; 随着AI、HPC及超大规模芯片设计需求呈指数级增长原型验证平台已成为芯片设计流程中验证复杂架构、缩短迭代周期的核心工具。然而&#xff0c;传统原型验证系统受限于单芯片容量&#xff08;通常<5000万门&#xff09;、多芯片分割效率及系统级联能力&#…

【工作记录】接口功能测试总结

如何对1个接口进行接口测试 一、单接口功能测试 1、接口文档信息 理解接口文档的内容&#xff1a; 请求URL: https://[ip]:[port]/xxxserviceValidation 请求方法: POST 请求参数: serviceCode(必填), servicePsw(必填) 响应参数: status, token 2、编写测试用例 2.1 正…

Dubbo Logback 远程调用携带traceid

背景 A项目有调用B项目的服务&#xff0c;A项目使用 logback 且有 MDC 方式做 traceid&#xff0c;调用B项目的时候&#xff0c;traceid 没传递过期&#xff0c;导致有时候不好排查问题和链路追踪 准备工作 因为使用的是 alibaba 的 dubbo 所以需要加入单独的包 <depend…

NLP学习路线图(二十):FastText

在自然语言处理(NLP)领域,词向量(Word Embedding)是基石般的存在。它将离散的符号——词语——转化为连续的、富含语义信息的向量表示,使得计算机能够“理解”语言。而在众多词向量模型中,FastText 凭借其独特的设计理念和卓越性能,尤其是在处理形态丰富的语言和罕见词…

力扣面试150题--除法求值

Day 62 题目描述 做法 此题本质是一个图论问题&#xff0c;对于两个字母相除是否存在值&#xff0c;其实就是判断&#xff0c;从一个字母能否通过其他字母到达&#xff0c;做法如下&#xff1a; 遍历所有等式&#xff0c;为每个变量分配唯一的整数索引。初始化一个二维数组 …

美业破局:AI智能体如何用数据重塑战略决策(5/6)

摘要&#xff1a;文章深入剖析美业现状与挑战&#xff0c;指出其市场规模庞大但竞争激烈&#xff0c;面临获客难、成本高、服务标准化缺失等问题。随后阐述 AI 智能体与数据驱动决策的概念&#xff0c;强调其在美业管理中的重要性。接着详细说明 AI 智能体在美业数据收集、整理…

生成模型+两种机器学习范式

生成模型&#xff1a;从数据分布到样本创造 生成模型&#xff08;Generative Model&#xff09; 是机器学习中一类能够学习数据整体概率分布&#xff0c;并生成新样本的模型。其核心目标是建模输入数据 x 和标签 y 的联合概率分布 P(x,y)&#xff0c;即回答 “数据是如何产生的…

【学习笔记】Python金融基础

Python金融入门 1. 加载数据与可视化1.1. 加载数据1.2. 折线图1.3. 重采样1.4. K线图 / 蜡烛图1.5. 挑战1 2. 计算2.1. 收益 / 回报2.2. 绘制收益图2.3. 累积收益2.4. 波动率2.5. 挑战2 3. 滚动窗口3.1. 创建移动平均线3.2. 绘制移动平均线3.3 Challenge 4. 技术分析4.1. OBV4.…

A Execllent Software Project Review and Solutions

The Phoenix Projec: how do we produce software? how many steps? how many people? how much money? you will get it. i am a pretty judge of people…a prank

windows命令行面板升级Git版本

Date: 2025-06-05 11:41:56 author: lijianzhan Git 是一个 ‌分布式版本控制系统‌ (DVCS)&#xff0c;由 Linux 之父 Linus Torvalds 于 2005 年开发&#xff0c;用于管理 Linux 内核开发。它彻底改变了代码协作和版本管理的方式&#xff0c;现已成为软件开发的事实标准工具&…

大故障,阿里云核心域名疑似被劫持

2025年6月5日凌晨&#xff0c;阿里云多个服务突发异常&#xff0c;罪魁祸首居然是它自家的“核心域名”——aliyuncs.com。包括对象存储 OSS、内容分发 CDN、镜像仓库 ACR、云解析 DNS 等服务在内&#xff0c;全部受到波及&#xff0c;用户业务连夜“塌房”。 更让人惊讶的是&…

SQLMesh实战:用虚拟数据环境和自动化测试重新定义数据工程

在数据工程领域&#xff0c;软件工程实践&#xff08;如版本控制、测试、CI/CD&#xff09;的引入已成为趋势。尽管像 dbt 这样的工具已经推动了数据建模的标准化&#xff0c;但在测试自动化、工作流管理等方面仍存在不足。 SQLMesh 应运而生&#xff0c;旨在填补这些空白&…

设计模式基础概念(行为模式):模板方法模式 (Template Method)

概述 模板方法模式是一种行为设计模式&#xff0c; 它在超类中定义了一个算法的框架&#xff0c; 允许子类在不修改结构的情况下重写算法的特定步骤。 是基于继承的代码复用的基本技术&#xff0c;模板方法模式的类结构图中&#xff0c;只有继承关系。 需要开发抽象类和具体子…

传统业务对接AI-AI编程框架-Rasa的业务应用实战(番外篇2)-- Rasa 训练数据文件的清理

经过我的【传统业务对接AI-AI编程框架-Rasa的业务应用实战】系列 1-6 的表述 已经实现了最初的目标&#xff1a;将传统平台业务&#xff08;如发票开具、审核、计税、回款等&#xff09;与智能交互结合&#xff0c;通过用户输入提示词或语音&#xff0c;识别用户意图和实体信…

LVDS的几个关键电压概念

LVDS的几个关键电压概念 1.LVDS的直流偏置 直流偏置指的是信号的电压围绕的基准电压&#xff0c;信号的中心电压。在LVDS中&#xff0c;信号是差分的&#xff0c; 两根线之间的电压差表示数据&#xff0c;很多时候两根线的电压不是在0v开始变化的&#xff0c;而是在某个 固定的…

2023年ASOC SCI2区TOP,随机跟随蚁群优化算法RFACO,深度解析+性能实测

目录 1.摘要2.连续蚁群优化算法ACOR3.随机跟随策略4.结果展示5.参考文献6.代码获取7.算法辅导应用定制读者交流 1.摘要 连续蚁群优化是一种基于群体的启发式搜索算法&#xff08;ACOR&#xff09;&#xff0c;其灵感来源于蚁群的路径寻找行为&#xff0c;具有结构简单、控制参…

DLL动态库实现文件遍历功能(Windows编程)

源文件&#xff1a; 文件遍历功能的动态库&#xff0c;并支持用户注册回调函数处理遍历到的文件 a8f80ba 周不才/cpp_linux study - Gitee.com 知识准备 1.Windows中的数据类型 2.DLL导出/导入宏 使用__declspec(dllexport)修饰函数&#xff0c;将函数标记为导出函数存放到…

jvm 垃圾收集算法 详解

垃圾收集算法 分代收集理论 垃圾收集器的理论基础&#xff0c;它建立在两个分代假说之上&#xff1a; 弱分代假说&#xff1a;绝大多数对象都是朝生夕灭的。强分代假说&#xff1a;熬过越多次垃圾收集过程的对象就越难以消亡。 这两个分代假说共同奠定了多款常用的垃圾收集…

[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制

Linux 内核作为一个多任务操作系统&#xff0c;其进程管理子系统是核心组成部分之一。无论是用户应用的运行、驱动行为的触发&#xff0c;还是系统调度决策&#xff0c;几乎所有操作都离不开进程的创建、调度与销毁。本文将从进程的概念出发&#xff0c;深入探讨 Linux 内核中进…

Flutter:下拉框选择

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d4 b70dec92594838a8b2c130717938aa.png) 文档地址dropdown_button2 // 限价、市价 状态final List<String> orderTypes [普通委托, 市价委托];String? selectedOrderType 普通委托;changeOrderType(String …