index.vue 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. <template>
  2. <view class="dashboard-container">
  3. <!-- 顶部信息卡片 - 更现代化的设计 -->
  4. <view class="header-card">
  5. <view class="header-left">
  6. <view class="welcome-section">
  7. <text class="welcome-text">您好,{{ userData.nickname }}</text>
  8. <view class="plot-info">
  9. <text class="plot-label">当前地块:</text>
  10. <text class="plot-name">{{ userData.selectedPlot }}</text>
  11. <view class="switch-plot-btn" @click="handleSwitchPlot">
  12. <u-icon name="arrow-down-fill" color="#ffffff" size="14"></u-icon>
  13. <text>切换</text>
  14. </view>
  15. </view>
  16. </view>
  17. </view>
  18. <view class="header-right">
  19. <view class="user-avatar" @click="navigateToProfile">
  20. <view class="avatar-svg">
  21. <svg width="100%" height="100%" viewBox="0 0 90 90" fill="none" xmlns="http://www.w3.org/2000/svg">
  22. <!-- 背景圆 -->
  23. <circle cx="45" cy="45" r="45" fill="#E1F5E9"/>
  24. <!-- 背景装饰 - 农作物图案 -->
  25. <path d="M15 35C15 35 25 25 35 35C45 45 65 25 75 35" stroke="#4CAF50" stroke-width="2" stroke-opacity="0.3"/>
  26. <path d="M20 30L20 40" stroke="#4CAF50" stroke-width="2" stroke-opacity="0.3"/>
  27. <path d="M35 30L35 45" stroke="#4CAF50" stroke-width="2" stroke-opacity="0.3"/>
  28. <path d="M50 30L50 40" stroke="#4CAF50" stroke-width="2" stroke-opacity="0.3"/>
  29. <path d="M65 30L65 45" stroke="#4CAF50" stroke-width="2" stroke-opacity="0.3"/>
  30. <!-- 人形轮廓 -->
  31. <circle cx="45" cy="35" r="15" fill="#4CAF50"/>
  32. <path d="M25 82C25 67 34 55 45 55C56 55 65 67 65 82H25Z" fill="#4CAF50"/>
  33. <!-- 帽子 - 农夫草帽 -->
  34. <path d="M25 30C25 30 35 20 45 20C55 20 65 30 65 30C65 30 55 25 45 25C35 25 25 30 25 30Z" fill="#8BC34A"/>
  35. <!-- 装饰细节 -->
  36. <circle cx="38" cy="32" r="2" fill="white" fill-opacity="0.7"/>
  37. <circle cx="52" cy="32" r="2" fill="white" fill-opacity="0.7"/>
  38. <path d="M40 40C40 40 43 42 45 42C47 42 50 40 50 40" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
  39. <!-- 麦穗装饰 -->
  40. <path d="M70 15C70 15 75 20 75 25" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  41. <path d="M73 18L77 20" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  42. <path d="M72 22L76 24" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  43. <path d="M20 15C20 15 15 20 15 25" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  44. <path d="M17 18L13 20" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  45. <path d="M18 22L14 24" stroke="#8BC34A" stroke-width="1.5" stroke-linecap="round"/>
  46. </svg>
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. <!-- 核心数据指标 - 科技感设计 -->
  52. <view class="stats-grid">
  53. <view class="stat-card" v-for="(stat, index) in coreStats" :key="index">
  54. <view class="stat-content">
  55. <text class="stat-value">{{ stat.value }}</text>
  56. <text class="stat-label">{{ stat.label }}</text>
  57. </view>
  58. </view>
  59. </view>
  60. <!-- 农事活动卡片 - 使用线性进度条 -->
  61. <view class="section-card">
  62. <view class="card-header">
  63. <view class="card-title">
  64. <view class="title-icon">
  65. <view class="icon-dot"></view>
  66. </view>
  67. <text class="title-text">近期农事活动</text>
  68. </view>
  69. <view class="more-link" @click="navigateToAllActivities">
  70. <text>更多</text>
  71. <u-icon name="arrow-right" color="#4CAF50" size="14"></u-icon>
  72. </view>
  73. </view>
  74. <view class="card-body">
  75. <view class="activity-header">
  76. <view class="activity-header-right">
  77. <text class="header-title">任务名称</text>
  78. <text class="header-executor">执行人</text>
  79. <text class="header-date">计划日期</text>
  80. <view class="header-action"></view>
  81. </view>
  82. </view>
  83. <view v-for="(item, index) in farmData.recentActivities" :key="index"
  84. class="activity-item" @click="navigateToActivity(item)">
  85. <view class="activity-right">
  86. <view class="activity-content">
  87. <text class="activity-title">{{ item.title }}</text>
  88. </view>
  89. <text class="activity-executor">{{ item.executor }}</text>
  90. <text class="activity-date">{{ item.date }}</text>
  91. <view class="activity-action">
  92. <u-icon name="arrow-right" color="#CCCCCC" size="16"></u-icon>
  93. </view>
  94. </view>
  95. </view>
  96. </view>
  97. </view>
  98. <!-- 天气和农情预测 - 更现代化的信息图表 -->
  99. <view class="section-card weather-card">
  100. <view class="card-header">
  101. <view class="card-title">
  102. <view class="title-icon">
  103. <view class="icon-dot"></view>
  104. </view>
  105. <text class="title-text">天气与农情</text>
  106. </view>
  107. </view>
  108. <view class="card-body">
  109. <view class="weather-main">
  110. <view class="weather-top">
  111. <view class="weather-left">
  112. <view class="weather-icon-large">
  113. <!-- 自定义的晴朗天气图标 -->
  114. <svg width="48" height="48" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg" class="sun-icon">
  115. <!-- 光晕效果 -->
  116. <circle cx="100" cy="100" r="65" fill="rgba(255, 193, 7, 0.1)" />
  117. <!-- 主太阳圆形 -->
  118. <circle cx="100" cy="100" r="45" fill="#FFC107"/>
  119. <!-- 放射光芒 - 主要 -->
  120. <line x1="100" y1="25" x2="100" y2="5" stroke="#FFC107" stroke-width="8" stroke-linecap="round"/>
  121. <line x1="100" y1="195" x2="100" y2="175" stroke="#FFC107" stroke-width="8" stroke-linecap="round"/>
  122. <line x1="25" y1="100" x2="5" y2="100" stroke="#FFC107" stroke-width="8" stroke-linecap="round"/>
  123. <line x1="195" y1="100" x2="175" y2="100" stroke="#FFC107" stroke-width="8" stroke-linecap="round"/>
  124. <!-- 内部细节 -->
  125. <circle cx="100" cy="100" r="35" fill="#FF9800"/>
  126. </svg>
  127. </view>
  128. <view class="weather-info">
  129. <view class="temp-row">
  130. <view class="temp-display">
  131. <text class="weather-temp">{{ weatherData.temperature }}</text>
  132. <text class="temp-unit">°C</text>
  133. </view>
  134. <text class="weather-desc">{{ weatherData.description }}</text>
  135. </view>
  136. </view>
  137. </view>
  138. </view>
  139. <view class="weather-advice">
  140. <view class="advice-header">
  141. <text class="advice-title">今日农事建议:</text>
  142. <u-icon name="account" color="#666666" size="32"></u-icon>
  143. </view>
  144. <text class="advice-content">{{ weatherData.advice }}</text>
  145. </view>
  146. </view>
  147. <view class="weather-metrics">
  148. <view class="metric-item">
  149. <text class="metric-label">湿度</text>
  150. <text class="metric-value">{{ weatherData.humidity }}%</text>
  151. </view>
  152. <view class="metric-divider"></view>
  153. <view class="metric-item">
  154. <text class="metric-label">风力</text>
  155. <text class="metric-value">{{ weatherData.windLevel }}级</text>
  156. </view>
  157. <view class="metric-divider"></view>
  158. <view class="metric-item">
  159. <text class="metric-label">降水</text>
  160. <text class="metric-value">{{ weatherData.rainfall }}mm</text>
  161. </view>
  162. </view>
  163. </view>
  164. </view>
  165. <!-- 统计卡片区域 -->
  166. <view class="stats-section">
  167. <view class="stats-grid">
  168. <!-- 本月作业情况 -->
  169. <view class="stat-card">
  170. <view class="card-header">
  171. <view class="icon-badge">
  172. <text class="icon">📊</text>
  173. </view>
  174. <text class="card-title">本月作业情况</text>
  175. </view>
  176. <view class="card-content">
  177. <view class="main-stats">
  178. <view class="stat-item">
  179. <text class="number">36</text>
  180. <text class="label">作业次数</text>
  181. </view>
  182. <view class="stat-item">
  183. <text class="number">128</text>
  184. <text class="label">作业面积(亩)</text>
  185. </view>
  186. </view>
  187. <view class="sub-info">
  188. <text class="emoji">🌾</text>
  189. <text class="info-text">主要作物:小麦、玉米</text>
  190. </view>
  191. </view>
  192. </view>
  193. <!-- 农机使用情况 -->
  194. <view class="stat-card">
  195. <view class="card-header">
  196. <view class="icon-badge">
  197. <text class="icon">🚜</text>
  198. </view>
  199. <text class="card-title">农机使用情况</text>
  200. </view>
  201. <view class="card-content">
  202. <view class="main-stats">
  203. <view class="stat-item">
  204. <text class="number">172</text>
  205. <text class="label">总使用时长(小时)</text>
  206. </view>
  207. <view class="stat-item">
  208. <text class="number">75%</text>
  209. <text class="label">计划完成率</text>
  210. </view>
  211. </view>
  212. <view class="sub-info">
  213. <text class="emoji">🛠</text>
  214. <text class="info-text">设备:无人拖拉机、播种机</text>
  215. </view>
  216. </view>
  217. </view>
  218. <!-- 灌溉与施肥数据 -->
  219. <view class="stat-card">
  220. <view class="card-header">
  221. <view class="icon-badge">
  222. <text class="icon">💧</text>
  223. </view>
  224. <text class="card-title">灌溉与施肥数据</text>
  225. </view>
  226. <view class="card-content">
  227. <view class="main-stats">
  228. <view class="stat-item">
  229. <text class="number">85</text>
  230. <text class="label">灌溉面积(亩)</text>
  231. </view>
  232. <view class="stat-item">
  233. <text class="number">230</text>
  234. <text class="label">用水量(m³)</text>
  235. </view>
  236. </view>
  237. <view class="sub-info">
  238. <text class="emoji">🌱</text>
  239. <text class="info-text">本月施肥次数:12次</text>
  240. </view>
  241. </view>
  242. </view>
  243. <!-- 病虫害处理情况 -->
  244. <view class="stat-card">
  245. <view class="card-header">
  246. <view class="icon-badge">
  247. <text class="icon">🐛</text>
  248. </view>
  249. <text class="card-title">病虫害处理情况</text>
  250. </view>
  251. <view class="card-content">
  252. <view class="main-stats">
  253. <view class="stat-item">
  254. <text class="number">4/5</text>
  255. <text class="label">处理进度</text>
  256. </view>
  257. <view class="stat-item">
  258. <view class="progress-circle">
  259. <text class="progress-text">80%</text>
  260. </view>
  261. <text class="label">完成率</text>
  262. </view>
  263. </view>
  264. <view class="sub-info warning">
  265. <text class="emoji">⚠️</text>
  266. <text class="info-text">待处理:1个预警</text>
  267. </view>
  268. </view>
  269. </view>
  270. </view>
  271. </view>
  272. </view>
  273. </template>
  274. <script setup>
  275. import { ref, computed, onMounted } from 'vue';
  276. // 用户数据
  277. const userData = ref({
  278. nickname: '张三',
  279. selectedPlot: '南地块'
  280. });
  281. // 地块选择
  282. const showPlotSelector = ref(false);
  283. const availablePlots = ref([
  284. { name: '南地块', id: 1 },
  285. { name: '西北区域', id: 2 },
  286. { name: '稻田', id: 3 },
  287. { name: '东区试验田', id: 4 },
  288. { name: '温室大棚', id: 5 }
  289. ]);
  290. // 农场数据
  291. const farmData = ref({
  292. plotCount: 5,
  293. deviceCount: 12,
  294. deviceOnlineRate: 85,
  295. taskCompletionRate: 76,
  296. recentActivities: [
  297. { title: '稻田水稻施肥', date: '2023-05-15', status: 'pending', id: 1, executor: '李四' },
  298. { title: '南地块除草', date: '2023-05-12', status: 'completed', id: 2, executor: '王五' },
  299. { title: '西北区域杀虫', date: '2023-05-08', status: 'completed', id: 3, executor: '张三' }
  300. ]
  301. });
  302. // 核心数据指标
  303. const coreStats = computed(() => [
  304. {
  305. label: '地块总数',
  306. value: farmData.value.plotCount,
  307. icon: 'map',
  308. bgColor: 'linear-gradient(135deg, #4CAF50, #2E7D32)'
  309. },
  310. {
  311. label: '设备数量',
  312. value: farmData.value.deviceCount,
  313. icon: 'setting',
  314. bgColor: 'linear-gradient(135deg, #42A5F5, #1976D2)'
  315. },
  316. {
  317. label: '设备在线率',
  318. value: farmData.value.deviceOnlineRate + '%',
  319. icon: 'wifi',
  320. bgColor: 'linear-gradient(135deg, #26C6DA, #00838F)'
  321. },
  322. {
  323. label: '农事完成率',
  324. value: farmData.value.taskCompletionRate + '%',
  325. icon: 'checkmark-circle',
  326. bgColor: 'linear-gradient(135deg, #66BB6A, #388E3C)'
  327. }
  328. ]);
  329. // 天气数据
  330. const weatherData = ref({
  331. temperature: 28,
  332. description: '晴朗',
  333. humidity: 65,
  334. windLevel: 3,
  335. rainfall: 0,
  336. advice: '今日适宜进行春玉米防虫作业,注意水分管理。'
  337. });
  338. // 统计数据
  339. const statsData = ref({
  340. operation: {
  341. workCount: 36,
  342. workArea: 128,
  343. mainCrops: ['小麦', '玉米']
  344. },
  345. machine: {
  346. totalHours: 172,
  347. mainEquipment: ['无人拖拉机', '播种机']
  348. },
  349. irrigation: {
  350. irrigationArea: 85,
  351. fertilizationCount: 12,
  352. waterUsage: 230
  353. },
  354. pest: {
  355. totalReports: 5,
  356. handled: 4,
  357. pending: 1
  358. }
  359. });
  360. // 方法
  361. const handleShowMap = () => {
  362. uni.navigateTo({
  363. url: '/pages/map/index'
  364. });
  365. };
  366. const navigateToProfile = () => {
  367. uni.navigateTo({
  368. url: '/pages/profile/index'
  369. });
  370. };
  371. const handleSwitchPlot = () => {
  372. showPlotSelector.value = true;
  373. };
  374. const selectPlot = (plot) => {
  375. userData.value.selectedPlot = plot.name;
  376. showPlotSelector.value = false;
  377. // 实际应用中,这里需要重新加载当前地块的数据
  378. uni.showToast({
  379. title: `已切换到${plot.name}`,
  380. icon: 'none'
  381. });
  382. };
  383. const navigateToActivity = (activity) => {
  384. uni.navigateTo({
  385. url: `/pages/activity/detail?id=${activity.id}`
  386. });
  387. };
  388. const navigateToAllActivities = () => {
  389. uni.navigateTo({
  390. url: '/pages/activity/list'
  391. });
  392. };
  393. // 获取统计数据
  394. const fetchStatsData = async () => {
  395. try {
  396. // 实际项目中替换为API调用
  397. // const response = await api.getStatsData();
  398. // statsData.value = response.data;
  399. console.log('统计数据加载成功');
  400. } catch (error) {
  401. console.error('获取统计数据失败', error);
  402. uni.showToast({
  403. title: '数据加载失败',
  404. icon: 'none'
  405. });
  406. }
  407. };
  408. // 页面加载
  409. onMounted(() => {
  410. fetchStatsData();
  411. });
  412. </script>
  413. <style lang="scss" scoped>
  414. .dashboard-container {
  415. padding: 30rpx 20rpx;
  416. background-color: #f8f9fa;
  417. min-height: 100vh;
  418. }
  419. // 顶部信息卡片
  420. .header-card {
  421. display: flex;
  422. justify-content: space-between;
  423. align-items: center;
  424. padding: 30rpx;
  425. background: linear-gradient(135deg, #4CAF50, #2E7D32);
  426. border-radius: 20rpx;
  427. margin-bottom: 24rpx;
  428. box-shadow: 0 8rpx 16rpx rgba(76, 175, 80, 0.2);
  429. .header-left {
  430. flex: 1;
  431. }
  432. .header-right {
  433. display: flex;
  434. align-items: center;
  435. }
  436. .user-avatar {
  437. width: 90rpx;
  438. height: 90rpx;
  439. border-radius: 50%;
  440. overflow: hidden;
  441. background-color: #ffffff;
  442. box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  443. .avatar-svg {
  444. width: 100%;
  445. height: 100%;
  446. }
  447. }
  448. .welcome-text {
  449. font-size: 38rpx;
  450. font-weight: bold;
  451. color: #ffffff;
  452. margin-bottom: 12rpx;
  453. }
  454. .plot-info {
  455. display: flex;
  456. align-items: center;
  457. flex-wrap: wrap;
  458. .plot-label {
  459. font-size: 28rpx;
  460. color: rgba(255, 255, 255, 0.9);
  461. margin-right: 4rpx;
  462. }
  463. .plot-name {
  464. font-size: 28rpx;
  465. color: #ffffff;
  466. font-weight: 500;
  467. margin-right: 16rpx;
  468. }
  469. .switch-plot-btn {
  470. display: flex;
  471. align-items: center;
  472. background-color: rgba(255, 255, 255, 0.2);
  473. border-radius: 30rpx;
  474. padding: 4rpx 16rpx;
  475. margin-left: 8rpx;
  476. text {
  477. font-size: 24rpx;
  478. color: #ffffff;
  479. margin-left: 4rpx;
  480. }
  481. }
  482. }
  483. }
  484. // 核心数据指标网格
  485. .stats-grid {
  486. display: grid;
  487. grid-template-columns: repeat(2, 1fr);
  488. gap: 20rpx;
  489. margin-bottom: 24rpx;
  490. .stat-card {
  491. background-color: #ffffff;
  492. border-radius: 16rpx;
  493. padding: 24rpx;
  494. display: flex;
  495. flex-direction: column;
  496. align-items: center;
  497. justify-content: center;
  498. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
  499. .stat-content {
  500. display: flex;
  501. flex-direction: column;
  502. align-items: center;
  503. text-align: center;
  504. .stat-value {
  505. font-size: 40rpx;
  506. font-weight: bold;
  507. color: #333;
  508. margin-bottom: 10rpx;
  509. }
  510. .stat-label {
  511. font-size: 26rpx;
  512. color: #666;
  513. }
  514. }
  515. }
  516. }
  517. // 卡片通用样式
  518. .section-card {
  519. background-color: #ffffff;
  520. border-radius: 16rpx;
  521. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
  522. margin-bottom: 24rpx;
  523. overflow: hidden;
  524. .card-header {
  525. display: flex;
  526. justify-content: space-between;
  527. align-items: center;
  528. padding: 20rpx 24rpx;
  529. border-bottom: 1px solid #f0f0f0;
  530. .card-title {
  531. display: flex;
  532. align-items: center;
  533. .title-icon {
  534. display: flex;
  535. align-items: center;
  536. margin-right: 12rpx;
  537. .icon-dot {
  538. width: 12rpx;
  539. height: 12rpx;
  540. border-radius: 6rpx;
  541. background-color: #4CAF50;
  542. }
  543. }
  544. .title-text {
  545. font-size: 30rpx;
  546. font-weight: bold;
  547. color: #333;
  548. }
  549. }
  550. .more-link {
  551. display: flex;
  552. align-items: center;
  553. text {
  554. font-size: 24rpx;
  555. color: #4CAF50;
  556. margin-right: 6rpx;
  557. }
  558. }
  559. }
  560. .card-body {
  561. padding: 0;
  562. border: 1rpx solid rgba(76, 175, 80, 0.15);
  563. border-radius: 10rpx;
  564. overflow: hidden;
  565. box-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.03);
  566. .activity-item:not(:last-child) {
  567. position: relative;
  568. &:after {
  569. content: '';
  570. position: absolute;
  571. left: 0;
  572. right: 0;
  573. bottom: 0;
  574. height: 1rpx;
  575. background-color: #f2f2f2;
  576. }
  577. }
  578. }
  579. }
  580. // 活动标题行
  581. .activity-header {
  582. display: flex;
  583. margin-bottom: 0;
  584. padding-bottom: 18rpx;
  585. padding-top: 18rpx;
  586. border-bottom: 1rpx solid rgba(76, 175, 80, 0.1);
  587. background-color: rgba(76, 175, 80, 0.07);
  588. border-radius: 8rpx 8rpx 0 0;
  589. .activity-header-right {
  590. flex: 1;
  591. display: flex;
  592. justify-content: space-between;
  593. align-items: center;
  594. .header-title {
  595. flex: 1.5;
  596. font-size: 28rpx;
  597. color: #4CAF50;
  598. font-weight: bold;
  599. padding-left: 30rpx;
  600. text-align: left;
  601. }
  602. .header-executor {
  603. font-size: 28rpx;
  604. color: #4CAF50;
  605. font-weight: bold;
  606. width: 180rpx;
  607. text-align: center;
  608. }
  609. .header-date {
  610. font-size: 28rpx;
  611. color: #4CAF50;
  612. font-weight: bold;
  613. min-width: 250rpx;
  614. text-align: center;
  615. margin-right: 20rpx;
  616. }
  617. .header-action {
  618. width: 36rpx;
  619. }
  620. }
  621. }
  622. // 农事活动列表
  623. .activity-item {
  624. display: flex;
  625. margin-bottom: 0;
  626. padding: 24rpx 0;
  627. border-bottom: 1rpx solid #f2f2f2;
  628. height: 60rpx;
  629. &:last-child {
  630. border-bottom-left-radius: 8rpx;
  631. border-bottom-right-radius: 8rpx;
  632. }
  633. .activity-right {
  634. flex: 1;
  635. display: flex;
  636. justify-content: space-between;
  637. align-items: center;
  638. padding-bottom: 0;
  639. border-bottom: none;
  640. height: 100%;
  641. .activity-content {
  642. flex: 1.5;
  643. padding-left: 30rpx;
  644. height: 100%;
  645. display: flex;
  646. align-items: center;
  647. .activity-title {
  648. font-size: 28rpx;
  649. color: #333;
  650. font-weight: 500;
  651. text-align: left;
  652. line-height: 1.4;
  653. }
  654. }
  655. .activity-executor {
  656. font-size: 28rpx;
  657. color: #666;
  658. width: 180rpx;
  659. text-align: center;
  660. height: 100%;
  661. display: flex;
  662. align-items: center;
  663. justify-content: center;
  664. }
  665. .activity-date {
  666. font-size: 28rpx;
  667. color: #999;
  668. text-align: center;
  669. margin-right: 20rpx;
  670. min-width: 250rpx;
  671. height: 100%;
  672. display: flex;
  673. align-items: center;
  674. justify-content: center;
  675. }
  676. .activity-action {
  677. width: 36rpx;
  678. }
  679. }
  680. }
  681. // 天气卡片
  682. .weather-card {
  683. .card-body {
  684. padding: 0;
  685. background: #ffffff;
  686. border-radius: 12rpx;
  687. overflow: hidden;
  688. }
  689. .weather-main {
  690. padding: 30rpx;
  691. }
  692. .weather-top {
  693. display: flex;
  694. margin-bottom: 0;
  695. }
  696. .weather-left {
  697. display: flex;
  698. align-items: flex-start;
  699. gap: 20rpx;
  700. }
  701. .weather-icon-large {
  702. width: 48rpx;
  703. height: 48rpx;
  704. margin-top: 6rpx;
  705. flex-shrink: 0;
  706. }
  707. .weather-info {
  708. .temp-row {
  709. display: flex;
  710. align-items: center;
  711. gap: 16rpx;
  712. .temp-display {
  713. display: flex;
  714. align-items: flex-start;
  715. .weather-temp {
  716. font-size: 48rpx;
  717. font-weight: 500;
  718. color: #333;
  719. line-height: 1;
  720. }
  721. .temp-unit {
  722. font-size: 24rpx;
  723. color: #666;
  724. margin-top: 6rpx;
  725. margin-left: 2rpx;
  726. }
  727. }
  728. .weather-desc {
  729. font-size: 28rpx;
  730. color: #666;
  731. margin-top: 4rpx;
  732. }
  733. }
  734. }
  735. .weather-advice {
  736. background: #F8FFF9;
  737. border: 2rpx solid rgba(76, 175, 80, 0.15);
  738. border-radius: 12rpx;
  739. padding: 24rpx;
  740. margin-top: 24rpx;
  741. .advice-header {
  742. display: flex;
  743. align-items: center;
  744. gap: 8rpx;
  745. margin-bottom: 12rpx;
  746. .advice-title {
  747. font-size: 28rpx;
  748. color: #4CAF50;
  749. font-weight: 500;
  750. }
  751. }
  752. .advice-content {
  753. font-size: 26rpx;
  754. color: #333;
  755. line-height: 1.5;
  756. }
  757. }
  758. }
  759. .weather-metrics {
  760. display: flex;
  761. justify-content: space-between;
  762. align-items: center;
  763. padding: 20rpx 30rpx;
  764. border-top: 2rpx solid #f5f5f5;
  765. .metric-item {
  766. flex: 1;
  767. display: flex;
  768. flex-direction: column;
  769. align-items: center;
  770. .metric-label {
  771. font-size: 24rpx;
  772. color: #999;
  773. margin-bottom: 8rpx;
  774. }
  775. .metric-value {
  776. font-size: 28rpx;
  777. color: #333;
  778. font-weight: 500;
  779. }
  780. }
  781. .metric-divider {
  782. width: 2rpx;
  783. height: 40rpx;
  784. background: #f0f0f0;
  785. margin: 0 20rpx;
  786. }
  787. }
  788. @keyframes rotate {
  789. from {
  790. transform: rotate(0deg);
  791. }
  792. to {
  793. transform: rotate(360deg);
  794. }
  795. }
  796. @keyframes float {
  797. 0%, 100% {
  798. transform: translateY(0);
  799. }
  800. 50% {
  801. transform: translateY(-6rpx);
  802. }
  803. }
  804. @keyframes rainDrop {
  805. 0%, 100% {
  806. transform: translateY(0);
  807. }
  808. 50% {
  809. transform: translateY(2rpx);
  810. }
  811. }
  812. // 地块选择弹出层
  813. .plot-selector {
  814. background-color: #ffffff;
  815. border-radius: 24rpx 24rpx 0 0;
  816. overflow: hidden;
  817. .plot-selector-header {
  818. display: flex;
  819. justify-content: space-between;
  820. align-items: center;
  821. padding: 30rpx;
  822. border-bottom: 1rpx solid #f0f0f0;
  823. .plot-selector-title {
  824. font-size: 32rpx;
  825. font-weight: bold;
  826. color: #333;
  827. }
  828. }
  829. .plot-selector-body {
  830. max-height: 60vh;
  831. overflow-y: auto;
  832. padding: 0 30rpx;
  833. .plot-selector-item {
  834. display: flex;
  835. justify-content: space-between;
  836. align-items: center;
  837. padding: 30rpx 0;
  838. border-bottom: 1rpx solid #f0f0f0;
  839. &:last-child {
  840. border-bottom: none;
  841. }
  842. &.active {
  843. .plot-name {
  844. color: #4CAF50;
  845. font-weight: bold;
  846. }
  847. }
  848. .plot-name {
  849. font-size: 30rpx;
  850. color: #333;
  851. }
  852. }
  853. }
  854. }
  855. .stats-section {
  856. margin: 40rpx 32rpx;
  857. .stats-grid {
  858. display: grid;
  859. grid-template-columns: repeat(2, 1fr);
  860. gap: 40rpx 32rpx;
  861. }
  862. .stat-card {
  863. background: #FAFAFA;
  864. border-radius: 24rpx;
  865. padding: 32rpx;
  866. box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.04);
  867. min-height: 320rpx;
  868. display: flex;
  869. flex-direction: column;
  870. transition: all 0.3s ease;
  871. &:hover {
  872. transform: translateY(-2rpx);
  873. box-shadow: 0 12rpx 48rpx rgba(0, 0, 0, 0.08);
  874. }
  875. .card-header {
  876. display: flex;
  877. align-items: center;
  878. justify-content: center;
  879. margin-bottom: 32rpx;
  880. gap: 16rpx;
  881. .icon-badge {
  882. width: 48rpx;
  883. height: 48rpx;
  884. border-radius: 50%;
  885. display: flex;
  886. align-items: center;
  887. justify-content: center;
  888. background: linear-gradient(135deg, var(--primary-color, #4CAF50), var(--primary-dark, #2E7D32));
  889. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  890. .icon {
  891. font-size: 24rpx;
  892. }
  893. }
  894. .card-title {
  895. font-size: 32rpx;
  896. color: #333;
  897. font-weight: 600;
  898. }
  899. }
  900. .card-content {
  901. flex: 1;
  902. display: flex;
  903. flex-direction: column;
  904. justify-content: space-between;
  905. .main-stats {
  906. display: flex;
  907. justify-content: space-around;
  908. gap: 24rpx;
  909. margin-bottom: 32rpx;
  910. .stat-item {
  911. flex: 1;
  912. text-align: center;
  913. .number {
  914. font-size: 48rpx;
  915. font-weight: 600;
  916. color: #333;
  917. line-height: 1.5;
  918. display: block;
  919. animation: numberChange 0.5s ease-out;
  920. }
  921. .label {
  922. font-size: 24rpx;
  923. color: #999;
  924. line-height: 1.5;
  925. display: block;
  926. margin-top: 8rpx;
  927. }
  928. .progress-circle {
  929. width: 96rpx;
  930. height: 96rpx;
  931. margin: 0 auto;
  932. border-radius: 50%;
  933. background: conic-gradient(
  934. var(--primary-color, #4CAF50) 80%,
  935. #f0f0f0 80%
  936. );
  937. display: flex;
  938. align-items: center;
  939. justify-content: center;
  940. position: relative;
  941. &::after {
  942. content: '';
  943. position: absolute;
  944. width: 80rpx;
  945. height: 80rpx;
  946. background: #FAFAFA;
  947. border-radius: 50%;
  948. }
  949. .progress-text {
  950. font-size: 28rpx;
  951. font-weight: 600;
  952. color: #333;
  953. z-index: 1;
  954. }
  955. }
  956. }
  957. }
  958. .sub-info {
  959. display: flex;
  960. align-items: center;
  961. justify-content: center;
  962. gap: 8rpx;
  963. padding: 16rpx;
  964. background: rgba(0, 0, 0, 0.02);
  965. border-radius: 12rpx;
  966. .emoji {
  967. font-size: 28rpx;
  968. }
  969. .info-text {
  970. font-size: 24rpx;
  971. color: #666;
  972. line-height: 1.5;
  973. }
  974. &.warning {
  975. background: rgba(255, 167, 38, 0.1);
  976. .info-text {
  977. color: #F57C00;
  978. }
  979. }
  980. }
  981. }
  982. }
  983. }
  984. @keyframes numberChange {
  985. from {
  986. opacity: 0;
  987. transform: translateY(10rpx);
  988. }
  989. to {
  990. opacity: 1;
  991. transform: translateY(0);
  992. }
  993. }
  994. </style>