feat: 首页新增预警信息模块;重新设计我的页面;新增预警信息页面;

style: 优化基础样式
master
chris 3 days ago
parent c8363875d3
commit 44dd0a2f9e

@ -0,0 +1,256 @@
<script setup>
import dapengzhongmiaoguanli from '@/static/svg/dapengzhongmiaoguanli.svg'
import dixing from '@/static/svg/dixing.svg'
import nongshi from '@/static/svg/nongshi.svg'
import shuguo from '@/static/svg/shuguo.svg'
const itemDict = {
plantingArea: {
svg: 'nongshi',
icon: nongshi,
text: '种植面积(亩)',
value: 250,
color: '#4CAF50',
},
terrain: {
svg: 'dixing',
icon: dixing,
text: '地形',
value: '丘陵山地',
color: '#FF9800',
},
variety: {
svg: 'dapengzhongmiaoguanli',
icon: dapengzhongmiaoguanli,
text: '主要品种',
value: '桂味',
color: '#E91E63',
},
plantingNum: {
svg: 'shuguo',
icon: shuguo,
text: '种植荔枝(棵)',
value: 8500,
color: '#2196F3',
},
}
</script>
<template>
<!-- 果园基本信息卡片 -->
<view class="info-section">
<wd-card :shadow="false" class="basic-card">
<!-- 基本信息网格 -->
<wd-row :gutter="12">
<wd-col
v-for="(item, key) in itemDict"
:key="key"
:span="12"
>
<view class="info-item-wrapper">
<view class="info-item">
<view
class="info-icon-container" :style="{
'backgroundColor': `${item.color}15`,
'borderColor': `${item.color}30`,
'boxShadow': `0 2px 8px ${item.color}20`,
'--hover-color': item.color,
}"
>
<!-- 使用统一的方式设置图标颜色 -->
<image
:src="item.icon" mode="aspectFit" class="info-icon" :style="{
// H5使filterAPP使tintColor
filter: item.color ? `drop-shadow(0 0 0 ${item.color})` : 'none',
tintColor: item.color,
}"
/>
</view>
<view class="info-content">
<text class="info-label">{{ item.text }}</text>
<text class="info-value">{{ item.value }}</text>
</view>
</view>
</view>
</wd-col>
</wd-row>
</wd-card>
</view>
</template>
<style scoped lang="scss">
@import '../variables.scss';
//
.info-section {
margin-bottom: 24px;
}
//
.info-item-wrapper {
height: 100%;
}
//
.basic-card {
border-radius: $border-radius;
box-shadow: $box-shadow;
overflow: hidden;
background: $card-bg-glass;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
position: relative;
padding: 8px !important;
//
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, $primary-color, $primary-color-dark);
}
}
// -
.info-item {
display: flex;
align-items: center;
height: 100%;
min-height: 100px;
justify-content: flex-start;
text-align: left;
position: relative;
//
&::before {
content: '';
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
background: radial-gradient(circle, rgba(0, 198, 255, 0.1) 0%, transparent 70%);
border-radius: 50%;
opacity: 0.6;
}
// -
.info-icon-container {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
border-radius: 50%;
margin-right: 12px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
flex-shrink: 0;
border: 1px solid;
.info-item:hover & {
transform: translateY(-2px) scale(1.08);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}
//
&::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 50%);
opacity: 0;
transition: opacity 0.3s ease;
}
.info-item:hover &::after {
opacity: 1;
}
//
&::before {
content: '';
position: absolute;
inset: -2px;
border-radius: 50%;
background: linear-gradient(45deg, transparent, currentColor, transparent);
opacity: 0;
transition: opacity 0.3s ease;
z-index: -1;
}
.info-item:hover &::before {
opacity: 0.5;
animation: rotate 2s linear infinite;
}
}
//
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
// -
.info-icon {
width: 20px;
height: 20px;
transition: all 0.3s ease;
//
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
//
.info-item:hover & {
transform: scale(1.1);
//
opacity: 1;
}
}
.info-content {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
gap: 4px;
}
.info-label {
font-size: 12px;
color: $text-tertiary;
letter-spacing: 0.2px;
position: relative;
z-index: 1;
}
.info-value {
font-size: 16px;
font-weight: 600;
color: $primary-color-dark;
letter-spacing: 0.3px;
position: relative;
z-index: 1;
//
&::after {
content: '';
position: absolute;
bottom: -3px;
left: 0;
width: 30%;
height: 1px;
background: linear-gradient(90deg, $primary-color, transparent);
opacity: 0.5;
}
}
}
</style>

@ -0,0 +1,261 @@
<script setup>
import bug from '@/static/svg/bug.svg'
import jiankongyun from '@/static/svg/jiankongyun.svg'
import tianqiyujing from '@/static/svg/tianqiyujing.svg'
import turangshuishi from '@/static/svg/turangshuishi.svg'
//
const modules = [
{
id: 'pest',
title: '虫情监控',
icon: bug,
desc: '实时监测果园病虫害情况',
route: '/pages/pest/pest',
},
{
id: 'soil',
title: '土壤墒情',
icon: turangshuishi,
desc: '监测土壤湿度、养分等数据',
route: '/pages/soil/soil',
},
{
id: 'weather',
title: '气象监测',
icon: tianqiyujing,
desc: '温度、湿度、光照等数据',
route: '/pages/weather/weather',
},
{
id: 'drone',
title: '无人机巡查',
icon: jiankongyun,
desc: '无人机航拍及数据分析',
route: '/pages/drone/index',
},
]
//
function handleModuleClick(module) {
//
console.log('跳转到:', module.route)
//
uni.navigateTo({
url: module.route,
})
}
</script>
<template>
<!-- 监控模块区域 -->
<view class="monitor-section">
<!-- 模块网格 -->
<wd-row :gutter="15" class="module-row">
<wd-col
v-for="module in modules"
:key="module.id"
:span="12"
>
<view class="module-item-wrapper">
<view
class="module-card"
@tap="handleModuleClick(module)"
>
<view class="module-icon-container" :class="`module-${module.id}`">
<image :src="module.icon" mode="aspectFit" class="module-icon" />
</view>
<view class="module-info">
<text class="module-title">{{ module.title }}</text>
<text class="module-desc">{{ module.desc }}</text>
</view>
</view>
</view>
</wd-col>
</wd-row>
</view>
</template>
<style lang="scss" scoped>
@import '../variables.scss';
//
.monitor-section {
margin-bottom: 10px;
//
.module-row {
// padding: 0 15px;
}
//
.module-item-wrapper {
height: 100%;
}
// -
.module-card {
padding: 20px 15px;
margin: 7.5px 0;
background-color: $card-bg-glass;
border-radius: $border-radius;
box-shadow: $box-shadow;
height: 160px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
transition: $transition;
overflow: hidden;
position: relative;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
//
&::before {
content: '';
position: absolute;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
border-radius: $border-radius;
padding: 1px;
background: linear-gradient(135deg, rgba(0, 198, 255, 0.2), transparent 50%, rgba(0, 198, 255, 0.2));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease;
}
//
&::after {
content: '';
position: absolute;
bottom: -20px;
right: -20px;
width: 60px;
height: 60px;
background: radial-gradient(circle, rgba(0, 198, 255, 0.1) 0%, transparent 70%);
border-radius: 50%;
opacity: 0.5;
}
}
// -
.module-icon-container {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12px;
width: 64px;
height: 64px;
border-radius: 12px;
position: relative;
overflow: hidden;
transition: transform 0.3s ease;
.module-card:hover & {
transform: scale(1.05);
}
&.module-pest {
background: linear-gradient(135deg, rgba(245, 87, 108, 0.12), rgba(245, 87, 108, 0.05));
box-shadow: 0 4px 12px rgba(245, 87, 108, 0.1);
}
&.module-soil {
background: linear-gradient(135deg, rgba(82, 196, 26, 0.12), rgba(82, 196, 26, 0.05));
box-shadow: 0 4px 12px rgba(82, 196, 26, 0.1);
}
&.module-weather {
background: linear-gradient(135deg, rgba(66, 153, 225, 0.12), rgba(66, 153, 225, 0.05));
box-shadow: 0 4px 12px rgba(66, 153, 225, 0.1);
}
&.module-drone {
background: linear-gradient(135deg, rgba(255, 152, 0, 0.12), rgba(255, 152, 0, 0.05));
box-shadow: 0 4px 12px rgba(255, 152, 0, 0.1);
}
//
&::before {
content: '';
position: absolute;
top: 0;
left: -50%;
width: 20%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transform: skewX(-20deg);
animation: shine 3s infinite linear;
}
}
//
@keyframes shine {
0% {
left: -50%;
}
100% {
left: 150%;
}
}
//
.module-icon {
width: 32px;
height: 32px;
transition: filter 0.3s ease;
.module-card:hover & {
filter: brightness(1.1);
}
}
//
.module-info {
width: 100%;
position: relative;
z-index: 1;
}
.module-title {
font-size: 16px;
font-weight: 600;
color: $text-primary;
margin-bottom: 6px;
display: block;
letter-spacing: 0.2px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.module-desc {
font-size: 13px;
color: $text-tertiary;
line-height: 1.5;
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
letter-spacing: 0.1px;
//
&::after {
content: '';
position: absolute;
bottom: -4px;
left: 50%;
transform: translateX(-50%);
width: 30%;
height: 1px;
background: linear-gradient(90deg, transparent, $primary-color, transparent);
opacity: 0.3;
}
}
}
</style>

@ -0,0 +1,59 @@
<!--
* @Author: chris
* @Date: 2025-10-23 11:25:00
* @LastEditors: chris
* @LastEditTime: 2025-10-23 12:02:30
-->
<script setup lang="ts">
//
interface TitleProps {
title: {
type: string
default: '模块标题'
}
}
const props = defineProps<TitleProps>()
</script>
<template>
<view class="section-title">
<view class="title-left">
{{ props.title }}
</view>
<view class="title-right">
<slot />
</view>
</view>
</template>
<style lang="scss" scoped>
@import '../variables.scss';
.section-title {
@apply flex items-center justify-between items-center px-15px;
.title-left {
font-size: 18px;
font-weight: 600;
color: $text-primary;
display: block;
margin-bottom: 16px;
position: relative;
padding-left: 15px;
//
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: linear-gradient(180deg, $primary-color, $primary-color-dark);
border-radius: 2px;
box-shadow: 0 0 8px rgba($primary-color, 0.3);
}
}
}
</style>

@ -0,0 +1,105 @@
<!--
* @Author: chris
* @Date: 2025-10-23 09:33:22
* @LastEditors: chris
* @LastEditTime: 2025-10-23 11:20:35
-->
<script setup lang="ts">
//
interface WarningItem {
id: string
type: string
title: string
description: string
location: string
time: string
recommendedAction: string
}
// -
const warningData = ref<WarningItem[]>([
{
id: '1',
type: '荔枝蒂蛀虫',
title: '荔枝蒂蛀虫爆发预警',
description: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
location: '果园东区',
time: '2小时前',
recommendedAction: '立即使用高效低毒农药进行全园防治',
},
{
id: '2',
type: '尺蠖',
title: '尺蠖活动增加',
description: '南部区域尺蠖数量呈上升趋势,需要密切关注',
location: '果园南区',
time: '5小时前',
recommendedAction: '加强监测,准备防治措施',
},
{
id: '3',
type: '气象提醒',
title: '降雨预警',
description: '未来24小时有降雨请注意防治药物的施用时间',
location: '全园',
time: '10小时前',
recommendedAction: '合理安排农药施用时间,避开降雨',
},
{
id: '4',
type: '蚜虫',
title: '蚜虫轻度发生',
description: '西北区域发现少量蚜虫活动,当前密度较低',
location: '果园西区',
time: '1天前',
recommendedAction: '定期监测,暂不需要防治',
},
{
id: '5',
type: '红蜘蛛',
title: '红蜘蛛密度上升',
description: '部分果树枝叶发现红蜘蛛,密度呈上升趋势',
location: '果园北区',
time: '12小时前',
recommendedAction: '准备生物防治措施,控制蔓延',
},
])
//
function handleWarningClick(warning: WarningItem) {
console.log('查看预警详情:', warning)
//
uni.navigateTo({
url: `/pages/pest/detail?id=${warning.id}`,
})
}
</script>
<template>
<wd-card class="warning-card">
<view class="warning-list">
<view v-for="warning in warningData" :key="warning.id" class="warning-item">
<wd-text color="#333" :lines="2" :text="warning.description" />
<view class="warning-time">
<wd-text size="12px" :text="warning.time" />
</view>
</view>
</view>
</wd-card>
</template>
<style lang="scss" scoped>
.warning-list {
@apply py-15px;
.warning-item {
+ .warning-item {
@apply mt-10px;
}
.warning-time {
@apply text-right mt-5px;
}
}
}
</style>

@ -2,13 +2,13 @@
* @Author: chris
* @Date: 2025-09-15 09:51:59
* @LastEditors: chris
* @LastEditTime: 2025-10-22 17:03:42
* @LastEditTime: 2025-10-23 16:53:59
-->
<script setup>
import bug from '@/static/svg/bug.svg'
import jiankongyun from '@/static/svg/jiankongyun.svg'
import tianqiyujing from '@/static/svg/tianqiyujing.svg'
import turangshuishi from '@/static/svg/turangshuishi.svg'
import BasicInfo from './components/basicInfo.vue'
import Monitor from './components/monitor.vue'
import Title from './components/title.vue'
import Warning from './components/warning.vue'
definePage({
style: {
@ -16,69 +16,10 @@ definePage({
},
})
//
const itemDict = {
plantingArea: {
svg: 'nongshi',
text: '种植面积(亩)',
value: 250,
},
terrain: {
svg: 'dixing',
text: '地形',
value: '丘陵山地',
},
variety: {
svg: 'dapengzhongmiaoguanli',
text: '主要品种',
value: '桂味',
},
plantingNum: {
svg: 'shuguo',
text: '种植荔枝(棵)',
value: 8500,
},
}
//
const modules = [
{
id: 'pest',
title: '虫情监控',
icon: bug,
desc: '实时监测果园病虫害情况',
route: '/pages/pest/pest',
},
{
id: 'soil',
title: '土壤墒情',
icon: turangshuishi,
desc: '监测土壤湿度、养分等数据',
route: '/pages/soil/soil',
},
{
id: 'weather',
title: '气象监测',
icon: tianqiyujing,
desc: '温度、湿度、光照等数据',
route: '/pages/weather/weather',
},
{
id: 'drone',
title: '无人机巡查',
icon: jiankongyun,
desc: '无人机航拍及数据分析',
route: '/pages/drone/index',
},
]
//
function handleModuleClick(module) {
//
console.log('跳转到:', module.route)
//
//
function handleMoreWarning() {
uni.navigateTo({
url: module.route,
url: '/pages/warning/warning',
})
}
</script>
@ -95,74 +36,25 @@ function handleModuleClick(module) {
<!-- 首页内容区域 -->
<view class="home-content">
<!-- 果园基本信息卡片 -->
<view class="info-section">
<wd-card :shadow="false" class="basic-card">
<!-- 基本信息网格 -->
<wd-row :gutter="12">
<wd-col
v-for="(item, key) in itemDict"
:key="key"
:span="12"
>
<view class="info-item-wrapper">
<view class="info-item">
<text class="info-label">{{ item.text }}</text>
<text class="info-value">{{ item.value }}</text>
</view>
</view>
</wd-col>
</wd-row>
</wd-card>
</view>
<!-- 基本信息区域 -->
<Title title="基本信息" />
<basic-info />
<!-- 监控模块区域 -->
<view class="monitor-section">
<text class="section-title">实时监控</text>
<!-- 模块网格 -->
<wd-row :gutter="15" class="module-row">
<wd-col
v-for="module in modules"
:key="module.id"
:span="12"
>
<view class="module-item-wrapper">
<view
class="module-card"
@tap="handleModuleClick(module)"
>
<view class="module-icon-container" :class="`module-${module.id}`">
<image :src="module.icon" mode="aspectFit" class="module-icon" />
</view>
<view class="module-info">
<text class="module-title">{{ module.title }}</text>
<text class="module-desc">{{ module.desc }}</text>
</view>
</view>
</view>
</wd-col>
</wd-row>
</view>
<Title title="实时监控" />
<monitor />
<!-- 虫情预警模块 -->
<Title title="预警信息">
<wd-button size="small" type="text" @tap="handleMoreWarning">
<text class="more-btn-text">查看更多</text>
</wd-button>
</Title>
<Warning />
</view>
</view>
</template>
<style lang="scss" scoped>
// -
$primary-color: #00c6ff; //
$primary-color-dark: #0072ff; //
$bg-color: #f0f2f5; //
$card-bg: #ffffff; //
$card-bg-glass: rgba(255, 255, 255, 0.85); //
$text-primary: #0f1419; //
$text-secondary: #333f51; //
$text-tertiary: #6e7683; //
$border-radius: 16px; //
$box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); //
$box-shadow-hover: 0 8px 32px rgba(0, 198, 255, 0.15); //
$transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); //
$glow-effect: 0 0 15px rgba(0, 198, 255, 0.3); //
@import './variables.scss';
//
.home-page {
@ -269,297 +161,31 @@ $glow-effect: 0 0 15px rgba(0, 198, 255, 0.3); // 发光效果
padding-bottom: 15px;
}
// .info-section,
// .monitor-section {
// margin: 0 -15px;
// }
//
.info-section {
margin-bottom: 24px;
}
//
.info-item-wrapper {
height: 100%;
}
//
.basic-card {
border-radius: $border-radius;
box-shadow: $box-shadow;
overflow: hidden;
background: $card-bg-glass;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
.section-title {
margin-left: 15px;
font-size: 18px;
font-weight: 600;
color: $text-primary;
display: block;
padding-left: 15px;
margin-bottom: 16px;
position: relative;
padding: 10px !important;
//
//
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, $primary-color, $primary-color-dark);
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: linear-gradient(180deg, $primary-color, $primary-color-dark);
border-radius: 2px;
box-shadow: 0 0 8px rgba($primary-color, 0.3);
}
}
// -
.info-item {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
min-height: 80px;
justify-content: center;
text-align: center;
position: relative;
padding: 10px;
//
&::before {
content: '';
position: absolute;
top: 10px;
right: 10px;
width: 30px;
height: 30px;
background: radial-gradient(circle, rgba(0, 198, 255, 0.1) 0%, transparent 70%);
border-radius: 50%;
opacity: 0.6;
}
.info-label {
font-size: 14px;
color: $text-tertiary;
margin-bottom: 8px;
letter-spacing: 0.3px;
position: relative;
z-index: 1;
}
.info-value {
font-size: 20px;
font-weight: 600;
color: $primary-color-dark;
letter-spacing: 0.5px;
position: relative;
z-index: 1;
//
&::after {
content: '';
position: absolute;
bottom: -4px;
left: 50%;
transform: translateX(-50%);
width: 40%;
height: 1px;
background: linear-gradient(90deg, transparent, $primary-color, transparent);
opacity: 0.6;
}
}
}
//
.monitor-section {
.section-title {
font-size: 18px;
font-weight: 600;
color: $text-primary;
display: block;
padding-left: 15px;
margin-bottom: 16px;
position: relative;
//
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: linear-gradient(180deg, $primary-color, $primary-color-dark);
border-radius: 2px;
box-shadow: 0 0 8px rgba($primary-color, 0.3);
}
}
//
.module-row {
// padding: 0 15px;
}
//
.module-item-wrapper {
height: 100%;
}
// -
.module-card {
padding: 20px 15px;
margin: 7.5px 0;
background-color: $card-bg-glass;
border-radius: $border-radius;
box-shadow: $box-shadow;
height: 160px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
transition: $transition;
overflow: hidden;
position: relative;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
//
&::before {
content: '';
position: absolute;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
border-radius: $border-radius;
padding: 1px;
background: linear-gradient(135deg, rgba(0, 198, 255, 0.2), transparent 50%, rgba(0, 198, 255, 0.2));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease;
}
//
&::after {
content: '';
position: absolute;
bottom: -20px;
right: -20px;
width: 60px;
height: 60px;
background: radial-gradient(circle, rgba(0, 198, 255, 0.1) 0%, transparent 70%);
border-radius: 50%;
opacity: 0.5;
}
}
// -
.module-icon-container {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12px;
width: 64px;
height: 64px;
border-radius: 12px;
position: relative;
overflow: hidden;
transition: transform 0.3s ease;
.module-card:hover & {
transform: scale(1.05);
}
&.module-pest {
background: linear-gradient(135deg, rgba(245, 87, 108, 0.12), rgba(245, 87, 108, 0.05));
box-shadow: 0 4px 12px rgba(245, 87, 108, 0.1);
}
&.module-soil {
background: linear-gradient(135deg, rgba(82, 196, 26, 0.12), rgba(82, 196, 26, 0.05));
box-shadow: 0 4px 12px rgba(82, 196, 26, 0.1);
}
&.module-weather {
background: linear-gradient(135deg, rgba(66, 153, 225, 0.12), rgba(66, 153, 225, 0.05));
box-shadow: 0 4px 12px rgba(66, 153, 225, 0.1);
}
&.module-drone {
background: linear-gradient(135deg, rgba(255, 152, 0, 0.12), rgba(255, 152, 0, 0.05));
box-shadow: 0 4px 12px rgba(255, 152, 0, 0.1);
}
//
&::before {
content: '';
position: absolute;
top: 0;
left: -50%;
width: 20%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transform: skewX(-20deg);
animation: shine 3s infinite linear;
}
}
//
@keyframes shine {
0% {
left: -50%;
}
100% {
left: 150%;
}
}
//
.module-icon {
width: 32px;
height: 32px;
transition: filter 0.3s ease;
.module-card:hover & {
filter: brightness(1.1);
}
}
//
.module-info {
width: 100%;
position: relative;
z-index: 1;
}
.module-title {
font-size: 16px;
font-weight: 600;
color: $text-primary;
margin-bottom: 6px;
display: block;
letter-spacing: 0.2px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.module-desc {
font-size: 13px;
color: $text-tertiary;
line-height: 1.5;
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
letter-spacing: 0.1px;
//
&::after {
content: '';
position: absolute;
bottom: -4px;
left: 50%;
transform: translateX(-50%);
width: 30%;
height: 1px;
background: linear-gradient(90deg, transparent, $primary-color, transparent);
opacity: 0.3;
}
}
.more-btn-text {
color: $-color-theme;
}
</style>

@ -0,0 +1,14 @@
// -
$primary-color: #00c6ff; //
$primary-color-dark: #0072ff; //
$bg-color: #f0f2f5; //
$card-bg: #ffffff; //
$card-bg-glass: rgba(255, 255, 255, 0.85); //
$text-primary: #0f1419; //
$text-secondary: #333f51; //
$text-tertiary: #6e7683; //
$border-radius: 16px; //
$box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06); //
$box-shadow-hover: 0 8px 32px rgba(0, 198, 255, 0.15); //
$transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); //
$glow-effect: 0 0 15px rgba(0, 198, 255, 0.3); //

@ -1,7 +1,6 @@
<script lang="ts" setup>
import type { IUploadSuccessInfo } from '@/api/types/login'
import { storeToRefs } from 'pinia'
import { LOGIN_PAGE } from '@/router/config'
import { useUserStore } from '@/store'
import { useTokenStore } from '@/store/token'
import { useUpload } from '@/utils/uploadFile'
@ -17,31 +16,11 @@ const tokenStore = useTokenStore()
// 使storeToRefsuserInfo
const { userInfo } = storeToRefs(userStore)
// #ifndef MP-WEIXIN
//
const { run: uploadAvatar } = useUpload<IUploadSuccessInfo>(
'/upload',
{},
{
onSuccess: (res) => {
console.log('h5头像上传成功', res)
useUserStore().setUserAvatar(res.url)
},
},
)
// #endif
//
async function handleLogin() {
// #ifdef MP-WEIXIN
//
await tokenStore.wxLogin()
// #endif
// #ifndef MP-WEIXIN
uni.navigateTo({
url: `${LOGIN_PAGE}?redirect=${encodeURIComponent('/pages/me/me')}`,
})
// #endif
}
@ -90,10 +69,6 @@ function handleLogout() {
//
// uni.reLaunch({ url: '/pages/index/index' })
// #endif
// #ifndef MP-WEIXIN
//
// uni.navigateTo({ url: LOGIN_PAGE })
// #endif
}
},
})
@ -103,92 +78,77 @@ function handleLogout() {
<template>
<view class="profile-container">
<!-- 用户信息区域 -->
<view class="user-info-section">
<!-- #ifdef MP-WEIXIN -->
<button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image :src="userInfo.avatar" mode="scaleToFill" class="h-full w-full" />
</button>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="avatar-wrapper" @click="uploadAvatar">
<image :src="userInfo.avatar" mode="scaleToFill" class="h-full w-full" />
</view>
<!-- #endif -->
<view class="user-details">
<wd-card>
<view class="user-info-section">
<!-- #ifdef MP-WEIXIN -->
<input
v-model="userInfo.username"
type="nickname"
class="weui-input"
placeholder="请输入昵称"
>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="username">
{{ userInfo.username }}
</view>
<button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image :src="userInfo.avatar" mode="scaleToFill" class="h-full w-full" />
</button>
<!-- #endif -->
<view class="user-id">
ID: {{ userInfo.userId }}
<view class="user-details">
<!-- #ifdef MP-WEIXIN -->
<input
v-model="userInfo.username"
type="nickname"
class="weui-input"
placeholder="请输入昵称"
>
<!-- #endif -->
<view class="user-id">
ID: {{ userInfo.userId }}
</view>
</view>
</view>
</view>
</wd-card>
<view class="mt-3 break-all px-3">
{{ JSON.stringify(userInfo, null, 2) }}
</view>
<wd-card>
<wd-cell-group :border="true">
<wd-cell title="我的果园" value="***果园" />
<wd-cell title="推送设置" is-link />
</wd-cell-group>
</wd-card>
<view class="mt-20 px-3">
<view class="m-auto w-160px text-center">
<button v-if="tokenStore.hasLogin" type="warn" class="w-full" @click="handleLogout">
<wd-button v-if="tokenStore.hasLogin" type="warning" block @click="handleLogout">
退出登录
</button>
<button v-else type="primary" class="w-full" @click="handleLogin">
</wd-button>
<!-- <button v-else type="primary" class="w-full" @click="handleLogin">
登录
</button>
</button> -->
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
$avatar-size: 120rpx;
/* 基础样式 */
.profile-container {
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
// background-color: #f7f8fa;
background-color: #f7f8fa;
height: 100vh;
padding: 20rpx 0;
}
/* 用户信息区域 */
.user-info-section {
display: flex;
align-items: center;
padding: 40rpx;
margin: 30rpx 30rpx 20rpx;
background-color: #fff;
border-radius: 24rpx;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
padding: 30rpx 0;
}
.avatar-wrapper {
width: 160rpx;
height: 160rpx;
margin-right: 40rpx;
overflow: hidden;
border: 4rpx solid #f5f5f5;
border-radius: 50%;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.avatar-button {
height: 160rpx;
width: 160rpx;
height: $avatar-size;
width: $avatar-size;
padding: 0;
margin-right: 40rpx;
overflow: hidden;
border: 4rpx solid #f5f5f5;
// border: 4rpx solid #f5f5f5;
border-radius: 50%;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.user-details {
flex: 1;
}

@ -0,0 +1,131 @@
<!--
* @Author: chris
* @Date: 2025-10-23 16:55:09
* @LastEditors: chris
* @LastEditTime: 2025-10-24 10:13:44
-->
<script setup lang="ts">
interface Form {
beginTime: string
endTime: string
pageSize: number
pageNum: number
}
interface Warning {
title: string
time: string
}
definePage({
style: {
navigationBarTitleText: '预警信息',
},
})
const form = ref<Form>({
beginTime: '',
endTime: '',
pageSize: 10,
pageNum: 1,
})
const dateRange = ref<number[]>([null, null])
const warningList = ref<Warning[]>([{
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}, {
title: '监测到果园东区荔枝蒂蛀虫密度异常增高预计48小时内可能大规模爆发可能大规模爆发可能大规模爆发123123123123',
time: '2小时前',
}])
function handleConfirm(value: number[]) {
console.log(value)
form.value.beginTime = dateRange.value[0] as any
form.value.endTime = dateRange.value[1] as any
}
function handleSubmit(value: number[]) {
console.log(value)
}
function handleScrollLower() {
console.log('scroll lower')
}
</script>
<template>
<view class="warning-page">
<wd-drop-menu>
<wd-drop-menu-item title="筛选">
<view class="filter-container">
<wd-calendar v-model="dateRange" type="daterange" @confirm="handleConfirm" />
<wd-button class="submit-btn" type="primary" block @click="handleSubmit">
查询
</wd-button>
</view>
</wd-drop-menu-item>
</wd-drop-menu>
<scroll-view scroll-y @scrolltolower="handleScrollLower">
<view class="warning-list">
<wd-card v-for="(item, index) in warningList" :key="index" class="warning-item">
<view class="warning-content">
<wd-text :text="item.title" />
<view class="warning-time">
<wd-text size="12px" :text="item.time" />
</view>
</view>
</wd-card>
</view>
</scroll-view>
</view>
</template>
<style lang="scss" scoped>
.warning-page {
@apply bg-[#f5f5f5];
}
.filter-container {
@apply p-20px;
.submit-btn {
@apply mt-30px;
}
}
scroll-view {
@apply h-[calc(100vh-48px)];
}
.warning-list {
@apply py-15px;
}
.warning-content {
@apply py-10px;
}
.warning-time {
@apply mt-20px text-right;
> .wd-text {
@apply py-2px px-6px bg-[#f5f5f5] rounded-8px;
}
}
</style>

@ -2,5 +2,5 @@ view {
padding: 0;
margin: 0;
box-sizing: border-box;
color: $-color-title;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
}

Loading…
Cancel
Save