Files
ys-app/src/pages/home/home.vue
2025-08-19 13:27:26 +08:00

532 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="con-body">
<view class="con-bg">
<!-- 头部 -->
<customHeader ref="customHeaderRef" :title="'首页'"
:leftFlag="false" :rightFlag="false"
></customHeader>
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<!-- 下拉刷新 -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
:down="downOption" @down="downCallback"
:fixed="false" class="scroll-h"
>
<!-- #ifdef APP-PLUS -->
<!-- 删除设备ID--测试用 -->
<view class="del-cache" @click="handleDelete">
<uni-icons type="minus" size="30" color="#ffffff"></uni-icons>
</view>
<!-- #endif -->
<!-- 待办内容 -->
<view class="backlog-bg">
<view class="backlog-b-item">
<view class="font-number">{{ backBlogObj.count1 }}</view>
<view class="font-title">待办</view>
</view>
<view class="backlog-b-item">
<view class="font-number">{{ backBlogObj.count2 }}</view>
<view class="font-title">待审查</view>
</view>
<view class="backlog-b-item">
<view class="font-number">{{ backBlogObj.count3 }}</view>
<view class="font-title">待巡检</view>
</view>
<view class="backlog-b-item">
<view class="font-number">{{ backBlogObj.count4 }}</view>
<view class="font-title">待发货</view>
</view>
</view>
<!-- 跑马灯滚动 -->
<view class="notice-bg">
<img :src="'static/images/icon-notice@2x.png'" class="notice-icon" />
<view class="notice-list">
<!-- :interval="4000" -->
<swiper class="swiper-con"
:vertical="true"
:autoplay="true"
:duration="500"
:circular="true"
:disable-touch="true"
:display-multiple-items="1"
>
<swiper-item v-for="(item, index) in extendedList" :key="index" >
<view class="swiper-item">
{{ item }}
</view>
</swiper-item>
</swiper>
</view>
</view>
<!-- 日程提醒 -->
<view class="white-bg mar-top" v-if="stepList.length>0">
<view class="w-b-title">日程提醒
<view class="yellow-bg">
<i :class="{iconfont:true,'icon-phoneshizhong':true}"></i>
<view class="text-black">{{ weekStr }}</view>
</view>
</view>
<view class="section-line">
<customSteps :steps="stepList" :modelValue="stepList"></customSteps>
</view>
</view>
<!-- 销售任务完成情况 -->
<view class="white-bg mar-top">
<view class="w-b-title">销售任务完成情况
<view class="yellow-bg">
<picker @change="bindPickerChange" :value="activeIndex" :range="salesList" @click="clickPicker" @cancel="bindPickerCancel">
<view class="uni-input">{{salesList[activeIndex]}}</view>
</picker>
<i :class="{iconfont:true,'icon-down':salesFlag,'icon-up':!salesFlag}" class="picker-icon"></i>
</view>
</view>
<view class="progress-bg">
<progress :percent="percentNum" stroke-width="10" activeColor="#41E1B1" backgroundColor="#F0F0F0" />
<view class="percent" :style="{left:percentNum+'%'}">
<view class="percent-num">{{ percentNum }}%</view>
<i class="iconfont icon-down"></i>
</view>
<view class="percent-con">
<view class="p-first">
<view>实际销售额</view>
<view class="font-money">{{totalSales}}</view>
</view>
<view class="p-last">
<view>目标销售额</view>
<view class="font-money">{{ targetSales }}</view>
</view>
</view>
</view>
</view>
<!-- 常用服务 -->
<view class="white-bg" v-if="commonServiceList.length>0">
<view class="w-b-title">常用服务</view>
<view class="logo-list">
<view v-for="(item,index) in commonServiceList" class="l-l-item" :key="index" @click="handleJump(item.bizUrl)">
<img :src="'static/images/business/'+item.icon+'.png'" />
<text class="font-gray">{{ item.bizName }}</text>
</view>
<!-- <view class="l-l-item" @click="handleAddCommonSercice">
<img :src="'static/images/business/icon-add.png'">
<text class="font-gray">添加</text>
</view> -->
</view>
</view>
<!-- 新闻公告 -->
<view class="white-bg">
<view class="w-b-title">新闻公告
<text>更多新闻</text>
</view>
<view class="news-list">
<view v-for="(item,index) in newsList" class="news-item" :key="index">
<view class="n-i-title">{{ item.name }}
<view class="n-i-date">{{ formatDateStr(item.date) }}</view>
</view>
<img :src="item.imgSrc" v-if="item.imgSrc" />
</view>
</view>
</view>
<!-- 底部加高度来避免tabbar遮挡 -->
<view class="bottom-height"></view>
</mescroll-uni>
</view>
</view>
</template>
<script setup>
import { ref,onMounted,computed } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue'
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import customSteps from '@/components/customSteps.vue'
import customSearch from '@/components/customSearch.vue'
import { getNavBarPaddingTop} from '@/utils/system.js'
// ,swiperList,stepData,salesTask,commonServices,newsQueryList
import { messageNotifyCount,messageFlowCount,getUserFavorite} from '@/api/home.js';
import { getWeekStr,formatTimestamp } from '@/utils/datetime.js'
import { formatMoney } from '@/utils/formatter.js'
import {showLoading,hideLoading} from '@/utils/message.js'
// #ifdef APP-PLUS
// 获取 存储手机的module
const safeSave = uni.requireNativePlugin("Tm-TmSafeSaveFileModule");
const handleDelete=()=>{
uni.showModal({
title: '提示',
content: "是否确认删除设备ID删除之后需重新绑定设备谨慎操作",
cancelText: '取消',
confirmText: '确定',
success: function (res) {
if (res.confirm) {
safeSave.delSafeFile({"key": "app_device_id"}, (res) => {
if (res.code == 1) {
uni.showModal({title: "提示",content:"删除成功"})
} else {
uni.showModal({title: "删除失败",content: res.msg})
}
})
} else if (res.cancel) {
}
}
})
}
// #endif
onLoad(async(opt) => {
uni.setStorageSync('page_cache',true);
// initLoad();
})
// 初始化调用方法
const initLoad =()=>{
try {
showLoading("加载中...");
getBackBlogCount();
getSwiperList();
getStepData();
getSalesTask();
getCommonServices();
getNewsList();
hideLoading();
} catch (error) {
hideLoading();
}
}
// 下拉刷新
const mescrollRef = ref(null);
const mescrollInit = (mescroll) => {
mescrollRef.value = mescroll;
};
const downOption = ref({
auto: true,
textInOffset: '下拉刷新',
textOutOffset: '释放更新',
textLoading: '刷新中...'
});
// 下拉刷新
const downCallback = async (mescroll) => {
try {
// setTimeout(async ()=>{
// // mescroll.resetUpScroll();
// },500);
initLoad();
} catch (error) {
mescroll.endErr();
} finally {
setTimeout(async ()=>{
mescroll.endSuccess();
},500);
}
}
// 获取导航栏高度用于内容区域padding
const navBarPaddingTop = ref(0);
onMounted(() => {
navBarPaddingTop.value = getNavBarPaddingTop()*2;
})
let backBlogObj = ref({
count1:0,
count2:0,
count3:0,
count4: 0
})
// 获取待办数据
const getBackBlogCount = async () =>{
let res = await messageNotifyCount();
let res2 = await messageFlowCount();
backBlogObj.value.count1= res.todoCount || 0//消息待阅
backBlogObj.value.count2= res2.todoCount || 0//审核待办
// tabar 增加消息数量
try {
if(backBlogObj.value.count1>0){
wx.setTabBarBadge({
index: 2, // TabBar的索引从0开始计数
text: res.todoCount+'' // 徽章的文本
});
}
} catch (error) {
console.error('设置TabBar Badge失败:', error);
}
}
// 跑马灯处理
let extendedList = ref([]);// ;
const getSwiperList = async () => {
// extendedList.value = await swiperList();
extendedList.value = ["祝贺“友晟夏季封装外壳发布会”圆满成功","祝贺“友晟科技发布会”圆满成功","祝贺“友晟夏季封装外壳发布会”圆满成功"]
}
// 日程提醒
let weekStr = ref(null) //'2025-09-19 星期三'
let stepList = ref([]);
const getStepData = async ()=>{
// let res = await stepData({});
let res={
date:new Date().getTime(),
list:[
{ id:1,desc: '2025秋季产品发布前期准备会在科研楼0317会议室召开。', title: '13:30 — 15:30',beginTime:'13:30',endTime:'15:30'},
{ id:2,desc: '生产间安全巡检。', title: '16:30 — 18:00',beginTime:'16:30',endTime:'18:00'},
]
}
weekStr.value = getWeekStr(res.date);
stepList.value = res.list;
}
// 销售任务完成情况
let salesList = ref([]);
let salesFlag = ref(true);
let activeIndex = ref(0);
const bindPickerChange = (e)=>{
// console.log('picker发送选择改变携带值为', e.detail.value)
activeIndex.value = e.detail.value;
salesFlag.value = true;
}
const bindPickerCancel= (e)=>{
salesFlag.value = true;
}
const clickPicker= (e)=>{
salesFlag.value = false;
}
let percentNum = ref(0);
let totalSales = ref(0)
let targetSales = ref(0)
const getSalesTask = async ()=>{
// let res = await salesTask({});
let res = {
salesList:['2025-3季度', '2025-2季度', '2025-1季度'],
percentNum:82,
totalSales:62075000,
targetSales:75000000
}
salesList.value = res.salesList;
percentNum.value = res.percentNum;
totalSales.value = formatMoney(res.totalSales);
targetSales.value = formatMoney(res.targetSales);
}
// 常用服务
let commonServiceList = ref([])
const getCommonServices = async ()=>{
let data = await getUserFavorite({});
commonServiceList.value = data || []
}
// 跳转
let handleJump=(url)=>{
if(url){
uni.navigateTo({ url })
}
}
// 添加常用服务
const handleAddCommonSercice = ()=>{
}
// 新闻公告
let newsList = ref([])
const getNewsList = async()=>{
// let res = await newsQueryList({});
let res = {
list:[
{id:1,date:'2025-06-29',name:'友晟亮相2025慕尼黑上海电子展',imgSrc:'https://img2.baidu.com/it/u=363858033,1221485415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1067'},
{id:2,date:'2025-06-26',name:'孜孜不倦,谱写公司发展新篇章',imgSrc:'https://img0.baidu.com/it/u=2830423559,3962669886&fm=253&app=138&f=JPEG?w=570&h=760'},
{id:3,date:'2025-03-29 08:10:00',name:'质量管理体系提升助力实现质的飞跃',imgSrc:''},
],
}
newsList.value = res.list;
}
const formatDateStr =(times)=>{
return formatTimestamp(times)
}
</script>
<style scope>
.del-cache{
position: fixed;
right:30rpx;
bottom:30%;
width:60rpx;
height: 60rpx;
line-height: 60rpx;
border-radius: 50%;
background:#579FF9;
font-size:12px;
padding:5rpx;
display: flex;
align-items: center;
justify-content: center;
}
.scroll-h{
/* #ifdef APP-PLUS */
height:calc(100vh - 78px) !important;
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 80px) !important;
/* #endif */
}
:deep(.mescroll-upwarp){
display:none
}
.search-sao{
display: flex;
padding-top:10rpx;
}
.search-sao .custom-search{
width:612rpx;
}
.search-sao :deep(.custom-search.uni-searchbar){
padding-bottom: 15rpx !important;
}
.search-sao .icon-phonesaoyisao{
margin:15rpx 30rpx 10rpx auto;
}
.backlog-bg{
background:url('@/static/images/bg-main@2x.png') no-repeat;
background-size:730rpx 205rpx;
/* width:730rpx; */
width:690rpx;
height:205rpx;
margin:0 auto;
display: flex;
padding:0 20rpx;
}
.backlog-b-item{
width:25%;
color:#579FF9;
border-right:1px solid #EAEAEA;
height:100rpx;
margin-top:40rpx;
}
.backlog-b-item .font-number{
font-size: 60rpx;
font-weight: bold;
text-align: center;
}
.backlog-b-item .font-title{
font-size:28rpx;
text-align: center;
}
.notice-bg{
background:url('@/static/images/bg-notice@2x.png') no-repeat;
background-size:750rpx 90rpx;
width:690rpx;
height: 90rpx;
margin-top:10rpx;
padding:0 30rpx;
display: flex;
align-items: center;
}
.notice-bg .notice-icon{
width:46rpx;
height:40rpx;
}
.notice-list{
width:100%;
position: relative;
height: 90rpx;
overflow: hidden;
}
.notice-list .swiper-con{
width:640rpx;
}
.notice-list .swiper-con .swiper-item {
height: 90rpx;
line-height: 90rpx;
padding: 0 20rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color:#fff;
font-size:30rpx;
}
.progress-bg{
position: relative;
width:528rpx;
margin:120rpx auto 0;
}
.progress-bg :deep(.uni-progress .uni-progress-bar){
border-radius: 5px;
}
.progress-bg :deep(.uni-progress .uni-progress-inner-bar){
border-radius: 5px 0 0 5px;
}
.progress-bg .percent{
position: absolute;
top:0;
color:#FF687A;
font-size:60rpx;
font-weight: bold;
}
.progress-bg .percent .icon-down{
position: absolute;
bottom:0rpx;
left:-20rpx;
color:#FF687A;
font-size:40rpx;
}
.progress-bg .percent .percent-num{
position: absolute;
left:-60rpx;
bottom:30rpx;
}
.progress-bg .percent-con{
display: flex;
width:528rpx;
color:#333;
font-size:28rpx;
margin:20rpx 0 10rpx;
}
.progress-bg .percent-con .p-last{
margin-left: auto;
text-align: right;
}
.progress-bg .percent-con .font-money{
font-weight: bold;
margin-top:10rpx;
}
.white-bg .logo-list{
gap:50rpx;
padding:0 20rpx;
/* margin-bottom: -50rpx; */
}
.white-bg .logo-list .l-l-item{
width:160rpx;
margin-bottom:0rpx;
}
.white-bg .logo-list .l-l-item img{
width:110rpx;
height:110rpx;
}
</style>