<template> 
 | 
  <view style="width: 100%; height: var(--status-bar-height)" /> 
 | 
  <view class="home"> 
 | 
    <!-- 当前用户 --> 
 | 
    <view class="flex items-center justify-between"> 
 | 
      <view class="text-[#0D867F] font-medium py-2 text-lg"> 
 | 
        <text>亨旺特导线缆上报系统</text> 
 | 
      </view> 
 | 
    </view> 
 | 
    <WorkerCallingCard /> 
 | 
  
 | 
    <!-- 通知公告 --> 
 | 
    <wd-notice-bar text="这是一条测试通知的数据" custom-class="space"> 
 | 
      <template #prefix> 
 | 
        <wd-icon class="prefix" name="warn-bold" size="14px"></wd-icon> 
 | 
        <text class="text-xs">通知</text> 
 | 
      </template> 
 | 
    </wd-notice-bar> 
 | 
    <!-- 快捷导航 --> 
 | 
    <wd-grid clickable :column="1" class="mt-2"> 
 | 
      <view v-for="(item, index) in navList"> 
 | 
        <wd-grid-item v-if="item.show" :key="index" use-slot link-type="navigateTo" :url="item.url"> 
 | 
          <view class="p-2"> 
 | 
            <image class="w-72rpx h-72rpx rounded-8rpx" :src="item.icon" /> 
 | 
          </view> 
 | 
          <view class="text">{{ item.title }}</view> 
 | 
        </wd-grid-item> 
 | 
      </view> 
 | 
    </wd-grid> 
 | 
    <wd-message-box /> 
 | 
    <wd-popup v-model="fileProgress.show" custom-style="width: 300px; border-radius: 32rpx;"> 
 | 
      <view class="download_box"> 
 | 
        <view class="download_box_title">下载中...</view> 
 | 
        <wd-progress :percentage="fileProgress.progress" hide-text :status="fileProgress.status" /> 
 | 
      </view> 
 | 
    </wd-popup> 
 | 
    <wd-toast /> 
 | 
    <!-- 数据统计 --> 
 | 
    <!-- <wd-grid :column="2" :gutter="2"> 
 | 
      <wd-grid-item use-slot custom-class="custom-item"> 
 | 
        <view class="flex justify-start pl-5"> 
 | 
          <view class="flex-center"> 
 | 
            <image class="w-80rpx h-80rpx rounded-8rpx" src="/static/icons/visitor.png" /> 
 | 
            <view class="ml-5 text-left"> 
 | 
              <view class="font-bold">访客数</view> 
 | 
              <view class="mt-2">{{ visitStatsData.todayUvCount }}</view> 
 | 
            </view> 
 | 
          </view> 
 | 
        </view> 
 | 
      </wd-grid-item> 
 | 
      <wd-grid-item use-slot custom-class="custom-item"> 
 | 
        <view class="flex justify-start pl-5"> 
 | 
          <view class="flex-center"> 
 | 
            <image class="w-80rpx h-80rpx rounded-8rpx" src="/static/icons/browser.png" /> 
 | 
            <view class="ml-5 text-left"> 
 | 
              <view class="font-bold">浏览量</view> 
 | 
              <view class="mt-2">{{ visitStatsData.todayPvCount }}</view> 
 | 
            </view> 
 | 
          </view> 
 | 
        </view> 
 | 
      </wd-grid-item> 
 | 
    </wd-grid> --> 
 | 
  
 | 
    <!-- <wd-card> 
 | 
      <template #title> 
 | 
        <view class="flex-between"> 
 | 
          <view>访问趋势</view> 
 | 
          <view> 
 | 
            <wd-radio-group 
 | 
              v-model="recentDaysRange" 
 | 
              shape="button" 
 | 
              inline 
 | 
              @change="handleDataRangeChange" 
 | 
            > 
 | 
              <wd-radio :value="7">近7天</wd-radio> 
 | 
              <wd-radio :value="15">近15天</wd-radio> 
 | 
            </wd-radio-group> 
 | 
          </view> 
 | 
        </view> 
 | 
      </template> 
 | 
  
 | 
      <view class="charts-box"> 
 | 
        <qiun-data-charts type="area" :chartData="chartData" :opts="chartOpts" /> 
 | 
      </view> 
 | 
    </wd-card> --> 
 | 
  </view> 
 | 
</template> 
 | 
  
 | 
<script setup lang="ts"> 
 | 
import { reactive } from "vue"; 
 | 
import { dayjs, useMessage, useToast } from "wot-design-uni"; 
 | 
import LogAPI, { VisitStatsVO } from "@/api/system/log"; 
 | 
import WorkerCallingCard from "@/components/worker-calling-card/index.vue"; 
 | 
import HomeApi from "@/api/home"; 
 | 
  
 | 
const visitStatsData = ref<VisitStatsVO>({ 
 | 
  todayUvCount: 0, 
 | 
  uvGrowthRate: 0, 
 | 
  totalUvCount: 0, 
 | 
  todayPvCount: 0, 
 | 
  pvGrowthRate: 0, 
 | 
  totalPvCount: 0, 
 | 
}); 
 | 
  
 | 
const message = useMessage(); 
 | 
const toast = useToast(); 
 | 
  
 | 
const fileProgress = reactive({ 
 | 
  show: false, 
 | 
  progress: 0, 
 | 
  status: undefined, 
 | 
}); 
 | 
  
 | 
// 图表数据 
 | 
const chartData = ref({}); 
 | 
  
 | 
const chartOpts = ref({ 
 | 
  padding: [20, 0, 20, 0], 
 | 
  xAxis: { 
 | 
    fontSize: 10, 
 | 
    rotateLabel: true, 
 | 
    rotateAngle: 30, 
 | 
  }, 
 | 
  yAxis: { 
 | 
    disabled: true, 
 | 
  }, 
 | 
  extra: { 
 | 
    area: { 
 | 
      type: "curve", 
 | 
      opacity: 0.2, 
 | 
      addLine: true, 
 | 
      width: 2, 
 | 
      gradient: true, 
 | 
      activeType: "hollow", 
 | 
    }, 
 | 
  }, 
 | 
}); 
 | 
  
 | 
// 日期范围 
 | 
const recentDaysRange = ref(7); 
 | 
  
 | 
// 快捷导航列表 
 | 
const navList = reactive([ 
 | 
  // { 
 | 
  //   icon: "/static/icons/user.png", 
 | 
  //   title: "用户管理", 
 | 
  //   url: "/pages/work/user/index", 
 | 
  //   prem: "sys:user:query", 
 | 
  // }, 
 | 
  { 
 | 
    icon: "/static/icons/user.png", 
 | 
    title: "生产管理", 
 | 
    url: "/pages/production/index", 
 | 
    show: false, 
 | 
  }, 
 | 
  // { 
 | 
  //   icon: "/static/icons/role.png", 
 | 
  //   title: "角色管理", 
 | 
  //   url: "/pages/work/role/index", 
 | 
  //   prem: "sys:role:query", 
 | 
  // }, 
 | 
  // { 
 | 
  //   icon: "/static/icons/notice.png", 
 | 
  //   title: "通知公告", 
 | 
  //   url: "/pages/work/notice/index", 
 | 
  //   prem: "sys:notice:query", 
 | 
  // }, 
 | 
  // { 
 | 
  //   icon: "/static/icons/setting.png", 
 | 
  //   title: "系统配置", 
 | 
  //   url: "/pages/work/config/index", 
 | 
  //   prem: "sys:config:query", 
 | 
  // }, 
 | 
  { 
 | 
    icon: "/static/icons/log.png", 
 | 
    title: "时效报工", 
 | 
    url: "/pages/timely/index", 
 | 
    show: false, 
 | 
  }, 
 | 
  { 
 | 
    icon: "/static/icons/routingInspection.png", 
 | 
    title: "巡检", 
 | 
    url: "/pages/routingInspection/index", 
 | 
    show: true, 
 | 
  }, 
 | 
]); 
 | 
  
 | 
// 加载访问统计数据 
 | 
const loadVisitStatsData = async () => { 
 | 
  LogAPI.getVisitStats().then((data) => { 
 | 
    visitStatsData.value = data; 
 | 
  }); 
 | 
}; 
 | 
  
 | 
// 加载访问趋势数据 
 | 
const loadVisitTrendData = () => { 
 | 
  const endDate = new Date(); 
 | 
  const startDate = new Date(endDate); 
 | 
  startDate.setDate(endDate.getDate() - recentDaysRange.value + 1); 
 | 
  
 | 
  const visitTrendQuery = { 
 | 
    startDate: dayjs(startDate).format("YYYY-MM-DD"), 
 | 
    endDate: dayjs(endDate).format("YYYY-MM-DD"), 
 | 
  }; 
 | 
  
 | 
  LogAPI.getVisitTrend(visitTrendQuery).then((data) => { 
 | 
    const res = { 
 | 
      categories: data.dates, 
 | 
      series: [ 
 | 
        { 
 | 
          name: "访客数(UV)", 
 | 
          data: data.ipList, 
 | 
        }, 
 | 
        { 
 | 
          name: "浏览量(PV)", 
 | 
          data: data.pvList, 
 | 
        }, 
 | 
      ], 
 | 
    }; 
 | 
    chartData.value = JSON.parse(JSON.stringify(res)); 
 | 
  }); 
 | 
}; 
 | 
  
 | 
//  数据范围变化 
 | 
const handleDataRangeChange = ({ value }: { value: number }) => { 
 | 
  console.log("handleDataRangeChange", value); 
 | 
  recentDaysRange.value = value; 
 | 
  loadVisitTrendData(); 
 | 
}; 
 | 
  
 | 
const init = async () => { 
 | 
  checkVersion(); 
 | 
  const { data } = await HomeApi.getIndex(); 
 | 
  if (data.deviceGroupName == "时效组") { 
 | 
    navList[1].show = true; 
 | 
  } else { 
 | 
    navList[0].show = true; 
 | 
  } 
 | 
}; 
 | 
  
 | 
/** 
 | 
 * @description 检查版本号 
 | 
 */ 
 | 
const checkVersion = async () => { 
 | 
  const systemInfo = uni.getSystemInfoSync(); 
 | 
  const { code, data } = await HomeApi.getVersion({ version: systemInfo.appVersion }); 
 | 
  if (code == 200 && data.isUpdate) { 
 | 
    message 
 | 
      .confirm({ 
 | 
        title: "发现新版本", 
 | 
        confirmButtonText: "下载", 
 | 
        cancelButtonText: "忽略", 
 | 
      }) 
 | 
      .then(() => { 
 | 
        downloadApk(data.url, data.fileSize); 
 | 
      }) 
 | 
      .catch(() => {}); 
 | 
  } 
 | 
}; 
 | 
  
 | 
/** 
 | 
 * @desc 发起下载APK 
 | 
 */ 
 | 
const downloadApk = (url: string, fileSize: number) => { 
 | 
  fileProgress.show = true; 
 | 
  let dtask: any = downloadFile(url); 
 | 
  // 下载任务开始下载 
 | 
  dtask.start(); 
 | 
  // 关于进度的获取是使用定时器不断获取已经下载的文件的大小,再对比总大小即可 
 | 
  let timer = setInterval(() => { 
 | 
    let percent: any = (dtask.downloadedSize / fileSize).toFixed(2); // fileSize文件总大小,后端返回的 
 | 
    console.log("发起下载APK", dtask.downloadedSize); 
 | 
    fileProgress.progress = Math.floor(percent * 100); // 转成整数展示 
 | 
    if (percent >= 1) { 
 | 
      // 注意百分比,及时清除定时器即可 
 | 
      clearInterval(timer); 
 | 
      fileProgress.show = false; 
 | 
    } 
 | 
  }, 18); 
 | 
}; 
 | 
  
 | 
// uniapp下载APK实例 
 | 
const downloadFile = (url: string) => { 
 | 
  return plus.downloader.createDownload(url, {}, (d, status) => { 
 | 
    console.log(d); 
 | 
    if (status == 200) { 
 | 
      fileProgress.show = true; 
 | 
      plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {}, {}, (error) => { 
 | 
        toast.error("安装失败"); 
 | 
      }); 
 | 
    } else { 
 | 
      toast.error("更新失败"); 
 | 
    } 
 | 
  }); 
 | 
}; 
 | 
  
 | 
onMounted(() => { 
 | 
  init(); 
 | 
}); 
 | 
</script> 
 | 
  
 | 
<style setup lang="scss"> 
 | 
.home { 
 | 
  padding: 10rpx 10rpx; 
 | 
  
 | 
  :deep(.custom-item) { 
 | 
    height: 80px !important; 
 | 
  } 
 | 
  
 | 
  :deep(.wd-card) { 
 | 
    margin: 10rpx 0 !important; 
 | 
  } 
 | 
} 
 | 
  
 | 
.charts-box { 
 | 
  width: 100%; 
 | 
  height: 300px; 
 | 
} 
 | 
.download_box { 
 | 
  padding: 24px; 
 | 
  .download_box_title { 
 | 
    text-align: center; 
 | 
    font-size: 16px; 
 | 
    color: #000000d9; 
 | 
    line-height: 20px; 
 | 
    font-weight: 500; 
 | 
    padding-top: 5px; 
 | 
    padding-bottom: 10px; 
 | 
  } 
 | 
} 
 | 
</style> 
 |