Browse Source

首页轮播,通知接口联调,地图药店诊所和办事指南接口联调,位置信息,名称,详情

master
ZhaoYang 14 hours ago
parent
commit
8e4c039cfa
  1. 13
      app.json
  2. 219
      pages/home/home.js
  3. 90
      pages/home/home.wxml
  4. 39
      pages/home/home.wxss
  5. BIN
      pages/images/aiwz.png
  6. BIN
      pages/images/banner1.png
  7. BIN
      pages/images/banner2.png
  8. BIN
      pages/images/banner3.png
  9. BIN
      pages/images/banner4.png
  10. BIN
      pages/images/sc.png
  11. BIN
      pages/images/sc1.png
  12. BIN
      pages/images/sjh.png
  13. 52
      pages/index/index.js
  14. 5
      pages/index/index.json
  15. 28
      pages/index/index.wxml
  16. 63
      pages/index/index.wxss
  17. 189
      pages/login/login.js
  18. 4
      pages/login/login.json
  19. 90
      pages/login/login.wxml
  20. 506
      pages/login/login.wxss
  21. 20
      pages/logs/logs.js
  22. 5
      pages/logs/logs.json
  23. 7
      pages/logs/logs.wxml
  24. 16
      pages/logs/logs.wxss
  25. 162
      pages/map/map.js
  26. 38
      pages/map/map.wxml
  27. 117
      pages/map/map.wxss
  28. 2
      pages/market/market.js
  29. 0
      pages/market/market.json
  30. 2
      pages/market/market.wxml
  31. 1
      pages/market/market.wxss
  32. 346
      pages/personal/personal.js
  33. 149
      pages/personal/personal.wxml
  34. 442
      pages/personal/personal.wxss
  35. 2
      pagesA/pages/socialWork/socialWork.wxml
  36. 1
      pagesA/pages/socialWork/socialWork.wxss
  37. 299
      pagesA/pages/wzai/wzai.js
  38. 5
      pagesA/pages/wzai/wzai.json
  39. 196
      pagesA/pages/wzai/wzai.wxml
  40. 530
      pagesA/pages/wzai/wzai.wxss
  41. 2
      project.config.json
  42. 32
      utils/api.js
  43. 6
      utils/baseUrl.js
  44. 5
      utils/http.js
  45. 19
      utils/tool.wxs

13
app.json

@ -1,15 +1,17 @@
{
"pages": [
"pages/home/home",
"pages/login/login",
"pages/news/news",
"pages/map/map",
"pages/personal/personal"
"pages/personal/personal",
"pages/market/market"
],
"subPackages": [
{
"root": "pagesA",
"pages": [
"pages/socialWork/socialWork"
"pages/wzai/wzai"
]
},
{
@ -21,6 +23,7 @@
}
],
"window": {
"backgroundColor": "#86D8D0",
"navigationBarBackgroundColor": "#86D8D0",
"navigationBarTextStyle": "white"
},
@ -41,6 +44,12 @@
"iconPath": "pages/images/xx.png",
"selectedIconPath": "pages/images/xx1.png"
},
{
"pagePath": "pages/market/market",
"text": "市场",
"iconPath": "pages/images/sc.png",
"selectedIconPath": "pages/images/sc1.png"
},
{
"pagePath": "pages/map/map",
"text": "导航",

219
pages/home/home.js

@ -1,97 +1,81 @@
import http from '../../utils/api'
const baseUr = require('../../utils/baseUrl')
Page({
data: {
// 轮播图数据
currentSwiper: 0,
swiperList: [{
id: 1,
image: '/pages/images/banner1.png',
tag: '疫病防治',
title: '春季牛羊常见病预防指南',
desc: '专业兽医教你科学预防',
isActive: false
},
{
id: 2,
image: '/pages/images/banner2.png',
tag: '专家直播',
title: '畜牧养殖新技术分享会',
desc: '今晚8点准时开播',
isActive: false
},
{
id: 3,
image: '/pages/images/banner3.png',
tag: '市场动态',
title: '最新牛羊肉价格行情',
desc: '实时掌握市场变化',
isActive: false
},
{
id: 4,
image: '/pages/images/banner4.png',
tag: '在线问诊',
title: 'AI智能诊断上线',
desc: '24小时在线解答',
isActive: false
}
],
baseUr: baseUr,
swiperList: [],
// 通知公告数据
currentNotice: 0,
noticeList: [{
id: 1,
type: 'urgent',
typeName: '紧急',
content: '关于春季动物疫病防控的重要通知,请各位牧民及时查看并做好预防工作',
time: '03-15 14:30'
},
{
id: 2,
type: 'important',
typeName: '重要',
content: '兽药购买资质审核流程更新,请相关商家及时上传最新资质文件',
time: '03-14 09:15'
},
{
id: 3,
type: 'normal',
typeName: '通知',
content: '平台将于3月20日进行系统升级,升级期间部分功能可能无法正常使用',
time: '03-13 16:45'
noticeList: [],
},
// 轮播
getCarousel() {
http.carousel({
data: {},
success: res => {
this.setData({
swiperList: res.rows
})
}
})
},
// 灾害
getDisaster() {
http.disaster({
data: {},
success: res => {
console.log(222, res);
this.setData({
noticeList:res.rows
})
}
],
})
},
// AI问诊
bindAI() {
wx.navigateTo({
url: '/pagesA/pages/wzai/wzai',
})
},
//获取当前位置信息
getLocation() {
let that = this;
// 腾讯获取的密钥
let key = 'AOBBZ-6LUK7-WXGXX-HJUXS-HHUM5-FWFPJ'
wx.getLocation({
isHighAccuracy: true,
type: 'gcj02',
success: function (res) {
console.log(res);
let latitude = res.latitude;
let longitude = res.longitude;
wx.request({
url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${key}`,
success: res => {
console.log(res);
that.setData({
county: res.data.result.address_component.district //城市
});
}
})
}
})
},
getLocation() {
let that = this;
// 腾讯获取的密钥
let key = 'AOBBZ-6LUK7-WXGXX-HJUXS-HHUM5-FWFPJ'
wx.getLocation({
isHighAccuracy: true,
type: 'gcj02',
success: function (res) {
console.log(res);
let latitude = res.latitude;
let longitude = res.longitude;
wx.request({
url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${key}`,
success: res => {
console.log(res);
that.setData({
county: res.data.result.address_component.district //城市
});
}
})
}
})
},
onLoad() {
// 初始化数据
this.initSwiperActiveState();
this.getDisaster()
this.getCarousel()
this.getLocation()
},
@ -101,23 +85,11 @@ Page({
// 初始化轮播图激活状态
initSwiperActiveState() {
const swiperList = this.data.swiperList.map((item, index) => ({
...item,
isActive: index === this.data.currentSwiper
}));
this.setData({
swiperList
});
},
// 轮播图变化事件
onSwiperChange(e) {
const current = e.detail.current;
const swiperList = this.data.swiperList.map((item, index) => ({
...item,
isActive: index === current
}));
this.setData({
@ -126,57 +98,18 @@ Page({
});
},
// 轮播图指示器点击
onIndicatorTap(e) {
const index = e.currentTarget.dataset.index;
this.setData({
currentSwiper: index
});
},
// 轮播图点击
onSwiperTap(e) {
const id = e.currentTarget.dataset.id;
const item = this.data.swiperList.find(item => item.id === id);
if (!item) return;
console.log('轮播图点击:', item);
console.log(1111, e);
var item = e.currentTarget.dataset.value
wx.showToast({
title: `进入${item.tag}`,
title: `进入${item.adsType}`,
icon: 'none',
duration: 1000
});
// 根据不同类型跳转不同页面
switch (id) {
case 1:
wx.navigateTo({
url: '/pages/knowledge/detail?id=' + id
});
break;
case 2:
wx.navigateTo({
url: '/pages/live/detail?id=' + id
});
break;
case 3:
wx.navigateTo({
url: '/pages/market/detail?id=' + id
});
break;
case 4:
wx.navigateTo({
url: '/pages/consult/ai'
});
break;
default:
// 默认跳转到详情页
wx.navigateTo({
url: '/pages/detail/index?id=' + id
});
}
},
@ -213,22 +146,22 @@ Page({
},
onReady(){
onReady() {
//当前网络状态
wx.getNetworkType({
success: function (res) { // 返回网络类型, 有效值:// wifi/2g/3g/4g/unknown(Android下不常见的网络类型)/none(无网络)
console.log(res);
var networkType = res.networkType
if (networkType !== 'unknown') {
wx.showToast({
title: '当前使用"' + networkType + '"网络',
icon: 'none',
duration: 1000
})
wx.showToast({
title: '当前使用"' + networkType + '"网络',
icon: 'none',
duration: 1000
})
}
}
})
},
})
},
// 下拉刷新

90
pages/home/home.wxml

@ -1,24 +1,29 @@
<wxs module="tool" src="../../utils/tool.wxs"></wxs>
<view class="home-container">
<view class="box">
<!-- 定位 -->
<view class="orientation">
<image src="/pages/images/dw.png" mode="" />
<view>{{county}}</view>
</view>
<!-- AI问诊 -->
<view class="Aidiagnosis" bind:tap="bindAI">
<image src="/pages/images/aiwz.png" mode=""/>
</view>
<!-- 轮播图区域 -->
<view class="swiper-container">
<swiper class="custom-swiper" indicator-dots="{{false}}" indicator-color="rgba(255,255,255,0.4)" indicator-active-color="#4CAF50" autoplay="{{true}}" interval="5000" duration="500" circular="{{true}}" current="{{currentSwiper}}" bindchange="onSwiperChange" style="height: 360rpx;">
<block wx:for="{{swiperList}}" wx:key="id">
<swiper-item>
<view class="swiper-item {{item.isActive ? 'active' : ''}}" data-id="{{item.id}}" catchtap="onSwiperTap">
<image src="{{item.image}}" class="swiper-image" mode="aspectFill" />
<view class="swiper-item {{item.isActive ? 'active' : ''}}" data-value="{{item}}" catchtap="onSwiperTap">
<image src="{{baseUr+item.imageUrl}}" class="swiper-image" mode="aspectFill" />
<view class="swiper-mask"></view>
<view class="swiper-content">
<text class="swiper-tag">{{item.tag}}</text>
<text class="swiper-tag">{{item.adsType}}</text>
<text class="swiper-title">{{item.title}}</text>
<text class="swiper-desc">{{item.desc}}</text>
<text class="swiper-desc">{{item.subtitle}}</text>
</view>
<view class="swiper-gradient"></view>
</view>
@ -33,38 +38,40 @@
</view>
</view>
<!-- 卡片类型 -->
<view class="card">
<view class="card2">
<view>问兽医</view>
<view class="card2_1">智能匹配医生</view>
<view class="card2_1">平均5分钟恢复</view>
</view>
<view class="card3">
<view class="card3_1 card3_kp">
<view>找专家</view>
<view>智能匹配医生</view>
<view class="kap">
<!-- 卡片类型 -->
<view class="card">
<view class="card2">
<view>问兽医</view>
<view class="card2_1">智能匹配医生</view>
<view class="card2_1">平均5分钟恢复</view>
</view>
<view class="card3_2 card3_kp">
<view>去买药</view>
<view>制定专业的治疗方案</view>
<view class="card3">
<view class="card3_1 card3_kp">
<view>找专家</view>
<view>智能匹配医生</view>
</view>
<view class="card3_2 card3_kp">
<view>去买药</view>
<view>制定专业的治疗方案</view>
</view>
</view>
</view>
</view>
<!-- 知识库 -->
<view class="repository">
<view class="repository1_1 zsk">
<view>养殖知识库</view>
<view>快速查询养殖知识</view>
</view>
<view class="repository1_2 zsk">
<view>在线培训</view>
<view>提高养殖技能</view>
</view>
<view class="repository1_3 zsk">
<view>政策解读</view>
<view>提供政策指导</view>
<!-- 知识库 -->
<view class="repository">
<view class="repository1_1 zsk">
<view>养殖知识库</view>
<view>快速查询养殖知识</view>
</view>
<view class="repository1_2 zsk">
<view>在线培训</view>
<view>提高养殖技能</view>
</view>
<view class="repository1_3 zsk">
<view>政策解读</view>
<view>提供政策指导</view>
</view>
</view>
</view>
@ -76,13 +83,10 @@
<swiper-item>
<view class="notice-item {{index === currentNotice ? 'highlight' : ''}}" data-id="{{item.id}}" catchtap="onNoticeTap">
<view class="notice-item-header">
<text class="notice-type {{item.type}}">{{item.typeName}}</text>
<text class="notice-time">{{item.time}}</text>
</view>
<text class="notice-text">{{item.content}}</text>
<view class="notice-arrow">
<image src="/pages/images/dw.png"></image>
<text class="notice-type {{tool.type(item.warningLevel)}}">{{item.warningLevel}}</text>
<text class="notice-time">{{item.createdTime}}</text>
</view>
<text class="notice-text">{{item.title}}</text>
</view>
</swiper-item>
</block>
@ -102,8 +106,8 @@
查看全部
</view>
</view>
<!-- 问题列表 -->
<view class="question-card placeholder">
<view class="question-meta">
@ -112,7 +116,7 @@
<text class="tag-text">发烧、流鼻涕、越来越瘦是什么原因?应该怎么治疗?</text>
</view>
</view>
<view class="question-info">
<view class="user-info">
<image src="/pages/images/tx.png" class="user-avatar"></image>

39
pages/home/home.wxss

@ -14,6 +14,21 @@
padding-bottom: 40rpx;
}
/* AI问诊 */
.Aidiagnosis {
position: fixed;
right: 0;
bottom: 150px;
margin: 0 auto;
z-index: 100;
}
.Aidiagnosis image {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
/* 定位 */
.orientation {
display: flex;
@ -44,6 +59,7 @@
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
@ -151,6 +167,23 @@
}
/* 卡片类型 */
.kap {
animation: kapIn 0.5s ease-out 0.5s both;
}
@keyframes kapIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.card {
width: 100%;
display: grid;
@ -266,6 +299,7 @@
from {
opacity: 0;
}
to {
opacity: 1;
}
@ -339,6 +373,8 @@
overflow: hidden;
}
/* 用户提问板块 - 优化样式 */
.user-question-section {
background: #FFFFFF;
@ -354,6 +390,7 @@
opacity: 0;
transform: translateY(60rpx);
}
to {
opacity: 1;
transform: translateY(0);
@ -515,4 +552,4 @@
background: rgba(0, 0, 0, 0.04);
padding: 6rpx 16rpx;
border-radius: 16rpx;
}
}

BIN
pages/images/aiwz.png

After

Width: 400  |  Height: 400  |  Size: 27 KiB

BIN
pages/images/banner1.png

Before

Width: 1920  |  Height: 1232  |  Size: 2.1 MiB

BIN
pages/images/banner2.png

Before

Width: 431  |  Height: 232  |  Size: 175 KiB

BIN
pages/images/banner3.png

Before

Width: 600  |  Height: 394  |  Size: 37 KiB

BIN
pages/images/banner4.png

Before

Width: 300  |  Height: 200  |  Size: 21 KiB

BIN
pages/images/sc.png

After

Width: 200  |  Height: 200  |  Size: 3.1 KiB

BIN
pages/images/sc1.png

After

Width: 200  |  Height: 200  |  Size: 3.2 KiB

BIN
pages/images/sjh.png

After

Width: 200  |  Height: 200  |  Size: 4.7 KiB

52
pages/index/index.js

@ -1,52 +0,0 @@
// index.js
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
Component({
data: {
motto: 'Hello World',
userInfo: {
avatarUrl: defaultAvatarUrl,
nickName: '',
},
hasUserInfo: false,
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
},
methods: {
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onChooseAvatar(e) {
const { avatarUrl } = e.detail
const { nickName } = this.data.userInfo
this.setData({
"userInfo.avatarUrl": avatarUrl,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
onInputChange(e) {
const nickName = e.detail.value
const { avatarUrl } = this.data.userInfo
this.setData({
"userInfo.nickName": nickName,
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
})
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
},
})

5
pages/index/index.json

@ -1,5 +0,0 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar"
}
}

28
pages/index/index.wxml

@ -1,28 +0,0 @@
<!--index.wxml-->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list">
<view class="container">
<view class="userinfo">
<block wx:if="{{canIUseNicknameComp && !hasUserInfo}}">
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
<image class="avatar" src="{{userInfo.avatarUrl}}"></image>
</button>
<view class="nickname-wrapper">
<text class="nickname-label">昵称</text>
<input type="nickname" class="nickname-input" placeholder="请输入昵称" bind:change="onInputChange" />
</view>
</block>
<block wx:elif="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<view wx:else> 请使用2.10.4及以上版本基础库 </view>
</block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>
</scroll-view>

63
pages/index/index.wxss

@ -1,63 +0,0 @@
/**index.wxss**/
page {
height: 100vh;
display: flex;
flex-direction: column;
}
.scrollarea {
flex: 1;
overflow-y: hidden;
}
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
color: #aaa;
width: 80%;
}
.userinfo-avatar {
overflow: hidden;
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.usermotto {
margin-top: 200px;
}
.avatar-wrapper {
padding: 0;
width: 56px !important;
border-radius: 8px;
margin-top: 40px;
margin-bottom: 40px;
}
.avatar {
display: block;
width: 56px;
height: 56px;
}
.nickname-wrapper {
display: flex;
width: 100%;
padding: 16px;
box-sizing: border-box;
border-top: .5px solid rgba(0, 0, 0, 0.1);
border-bottom: .5px solid rgba(0, 0, 0, 0.1);
color: black;
}
.nickname-label {
width: 105px;
}
.nickname-input {
flex: 1;
}

189
pages/login/login.js

@ -0,0 +1,189 @@
import http from '../../utils/api'
Page({
data: {
isAgree: true, // 是否同意协议
showAgreementModal: false, // 是否显示协议弹窗
modalTitle: '', // 弹窗标题
modalContent: '', // 弹窗内容
isLoading: false, // 是否显示加载中,
phoneData: {},
},
onLoad() {
this.login()
},
// 登录获取
login() {
// 小程序接口
var that = this
wx.login({
success(res) {
//登录接口
http.login({
data: {
code: res.code,
clientType: 'herdsman-app'
},
success: function (res) {
if (res.data) {
that.setData({
phoneData: res.data
})
wx.showToast({
title: res.data.message,
icon: 'none',
duration: 2000
});
}
if (res.token) {
wx.setStorageSync('token', res.token)
wx.switchTab({
url: '/pages/home/home'
});
}
},
})
},
fail: (error) => {
console.log('登录失败!' + error);
}
})
},
// 获取用户手机号
getPhoneNumber(e) {
if (!this.data.isAgree) {
wx.showToast({
title: '请先同意协议',
icon: 'none',
duration: 2000
});
return;
}
// 显示加载中
this.setData({
isLoading: true
});
// 检查是否获取到手机号
if (e.detail.errMsg === "getPhoneNumber:ok") {
// 这里应该将加密数据发送到后端进行解密
this.data.phoneData.encryptedData = e.detail.encryptedData
this.data.phoneData.iv = e.detail.iv
http.getPhoneNumber({
data: this.data.phoneData,
success: res => {
if (res.code == 200) {
wx.setStorageSync('token', res.token)
setTimeout(() => {
wx.switchTab({
url: '/pages/home/home'
});
}, 1500);
this.setData({
isLoading: false
})
wx.showToast({
title: '登录成功',
icon: 'success',
duration: 2000
});
}
}
})
} else {
// 用户拒绝授权
this.setData({
isLoading: false
});
wx.showToast({
title: '需要手机号授权才能登录',
icon: 'none',
duration: 2000
});
}
},
// 切换协议同意状态
toggleAgreement() {
this.setData({
isAgree: !this.data.isAgree
});
},
// 显示用户协议
showAgreement() {
const content = `欢迎您使用与牧同行服务!
服务说明
与牧同行为您提供智慧放牧管理牲畜追踪草场监测等服务通过我们的平台您可以更高效地管理牧场资源提升放牧效率
账号注册
1. 您需要使用手机号完成注册
2. 您应保证提供的信息真实准确完整
3. 您对账号安全负全部责任
使用规范
1. 不得利用本服务从事任何违法违规活动
2. 不得干扰或破坏本服务的正常运行
3. 遵守相关法律法规和平台规则
服务变更与终止
我们可能根据需要变更服务内容如您不同意变更可停止使用本服务
免责声明
对于不可抗力网络问题等导致的服务中断我们不承担相应责任
法律适用
本协议受中华人民共和国法律管辖
感谢您选择与牧同行`;
this.setData({
showAgreementModal: true,
modalTitle: '用户协议',
modalContent: content
});
},
// 显示隐私政策
showPrivacy() {
const content = `与牧同行隐私政策
我们深知个人信息对您的重要性并会尽全力保护您的个人信息安全可靠我们致力于维持您对我们的信任恪守以下原则保护您的个人信息权责一致原则目的明确原则选择同意原则最少够用原则确保安全原则主体参与原则公开透明原则等
我们如何收集和使用您的个人信息
我们仅会出于本政策所述的以下目的收集和使用您的个人信息
1. 账号注册手机号
2. 服务提供位置信息设备信息
3. 安全保障登录日志操作记录
我们如何共享转让公开披露您的个人信息
1. 我们不会与任何公司组织和个人共享您的个人信息
2. 我们不会将您的个人信息转让给任何公司组织和个人
3. 我们仅会在法律要求的情况下公开披露您的个人信息
我们如何保护您的个人信息
1. 我们已使用符合业界标准的安全防护措施保护您提供的个人信息
2. 我们会采取合理可行的措施确保未收集无关的个人信息
您的权利
您有权访问更正删除您的个人信息以及改变您授权同意的范围或撤回授权
我们如何处理儿童的个人信息
我们的服务主要面向成人如果没有父母或监护人的同意儿童不应创建自己的个人信息主体账户
本政策如何更新
我们可能适时修订本政策内容并通过公告等方式通知您
如有任何疑问请通过客服渠道联系我们`;
this.setData({
showAgreementModal: true,
modalTitle: '隐私政策',
modalContent: content
});
},
// 隐藏弹窗
hideModal() {
this.setData({
showAgreementModal: false
});
}
})

4
pages/login/login.json

@ -0,0 +1,4 @@
{
"navigationBarTitleText":"登录",
"usingComponents": {}
}

90
pages/login/login.wxml

@ -0,0 +1,90 @@
<view class="login-container">
<!-- 顶部波浪背景 -->
<view class="wave-background">
<view class="wave wave-1"></view>
<view class="wave wave-2"></view>
<view class="wave wave-3"></view>
</view>
<!-- 装饰元素 -->
<view class="decorations">
<view class="cloud cloud-1"></view>
<view class="cloud cloud-2"></view>
<view class="cloud cloud-3"></view>
<view class="grass grass-1"></view>
<view class="grass grass-2"></view>
<view class="grass grass-3"></view>
<view class="sheep"></view>
</view>
<!-- 主要内容区域 -->
<view class="main-content">
<!-- Logo区域 -->
<view class="logo-section">
<view class="logo-container">
<view class="logo-circle">
<view class="logo-inner">
<text class="logo-text">牧</text>
</view>
</view>
</view>
<text class="app-title">与牧同行</text>
</view>
<!-- 登录区域 -->
<view class="login-section">
<view class="welcome-text">
<text class="welcome-main">欢迎回来</text>
<text class="welcome-desc">请使用手机号快捷登录</text>
</view>
<!-- 手机号登录按钮 -->
<button class="phone-login-btn" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" hover-class="phone-btn-hover">
<view class="btn-inner">
<image src="/pages/images/sjh.png" mode="" />
<text class="btn-text">手机号快捷登录</text>
</view>
</button>
<!-- 协议确认 -->
<view class="agreement-section">
<view class="agreement-checkbox {{isAgree ? 'checked' : ''}}" bindtap="toggleAgreement">
<text class="checkmark" wx:if="{{isAgree}}">✓</text>
</view>
<view class="agreement-text">
我已阅读并同意
<view class="link" bindtap="showAgreement">《用户协议》</view>
<view class="link" bindtap="showPrivacy">《隐私政策》</view>
</view>
</view>
</view>
</view>
<!-- 底部装饰 -->
<view class="bottom-decor">
<view class="bottom-wave"></view>
</view>
<!-- 协议弹窗 -->
<view class="agreement-modal" wx:if="{{showAgreementModal}}">
<view class="modal-mask" bindtap="hideModal"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">{{modalTitle}}</text>
<view class="modal-close" bindtap="hideModal">×</view>
</view>
<scroll-view class="modal-body" scroll-y>
<text class="modal-text">{{modalContent}}</text>
</scroll-view>
</view>
</view>
<!-- 加载提示 -->
<view class="loading-mask" wx:if="{{isLoading}}">
<view class="loading-content">
<view class="loading-spinner"></view>
<text class="loading-text">登录中...</text>
</view>
</view>
</view>

506
pages/login/login.wxss

@ -0,0 +1,506 @@
/* pages/login/login.wxss */
.login-container {
height: 100vh;
width: 100%;
position: relative;
overflow: hidden;
background: linear-gradient(180deg, #f8fafc 0%, #f0f9ff 100%);
}
/* 波浪背景 */
.wave-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 400rpx;
overflow: hidden;
}
.wave {
position: absolute;
bottom: 0;
width: 200%;
height: 100%;
background: linear-gradient(90deg, #86D8D0 0%, #A8E6CF 100%);
border-radius: 0 0 50% 50%;
animation: waveMove 15s linear infinite;
}
.wave-1 {
opacity: 0.7;
animation-delay: 0s;
}
.wave-2 {
opacity: 0.5;
animation-delay: 5s;
background: linear-gradient(90deg, #7ACCC4 0%, #98D6C6 100%);
}
.wave-3 {
opacity: 0.3;
animation-delay: 10s;
background: linear-gradient(90deg, #6EC0B8 0%, #88C6BD 100%);
}
@keyframes waveMove {
0% {
transform: translateX(0) rotate(0deg);
}
50% {
transform: translateX(-25%) rotate(1deg);
}
100% {
transform: translateX(-50%) rotate(0deg);
}
}
/* 装饰元素 */
.decorations {
position: absolute;
width: 100%;
height: 100%;
pointer-events: none;
}
.cloud {
position: absolute;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 100rpx;
}
.cloud-1 {
width: 120rpx;
height: 40rpx;
top: 120rpx;
left: 10%;
box-shadow:
20rpx 0 0 0 rgba(255, 255, 255, 0.9),
40rpx 0 0 0 rgba(255, 255, 255, 0.9);
}
.cloud-2 {
width: 90rpx;
height: 30rpx;
top: 80rpx;
right: 15%;
box-shadow:
15rpx 0 0 0 rgba(255, 255, 255, 0.9),
30rpx 0 0 0 rgba(255, 255, 255, 0.9);
}
.cloud-3 {
width: 70rpx;
height: 25rpx;
top: 180rpx;
left: 70%;
box-shadow:
12rpx 0 0 0 rgba(255, 255, 255, 0.9),
24rpx 0 0 0 rgba(255, 255, 255, 0.9);
}
.grass {
position: absolute;
bottom: 0;
width: 8rpx;
background-color: #86D8D0;
border-radius: 4rpx 4rpx 0 0;
}
.grass-1 {
height: 80rpx;
left: 20%;
}
.grass-2 {
height: 60rpx;
left: 35%;
}
.grass-3 {
height: 100rpx;
left: 50%;
}
.grass:before,
.grass:after {
content: '';
position: absolute;
width: 8rpx;
background-color: #86D8D0;
border-radius: 4rpx;
}
.grass:before {
height: 40rpx;
transform: rotate(-30deg);
top: -20rpx;
left: -10rpx;
}
.grass:after {
height: 30rpx;
transform: rotate(30deg);
top: -15rpx;
right: -10rpx;
}
.sheep {
position: absolute;
bottom: 120rpx;
right: 20%;
width: 80rpx;
height: 50rpx;
background-color: white;
border-radius: 50%;
box-shadow:
-15rpx -10rpx 0 0 white,
15rpx -8rpx 0 0 white;
}
.sheep:before {
content: '';
position: absolute;
width: 20rpx;
height: 20rpx;
background-color: #333;
border-radius: 50%;
top: -5rpx;
left: 15rpx;
}
/* 主要内容区域 */
.main-content {
position: relative;
z-index: 10;
height: 100%;
display: flex;
flex-direction: column;
padding: 0 60rpx;
padding-top: 120rpx;
}
/* Logo区域 */
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 120rpx;
}
.logo-container {
margin-bottom: 40rpx;
}
.logo-circle {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
background: linear-gradient(135deg, #86D8D0 0%, #6BC4BC 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow:
0 20rpx 40rpx rgba(134, 216, 208, 0.3),
inset 0 -4rpx 8rpx rgba(107, 196, 188, 0.4),
inset 0 4rpx 8rpx rgba(255, 255, 255, 0.8);
position: relative;
}
.logo-circle:before {
content: '';
position: absolute;
width: 160rpx;
height: 160rpx;
border-radius: 50%;
border: 2rpx solid rgba(255, 255, 255, 0.3);
}
.logo-inner {
width: 140rpx;
height: 140rpx;
border-radius: 50%;
background: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow:
inset 0 4rpx 8rpx rgba(134, 216, 208, 0.2),
0 4rpx 8rpx rgba(0, 0, 0, 0.1);
}
.logo-text {
font-size: 64rpx;
font-weight: bold;
color: #86D8D0;
letter-spacing: 4rpx;
}
.app-title {
font-size: 56rpx;
font-weight: 700;
color: #333;
margin-bottom: 16rpx;
letter-spacing: 2rpx;
}
/* 登录区域 */
.login-section {
display: flex;
flex-direction: column;
align-items: center;
}
.welcome-text {
text-align: center;
margin-bottom: 80rpx;
}
.welcome-main {
display: block;
font-size: 44rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
}
.welcome-desc {
display: block;
font-size: 28rpx;
color: #888;
font-weight: 300;
}
/* 手机号登录按钮 */
.phone-login-btn {
width: 100%;
height: 100rpx;
border-radius: 50rpx;
background: linear-gradient(to right, #86D8D0, #6BC4BC);
box-shadow:
0 12rpx 24rpx rgba(134, 216, 208, 0.3),
0 4rpx 12rpx rgba(0, 0, 0, 0.08);
margin-bottom: 50rpx;
transition: all 0.3s ease;
}
.phone-btn-hover {
transform: translateY(-4rpx);
box-shadow:
0 16rpx 32rpx rgba(134, 216, 208, 0.4),
0 6rpx 16rpx rgba(0, 0, 0, 0.12);
}
.btn-inner {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.btn-inner image {
width: 45rpx;
height: 45rpx;
padding: 0 20rpx;
}
.btn-text {
color: white;
font-size: 34rpx;
font-weight: 500;
letter-spacing: 2rpx;
}
/* 协议确认 */
.agreement-section {
display: flex;
align-items: center;
justify-content: center;
}
.agreement-checkbox {
width: 30rpx;
height: 30rpx;
border: 2rpx solid #ccc;
border-radius: 6rpx;
margin-right: 16rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.agreement-checkbox.checked {
background-color: #86D8D0;
border-color: #86D8D0;
}
.checkmark {
color: white;
font-size: 24rpx;
font-weight: bold;
}
.agreement-text {
font-size: 24rpx;
color: #888;
display: flex;
align-items: center;
}
.link {
color: #86D8D0;
}
/* 底部装饰 */
.bottom-decor {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 60rpx;
overflow: hidden;
}
.bottom-wave {
position: absolute;
top: 0;
left: 0;
width: 200%;
height: 200%;
background: linear-gradient(90deg, #86D8D0 0%, #A8E6CF 100%);
border-radius: 50% 50% 0 0;
animation: bottomWave 20s linear infinite;
}
@keyframes bottomWave {
0% {
transform: translateX(0) rotate(0deg);
}
50% {
transform: translateX(-25%) rotate(0.5deg);
}
100% {
transform: translateX(-50%) rotate(0deg);
}
}
/* 协议弹窗 */
.agreement-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: relative;
width: 85%;
max-height: 80%;
background-color: white;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.15);
}
.modal-header {
padding: 40rpx;
border-bottom: 1rpx solid #f0f0f0;
display: flex;
align-items: center;
justify-content: space-between;
}
.modal-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
.modal-close {
font-size: 48rpx;
color: #999;
line-height: 1;
}
.modal-body {
max-height: 600rpx;
padding: 20rpx;
box-sizing: border-box;
}
.modal-text {
font-size: 28rpx;
color: #666;
line-height: 1.8;
padding: 20rpx 0;
}
/* 加载提示 */
.loading-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1001;
display: flex;
align-items: center;
justify-content: center;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
}
.loading-spinner {
width: 80rpx;
height: 80rpx;
border: 6rpx solid rgba(134, 216, 208, 0.2);
border-top-color: #86D8D0;
border-radius: 50%;
animation: loadingSpin 1s linear infinite;
margin-bottom: 30rpx;
}
@keyframes loadingSpin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-text {
font-size: 28rpx;
color: #fff;
font-weight: 300;
}

20
pages/logs/logs.js

@ -1,20 +0,0 @@
// logs.js
const util = require('../../utils/util.js')
Component({
data: {
logs: []
},
lifetimes: {
attached() {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(log => {
return {
date: util.formatTime(new Date(log)),
timeStamp: log
}
})
})
}
},
})

5
pages/logs/logs.json

@ -1,5 +0,0 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar"
}
}

7
pages/logs/logs.wxml

@ -1,7 +0,0 @@
<!--logs.wxml-->
<navigation-bar title="查看启动日志" back="{{true}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list">
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
<view class="log-item">{{index + 1}}. {{log.date}}</view>
</block>
</scroll-view>

16
pages/logs/logs.wxss

@ -1,16 +0,0 @@
page {
height: 100vh;
display: flex;
flex-direction: column;
}
.scrollarea {
flex: 1;
overflow-y: hidden;
}
.log-item {
margin-top: 20rpx;
text-align: center;
}
.log-item:last-child {
padding-bottom: env(safe-area-inset-bottom);
}

162
pages/map/map.js

@ -1,15 +1,18 @@
// pages/map/map.js
import http from '../../utils/api'
const baseUr = require('../../utils/baseUrl')
Page({
/**
* 页面的初始数据
*/
data: {
markers: {
longitude: null,
latitude: null
},
activeTab: '',
longitude: null,
latitude: null,
markers: [],
activeTab: 'clinic',
baseUr: baseUr,
showDetail: false,
currentMarker: null
},
@ -17,16 +20,133 @@ Page({
switchTab(e) {
const tab = e.currentTarget.dataset.tab;
this.setData({
activeTab: tab
activeTab: tab,
showDetail: false // 切换标签时关闭详情
});
// 这里可以添加切换标签后的逻辑
if (tab === 'clinic') {
// 药店诊所相关操作
console.log('切换到药店诊所');
http.pharmacy({
data: {},
success: res => {
console.log(111, res);
this.setData({
markers: res.rows.map((point, index) => ({
id: point.id,
title: point.title,
latitude: point.latitude,
longitude: point.longitude,
iconPath: point.iconPath ? baseUr + point.iconPath : '/pages/images/dw.png',
width: 35,
height: 35,
// 添加气泡标签显示名称
callout: {
content: point.title,
color: '#333',
fontSize: 12,
borderRadius: 4,
bgColor: '#ffffff',
padding: 4,
display: 'ALWAYS'
},
// 保存详细信息
merchantType: point.merchantType,
region: point.region,
address: point.address
}))
})
// 调整地图视野以显示所有标记
if (res.rows.length > 0) {
this.adjustMapView(res.rows);
}
}
})
} else if (tab === 'guide') {
// 办事指南相关操作
console.log('切换到办事指南');
http.guidance({
data: {},
success: res => {
console.log(222, res);
// 清除地图标记
this.setData({
markers: []
});
}
})
}
},
// 调整地图视野以显示所有标记点
adjustMapView(points) {
const mapContext = wx.createMapContext('myMap', this);
if (points && points.length > 0) {
// 将点转换为地图需要的格式
const mapPoints = points.map(point => ({
latitude: point.latitude,
longitude: point.longitude
}));
// 如果有当前位置,也包含在内
if (this.data.latitude && this.data.longitude) {
mapPoints.push({
latitude: this.data.latitude,
longitude: this.data.longitude
});
}
// 调整地图视野
mapContext.includePoints({
points: mapPoints,
padding: [60, 60, 60, 60]
});
}
},
// 地图标记点击事件
onMarkerTap(e) {
const markerId = e.markerId;
const marker = this.data.markers.find(m => m.id === markerId);
if (marker) {
this.setData({
showDetail: true,
currentMarker: {
title: marker.title,
merchantType: marker.merchantType,
region: marker.region,
address: marker.address,
latitude: marker.latitude,
longitude: marker.longitude
}
});
}
},
// 关闭详情
closeDetail() {
this.setData({
showDetail: false,
currentMarker: null
});
},
// 导航到标记点
navigateToMarker() {
if (this.data.currentMarker) {
const { latitude, longitude, title, address } = this.data.currentMarker;
wx.openLocation({
latitude: latitude,
longitude: longitude,
name: title,
address: address,
scale: 18
});
}
},
@ -38,29 +158,21 @@ Page({
type: 'gcj02',
success: function (res) {
console.log(res);
const latitude = res.latitude;
const longitude = res.longitude;
that.setData({
['markers.longitude']: res.longitude,
['markers.latitude']: res.latitude
})
latitude: latitude,
longitude: longitude
});
// 加载初始数据
that.switchTab({ currentTarget: { dataset: { tab: 'clinic' } } });
}
})
},
// 地图
getMap() {
wx.chooseLocation({
success: res => {
console.log(111, res);
this.setData({
['markers.longitude']: res.longitude,
['markers.latitude']: res.latitude
})
}
})
},
/**
* 生命周期函数--监听页面加载
@ -87,7 +199,9 @@ Page({
* 生命周期函数--监听页面隐藏
*/
onHide() {
this.setData({
showDetail: false
});
},
/**

38
pages/map/map.wxml

@ -22,11 +22,43 @@
<map
id="myMap"
enable-zoom
longitude="{{markers.longitude}}"
latitude="{{markers.latitude}}"
latitude="{{latitude}}"
longitude="{{longitude}}"
enable-3D="{{true}}"
scale="16"
markers="{{[markers]}}"
markers="{{markers}}"
show-location="{{true}}"
enable-building="{{true}}"
bindmarkertap="onMarkerTap"
></map>
<!-- 详情信息卡片 - 添加在地图容器内部 -->
<view class="marker-detail-card" wx:if="{{showDetail}}">
<view class="detail-header">
<text class="detail-title">{{currentMarker.title}}</text>
<text class="detail-close" bindtap="closeDetail">✕</text>
</view>
<view class="detail-info">
<view class="info-item">
<text class="info-label">类型:</text>
<text class="info-value">{{currentMarker.merchantType}}</text>
</view>
<view class="info-item">
<text class="info-label">地区:</text>
<text class="info-value">{{currentMarker.region}}</text>
</view>
<view class="info-item">
<text class="info-label">地址:</text>
<text class="info-value">{{currentMarker.address}}</text>
</view>
<view class="info-item">
<text class="info-label">坐标:</text>
<text class="info-value">{{currentMarker.latitude}}, {{currentMarker.longitude}}</text>
</view>
</view>
<view class="detail-actions">
<button class="action-btn" bindtap="navigateToMarker">导航前往</button>
</view>
</view>
</view>
</view>

117
pages/map/map.wxss

@ -124,6 +124,123 @@
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
color: white;
}
/* 地图详情卡片样式 - 添加在地图容器内部 */
.marker-detail-card {
position: absolute;
bottom: 30rpx;
left: 50%;
transform: translateX(-50%);
width: 90%;
background: rgba(255, 255, 255, 0.95);
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
z-index: 100;
backdrop-filter: blur(10rpx);
border: 1rpx solid rgba(255, 255, 255, 0.2);
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
transform: translateX(-50%) translateY(100%);
opacity: 0;
}
to {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
}
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
padding-bottom: 16rpx;
}
.detail-title {
font-size: 30rpx;
font-weight: 600;
color: #333;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 16rpx;
}
.detail-close {
font-size: 32rpx;
color: #999;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
cursor: pointer;
transition: background-color 0.2s;
}
.detail-close:active {
background-color: #f5f5f5;
}
.detail-info {
margin-bottom: 20rpx;
}
.info-item {
display: flex;
margin-bottom: 12rpx;
line-height: 1.4;
}
.info-item:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 26rpx;
color: #666;
width: 100rpx;
flex-shrink: 0;
}
.info-value {
font-size: 26rpx;
color: #333;
flex: 1;
}
.detail-actions {
display: flex;
justify-content: center;
}
.action-btn {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
color: white;
border: none;
border-radius: 8rpx;
padding: 16rpx 40rpx;
font-size: 28rpx;
font-weight: 500;
transition: transform 0.2s;
box-shadow: 0 4rpx 12rpx rgba(106, 17, 203, 0.2);
}
.action-btn::after {
border: none;
}
.action-btn:active {
transform: scale(0.95);
}

pagesA/pages/socialWork/socialWork.js → pages/market/market.js

pagesA/pages/socialWork/socialWork.json → pages/market/market.json

2
pages/market/market.wxml

@ -0,0 +1,2 @@
<!--pages/market/market.wxml-->
<text>pages/market/market.wxml</text>

1
pages/market/market.wxss

@ -0,0 +1 @@
/* pages/market/market.wxss */

346
pages/personal/personal.js

@ -1,66 +1,330 @@
// pages/personal/personal.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
userInfo: {
avatar: '/assets/images/avatar.png',
nickname: '用户昵称',
phone: '138****8888',
isVerified: false,
isDoctor: false
},
// 功能模块
modules: [
{
id: 'info',
icon: 'user-circle',
name: '个人管理',
items: [
{
id: 'profile',
name: '信息管理',
desc: '查看和编辑个人信息',
icon: 'profile',
badge: 0,
arrow: true
},
{
id: 'realname',
name: '实名认证',
desc: '通过输入身份信息',
icon: 'shield-check',
badge: 0,
arrow: true,
status: '未认证', // 认证状态
statusColor: 'text-orange'
}
]
},
{
id: 'security',
icon: 'lock',
name: '账户安全',
items: [
{
id: 'security_settings',
name: '账户安全',
desc: '设置账户密码和安全问题',
icon: 'settings',
badge: 0,
arrow: true
},
{
id: 'feedback',
name: '反馈建议',
desc: '向平台提交反馈和建议',
icon: 'message',
badge: 3, // 未读回复数
arrow: true
}
]
},
{
id: 'notification',
icon: 'bell',
name: '消息通知',
items: [
{
id: 'notifications',
name: '消息通知',
desc: '问诊、问答、订单等消息',
icon: 'notification',
badge: 5, // 未读消息数
arrow: true
},
{
id: 'privacy',
name: '隐私设置',
desc: '管理个人信息可见性',
icon: 'eye-off',
badge: 0,
arrow: true
}
]
},
{
id: 'support',
icon: 'help-circle',
name: '帮助与支持',
items: [
{
id: 'about',
name: '关于我们',
desc: '了解平台信息',
icon: 'info',
badge: 0,
arrow: true
},
{
id: 'service',
name: '客服中心',
desc: '7x24小时在线服务',
icon: 'headphones',
badge: 0,
arrow: true
},
{
id: 'agreement',
name: '用户协议',
desc: '查看平台使用条款',
icon: 'file-text',
badge: 0,
arrow: true
}
]
}
],
// 统计数据
stats: [
{
id: 'consultation',
name: '我的问诊',
value: '12',
icon: 'stethoscope',
color: '#07c160'
},
{
id: 'orders',
name: '我的订单',
value: '8',
icon: 'shopping-bag',
color: '#ff6b6b'
},
{
id: 'favorites',
name: '我的收藏',
value: '23',
icon: 'heart',
color: '#ff9f43'
},
{
id: 'coupons',
name: '我的优惠券',
value: '3',
icon: 'tag',
color: '#2e86de'
}
],
// 快捷操作
quickActions: [
{
id: 'health_record',
name: '健康档案',
icon: 'file-medical',
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
},
{
id: 'appointment',
name: '预约挂号',
icon: 'calendar',
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)'
},
{
id: 'medicine',
name: '我的药箱',
icon: 'pill',
color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)'
},
{
id: 'report',
name: '检查报告',
icon: 'clipboard',
color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)'
}
],
// 系统信息
systemInfo: {
version: '2.1.0',
lastLogin: '2024-01-15 14:30'
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
onLoad() {
this.loadUserInfo()
this.checkNotifications()
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
// 每次显示页面时刷新数据
this.refreshData()
},
// 加载用户信息
loadUserInfo() {
// 模拟API调用
setTimeout(() => {
this.setData({
'userInfo.nickname': '张小凡',
'userInfo.phone': '138****5678',
'userInfo.isVerified': true,
'userInfo.isDoctor': false
})
}, 500)
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
// 检查通知
checkNotifications() {
// 模拟检查未读消息
const updatedModules = this.data.modules.map(module => {
return {
...module,
items: module.items.map(item => {
if (item.id === 'notifications') {
return { ...item, badge: Math.floor(Math.random() * 10) }
}
return item
})
}
})
this.setData({ modules: updatedModules })
},
// 刷新数据
refreshData() {
// 刷新统计数据
const updatedStats = this.data.stats.map(stat => ({
...stat,
value: String(Math.floor(Math.random() * 20) + 5)
}))
this.setData({ stats: updatedStats })
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
// 点击用户头像区域
onTapUserInfo() {
wx.navigateTo({
url: '/pages/profile/edit-profile'
})
},
// 点击统计项
onTapStat(e) {
const { id } = e.currentTarget.dataset
const urls = {
consultation: '/pages/consultation/my-consultation',
orders: '/pages/order/my-orders',
favorites: '/pages/favorites/favorites',
coupons: '/pages/coupon/my-coupons'
}
if (urls[id]) {
wx.navigateTo({ url: urls[id] })
}
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
// 点击快捷操作
onTapQuickAction(e) {
const { id } = e.currentTarget.dataset
const urls = {
health_record: '/pages/health/record',
appointment: '/pages/appointment/list',
medicine: '/pages/medicine/medicine-box',
report: '/pages/report/list'
}
if (urls[id]) {
wx.navigateTo({ url: urls[id] })
}
},
// 点击功能项
onTapMenuItem(e) {
const { moduleid, itemid } = e.currentTarget.dataset
console.log('点击:', moduleid, itemid)
// 根据不同的itemid跳转到不同页面
const pageMap = {
profile: '/pages/profile/edit-profile',
realname: '/pages/auth/realname-auth',
security_settings: '/pages/security/settings',
feedback: '/pages/feedback/feedback',
notifications: '/pages/notification/notification-center',
privacy: '/pages/privacy/settings',
about: '/pages/about/about',
service: '/pages/service/customer-service',
agreement: '/pages/agreement/user-agreement'
}
if (pageMap[itemid]) {
wx.navigateTo({ url: pageMap[itemid] })
}
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
// 设置
onTapSettings() {
wx.navigateTo({
url: '/pages/settings/settings'
})
},
// 退出登录
onLogout() {
wx.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
// 清除登录状态
wx.removeStorageSync('token')
wx.removeStorageSync('userInfo')
// 跳转到登录页
wx.reLaunch({
url: '/pages/login/login'
})
}
}
})
},
/**
* 用户点击右上角分享
*/
// 分享
onShareAppMessage() {
return {
title: '健康管理,从这里开始',
path: '/pages/index/index'
}
}
})

149
pages/personal/personal.wxml

@ -1,2 +1,147 @@
<!--pages/personal/personal.wxml-->
<text>pages/personal/personal.wxml</text>
<view class="personal-center">
<!-- 顶部背景 -->
<view class="header-bg"></view>
<!-- 用户信息卡片 -->
<view class="user-card" bindtap="onTapUserInfo">
<view class="user-info">
<view class="avatar-section">
<image class="avatar" src="{{userInfo.avatar || '/assets/images/avatar-default.png'}}" mode="aspectFill"></image>
<view class="avatar-badge" wx:if="{{userInfo.isVerified}}">
<text class="iconfont icon-check-circle"></text>
</view>
</view>
<view class="user-details">
<view class="user-name">
<text class="name">{{userInfo.nickname || '点击登录'}}</text>
<text class="iconfont icon-edit" wx:if="{{userInfo.nickname}}"></text>
</view>
<view class="user-phone">
<text class="iconfont icon-phone"></text>
<text>{{userInfo.phone || '未绑定手机号'}}</text>
</view>
<view class="user-tags">
<view class="tag" wx:if="{{userInfo.isDoctor}}">
<text class="iconfont icon-stethoscope"></text>
<text>医生认证</text>
</view>
<view class="tag" wx:if="{{userInfo.isVerified}}">
<text class="iconfont icon-shield-check"></text>
<text>已实名</text>
</view>
</view>
</view>
</view>
<view class="card-arrow">
<text class="iconfont icon-chevron-right"></text>
</view>
</view>
<!-- 统计数据 -->
<view class="stats-grid">
<view
wx:for="{{stats}}"
wx:key="id"
class="stat-item"
bindtap="onTapStat"
data-id="{{item.id}}"
>
<view class="stat-icon" style="color: {{item.color}};">
<text class="iconfont icon-{{item.icon}}"></text>
</view>
<view class="stat-value">{{item.value}}</view>
<view class="stat-name">{{item.name}}</view>
</view>
</view>
<!-- 快捷操作 -->
<view class="quick-actions">
<view class="section-title">
<text class="iconfont icon-zap"></text>
<text>快捷操作</text>
</view>
<view class="actions-grid">
<view
wx:for="{{quickActions}}"
wx:key="id"
class="action-item"
bindtap="onTapQuickAction"
data-id="{{item.id}}"
>
<view class="action-icon" style="background: {{item.color}};">
<text class="iconfont icon-{{item.icon}}"></text>
</view>
<view class="action-name">{{item.name}}</view>
</view>
</view>
</view>
<!-- 功能模块 -->
<view class="modules">
<block wx:for="{{modules}}" wx:key="id">
<view class="module-section">
<view class="section-title">
<text class="iconfont icon-{{item.icon}}"></text>
<text>{{item.name}}</text>
</view>
<view class="module-items">
<view
wx:for="{{item.items}}"
wx:key="id"
class="module-item"
bindtap="onTapMenuItem"
data-moduleid="{{moduleId}}"
data-itemid="{{item.id}}"
>
<view class="item-left">
<view class="item-icon">
<text class="iconfont icon-{{item.icon}}"></text>
</view>
<view class="item-info">
<view class="item-name">{{item.name}}</view>
<view class="item-desc">{{item.desc}}</view>
<view
class="item-status {{item.statusColor || ''}}"
wx:if="{{item.status}}"
>
{{item.status}}
</view>
</view>
</view>
<view class="item-right">
<view class="badge" wx:if="{{item.badge > 0}}">
{{item.badge > 99 ? '99+' : item.badge}}
</view>
<text class="iconfont icon-chevron-right" wx:if="{{item.arrow}}"></text>
</view>
</view>
</view>
</view>
</block>
</view>
<!-- 底部操作 -->
<view class="bottom-actions">
<view class="system-info">
<text>版本 {{systemInfo.version}}</text>
<text>最后登录 {{systemInfo.lastLogin}}</text>
</view>
<view class="action-buttons">
<button class="btn btn-setting" bindtap="onTapSettings">
<text class="iconfont icon-settings"></text>
<text>设置</text>
</button>
<button class="btn btn-logout" bindtap="onLogout">
<text class="iconfont icon-log-out"></text>
<text>退出登录</text>
</button>
</view>
</view>
</view>

442
pages/personal/personal.wxss

@ -1 +1,441 @@
/* pages/personal/personal.wxss */
.personal-center {
min-height: 100vh;
background: linear-gradient(to bottom, #f5f7fa 0%, #e4e8f0 100%);
padding-bottom: 120rpx;
}
/* 顶部背景 */
.header-bg {
height: 300rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 1;
border-radius: 0 0 40rpx 40rpx;
}
/* 用户信息卡片 */
.user-card {
position: relative;
z-index: 2;
background: white;
margin: 40rpx;
border-radius: 24rpx;
padding: 40rpx;
box-shadow: 0 10rpx 30rpx rgba(102, 126, 234, 0.15);
display: flex;
align-items: center;
justify-content: space-between;
animation: slideUp 0.6s ease;
}
.user-info {
display: flex;
align-items: center;
flex: 1;
}
.avatar-section {
position: relative;
margin-right: 30rpx;
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
border: 6rpx solid white;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
}
.avatar-badge {
position: absolute;
bottom: 0;
right: 0;
background: #07c160;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 3rpx solid white;
}
.avatar-badge .iconfont {
color: white;
font-size: 20rpx;
}
.user-details {
flex: 1;
}
.user-name {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
.user-name .name {
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-right: 15rpx;
}
.user-name .iconfont {
color: #667eea;
font-size: 28rpx;
}
.user-phone {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666;
margin-bottom: 15rpx;
}
.user-phone .iconfont {
margin-right: 10rpx;
font-size: 24rpx;
}
.user-tags {
display: flex;
gap: 15rpx;
}
.user-tags .tag {
background: rgba(102, 126, 234, 0.1);
padding: 6rpx 15rpx;
border-radius: 20rpx;
font-size: 22rpx;
color: #667eea;
display: flex;
align-items: center;
}
.user-tags .tag .iconfont {
font-size: 20rpx;
margin-right: 5rpx;
}
.card-arrow .iconfont {
color: #ccc;
font-size: 32rpx;
}
/* 统计数据 */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
margin: 30rpx 40rpx;
animation: fadeIn 0.8s ease 0.2s both;
}
.stat-item {
background: white;
border-radius: 20rpx;
padding: 30rpx 0;
text-align: center;
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.stat-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: var(--item-color);
opacity: 0;
transition: opacity 0.3s ease;
}
.stat-item:active {
transform: translateY(-5rpx);
box-shadow: 0 10rpx 25rpx rgba(0, 0, 0, 0.1);
}
.stat-item:active::before {
opacity: 1;
}
.stat-icon .iconfont {
font-size: 44rpx;
margin-bottom: 15rpx;
display: block;
}
.stat-value {
font-size: 36rpx;
font-weight: 700;
color: #333;
margin-bottom: 5rpx;
}
.stat-name {
font-size: 24rpx;
color: #999;
}
/* 快捷操作 */
.quick-actions {
margin: 30rpx 40rpx;
animation: fadeIn 0.8s ease 0.4s both;
}
.section-title {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 30rpx;
}
.section-title .iconfont {
margin-right: 15rpx;
font-size: 32rpx;
color: #667eea;
}
.actions-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
}
.action-item {
text-align: center;
}
.action-icon {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
margin: 0 auto 20rpx;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 40rpx;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.action-item:active .action-icon {
transform: scale(0.95);
}
.action-name {
font-size: 24rpx;
color: #666;
}
/* 功能模块 */
.modules {
margin: 30rpx 40rpx;
animation: fadeIn 0.8s ease 0.6s both;
}
.module-section {
background: white;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.05);
}
.module-items {
margin-top: 20rpx;
}
.module-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 0;
border-bottom: 1rpx solid #f0f0f0;
transition: background-color 0.2s ease;
}
.module-item:active {
background-color: #f8f9fa;
}
.module-item:last-child {
border-bottom: none;
}
.item-left {
display: flex;
align-items: center;
flex: 1;
}
.item-icon {
width: 60rpx;
height: 60rpx;
border-radius: 15rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
margin-right: 25rpx;
}
.item-icon .iconfont {
color: white;
font-size: 30rpx;
}
.item-info {
flex: 1;
}
.item-name {
font-size: 30rpx;
color: #333;
margin-bottom: 8rpx;
}
.item-desc {
font-size: 24rpx;
color: #999;
margin-bottom: 5rpx;
}
.item-status {
font-size: 22rpx;
padding: 4rpx 12rpx;
border-radius: 12rpx;
background: rgba(255, 107, 107, 0.1);
display: inline-block;
}
.text-orange {
color: #ff9f43;
background: rgba(255, 159, 67, 0.1);
}
.item-right {
display: flex;
align-items: center;
}
.badge {
background: #ff6b6b;
color: white;
font-size: 20rpx;
min-width: 36rpx;
height: 36rpx;
border-radius: 18rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 0 8rpx;
margin-right: 15rpx;
}
.item-right .iconfont {
color: #ccc;
font-size: 28rpx;
}
/* 底部操作 */
.bottom-actions {
margin: 30rpx 40rpx;
animation: fadeIn 0.8s ease 0.8s both;
}
.system-info {
text-align: center;
font-size: 24rpx;
color: #999;
margin-bottom: 40rpx;
display: flex;
flex-direction: column;
gap: 10rpx;
}
.action-buttons {
display: flex;
gap: 20rpx;
}
.btn {
flex: 1;
height: 88rpx;
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 500;
border: none;
transition: all 0.3s ease;
}
.btn:active {
transform: scale(0.98);
}
.btn-setting {
background: white;
color: #667eea;
border: 2rpx solid #667eea;
}
.btn-logout {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
box-shadow: 0 10rpx 20rpx rgba(255, 107, 107, 0.3);
}
.btn .iconfont {
margin-right: 10rpx;
font-size: 28rpx;
}
/* 动画效果 */
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* 响应式调整 */
@media (max-width: 375px) {
.user-card,
.stats-grid,
.quick-actions,
.modules,
.bottom-actions {
margin-left: 30rpx;
margin-right: 30rpx;
}
}

2
pagesA/pages/socialWork/socialWork.wxml

@ -1,2 +0,0 @@
<!--pagesA/pages/socialWork/socialWork.wxml-->
<text>pagesA/pages/socialWork/socialWork.wxml</text>

1
pagesA/pages/socialWork/socialWork.wxss

@ -1 +0,0 @@
/* pagesA/pages/socialWork/socialWork.wxss */

299
pagesA/pages/wzai/wzai.js

@ -0,0 +1,299 @@
Page({
data: {
// 当前时间
currentTime: '',
// 聊天消息
messages: [],
// 输入框相关
inputValue: '',
autoFocus: false,
// 症状选择
quickSymptoms: [
'发热', '咳嗽', '腹泻', '食欲不振',
'精神萎靡', '呼吸困难', '体重下降', '皮肤问题'
],
selectedSymptoms: [],
showSymptomSelector: false,
// 症状数据
symptoms: [
{ id: 1, name: '发热', category: '全身症状' },
{ id: 2, name: '咳嗽', category: '呼吸系统' },
{ id: 3, name: '腹泻', category: '消化系统' },
{ id: 4, name: '呕吐', category: '消化系统' },
{ id: 5, name: '食欲不振', category: '消化系统' },
{ id: 6, name: '呼吸困难', category: '呼吸系统' },
{ id: 7, name: '精神萎靡', category: '神经系统' },
{ id: 8, name: '体重下降', category: '全身症状' },
{ id: 9, name: '皮肤问题', category: '皮肤系统' },
{ id: 10, name: '跛行', category: '运动系统' },
{ id: 11, name: '眼部分泌物', category: '五官' },
{ id: 12, name: '流鼻涕', category: '呼吸系统' }
],
// 状态控制
isAIThinking: false,
isLoading: false,
loadingText: '',
showMoreMenu: false
},
onLoad() {
this.initData();
},
onShow() {
this.updateCurrentTime();
this.setData({ autoFocus: true });
},
// 初始化数据
initData() {
// 设置当前时间
this.updateCurrentTime();
// 定时更新当前时间
setInterval(() => {
this.updateCurrentTime();
}, 60000);
},
// 更新当前时间
updateCurrentTime() {
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
this.setData({ currentTime: timeString });
},
// 输入框变化
onInput(e) {
this.setData({ inputValue: e.detail.value });
},
// 发送消息
sendMessage() {
const message = this.data.inputValue.trim();
if (!message) return;
// 添加用户消息
const userMessage = {
id: Date.now(),
type: 'user',
content: message,
time: this.getCurrentTime()
};
this.setData({
messages: [...this.data.messages, userMessage],
inputValue: '',
autoFocus: true
});
// 模拟AI思考
this.simulateAIResponse(message);
},
// 获取当前时间
getCurrentTime() {
const now = new Date();
return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
},
// 模拟AI响应
simulateAIResponse(userMessage) {
this.setData({ isAIThinking: true });
// 模拟AI思考时间
setTimeout(() => {
const aiMessage = this.generateAIResponse(userMessage);
console.log(333,aiMessage);
this.setData({
messages: [...this.data.messages, aiMessage],
isAIThinking: false
});
}, 1500 + Math.random() * 1000);
},
// 生成AI响应
generateAIResponse(userMessage) {
console.log(444,userMessage);
const responses = {
'发热': {
content: '根据您的描述,牲畜出现发热症状。',
diagnosis: {
disease: '可能为感染性疾病或中暑',
severity: 'moderate',
severityText: '中度',
suggestion: '建议:1. 隔离观察 2. 监测体温 3. 提供充足饮水 4. 如持续发热,及时联系兽医'
}
},
'咳嗽': {
content: '咳嗽症状提示可能存在呼吸系统问题。',
diagnosis: {
disease: '可能为呼吸道感染或肺炎',
severity: 'low',
severityText: '轻度',
suggestion: '建议:1. 保持圈舍通风 2. 避免粉尘 3. 观察呼吸频率 4. 如有加重及时就医'
}
},
'腹泻': {
content: '腹泻症状需要关注,可能由多种原因引起。',
diagnosis: {
disease: '可能为消化不良或肠胃感染',
severity: 'moderate',
severityText: '中度',
suggestion: '建议:1. 调整饲料 2. 补充电解质 3. 观察粪便性状 4. 如持续腹泻需兽医检查'
}
}
};
// 匹配症状关键词
let response = responses['发热']; // 默认响应
for (const [symptom, data] of Object.entries(responses)) {
if (userMessage.includes(symptom)) {
response = data;
break;
}
}
return {
id: Date.now() + 1,
type: 'assistant',
content: response.content,
diagnosis: response.diagnosis,
time: this.getCurrentTime()
};
},
// 选择快捷症状
selectQuickSymptom(e) {
console.log(1111,e);
const symptom = e.currentTarget.dataset.symptom;
this.setData({ inputValue: symptom });
this.sendMessage();
},
// 切换症状选择器
toggleSymptomSelector() {
this.setData({ showSymptomSelector: !this.data.showSymptomSelector });
},
// 关闭症状选择器
closeSymptomSelector() {
this.setData({ showSymptomSelector: false });
},
// 症状选择
onSymptomSelect(e) {
const { symptom } = e.detail;
const selectedSymptoms = [...this.data.selectedSymptoms];
const index = selectedSymptoms.findIndex(s => s.id === symptom.id);
if (index > -1) {
selectedSymptoms.splice(index, 1);
} else {
selectedSymptoms.push(symptom);
}
this.setData({ selectedSymptoms });
},
// 确认症状选择
confirmSymptoms() {
if (this.data.selectedSymptoms.length === 0) {
wx.showToast({
title: '请选择至少一个症状',
icon: 'none'
});
return;
}
const symptomNames = this.data.selectedSymptoms.map(s => s.name).join('、');
this.setData({
inputValue: `我的牲畜出现以下症状:${symptomNames}`,
showSymptomSelector: false
});
},
// 返回
goBack() {
wx.navigateBack();
},
// 显示更多菜单
showMoreMenu() {
this.setData({ showMoreMenu: true });
},
// 关闭更多菜单
closeMoreMenu() {
this.setData({ showMoreMenu: false });
},
// 阻止事件冒泡
stopPropagation() {},
// 清空记录
clearHistory() {
wx.showModal({
title: '提示',
content: '确定要清空所有聊天记录吗?',
success: (res) => {
if (res.confirm) {
this.setData({
messages: [{
id: 1,
type: 'assistant',
content: '您好!我是AI健康助手,有什么可以帮您?\n\n请描述您或牲畜的健康状况,我会为您提供专业的分析和建议。',
time: this.getCurrentTime()
}],
selectedSymptoms: []
});
this.closeMoreMenu();
}
}
});
},
// 导出记录
exportChat() {
wx.showToast({
title: '记录已保存到本地',
icon: 'success'
});
this.closeMoreMenu();
},
// 联系兽医
contactDoctor() {
wx.showModal({
title: '联系兽医',
content: '确定要拨打兽医热线吗?',
success: (res) => {
if (res.confirm) {
wx.makePhoneCall({
phoneNumber: '400-123-4567'
});
}
}
});
this.closeMoreMenu();
},
// 显示使用说明
showInstructions() {
wx.showModal({
title: '使用说明',
content: '1. 描述您或牲畜的症状\n2. AI助手会分析并提供建议\n3. 可使用快捷症状选择\n4. 诊断结果仅供参考,请及时咨询专业兽医',
showCancel: false
});
this.closeMoreMenu();
}
});

5
pagesA/pages/wzai/wzai.json

@ -0,0 +1,5 @@
{
"navigationBarTitleText":"AI问诊",
"navigationStyle": "custom",
"usingComponents": {}
}

196
pagesA/pages/wzai/wzai.wxml

@ -0,0 +1,196 @@
<view class="diagnosis-container">
<!-- 自定义导航栏 -->
<view class="custom-navbar">
<view class="nav-left">
<view class="back-btn" bindtap="goBack">
<text class="back-icon">←</text>
</view>
</view>
<view class="nav-center">
<text class="nav-title">AI智能问诊</text>
<text class="nav-subtitle">与牧健康助手</text>
</view>
<view class="nav-right">
<view class="more-btn" bindtap="showMoreMenu">···</view>
</view>
</view>
<!-- 医生信息卡片 -->
<view class="doctor-card">
<view class="doctor-avatar">
<image class="avatar-img" src="/pages/images/aiwz.png" mode="aspectFit"></image>
</view>
<view class="doctor-info">
<text class="doctor-name">AI健康助手</text>
<text class="doctor-title">智能诊断专家</text>
<view class="doctor-tags">
<view class="tag">24小时在线</view>
<view class="tag">专业诊断</view>
<view class="tag">快速响应</view>
</view>
</view>
<view class="online-status online">在线</view>
</view>
<!-- 聊天区域 -->
<scroll-view
class="chat-container"
scroll-y
scroll-into-view="{{'msg-' + (messages.length - 1)}}"
scroll-with-animation="true"
>
<!-- 欢迎消息 -->
<view class="message-wrapper assistant">
<view class="message-avatar">
<image class="avatar" src="/pages/images/aiwz.png" mode="aspectFit"></image>
</view>
<view class="message-content">
<view class="message-bubble assistant-bubble">
<text class="message-text">您好!我是AI健康助手,有什么可以帮您?\n\n请描述你的牲畜的健康状况,我会为你提供专业的分析和建议。</text>
</view>
<view class="message-time">{{currentTime}}</view>
</view>
</view>
<!-- 消息列表 -->
<view wx:for="{{messages}}" wx:key="id" id="msg-{{index}}">
<!-- 用户消息 -->
<view wx:if="{{item.type === 'user'}}" class="message-wrapper user">
<view class="message-content">
<view class="message-bubble user-bubble">
<text class="message-text">{{item.content}}</text>
</view>
<view class="message-time">{{item.time}}</view>
</view>
<view class="message-avatar">
<image class="avatar" src="/pages/images/tx.png" mode="aspectFit"></image>
</view>
</view>
<!-- AI助手消息 -->
<view wx:if="{{item.type === 'assistant'}}" class="message-wrapper assistant">
<view class="message-avatar">
<image class="avatar" src="/pages/images/aiwz.png" mode="aspectFit"></image>
</view>
<view class="message-content">
<view class="message-bubble assistant-bubble">
<text class="message-text">{{item.content}}</text>
<!-- 诊断结果卡片 -->
<view wx:if="{{item.diagnosis}}" class="diagnosis-card">
<view class="diagnosis-header">
<text class="diagnosis-title">🤖 智能诊断结果</text>
</view>
<view class="diagnosis-item">
<text class="diagnosis-label">可能病症:</text>
<text class="diagnosis-value">{{item.diagnosis.disease}}</text>
</view>
<view class="diagnosis-item">
<text class="diagnosis-label">严重程度:</text>
<view class="severity-level {{item.diagnosis.severity}}">
{{item.diagnosis.severityText}}
</view>
</view>
<view class="diagnosis-item">
<text class="diagnosis-label">建议措施:</text>
<text class="diagnosis-value">{{item.diagnosis.suggestion}}</text>
</view>
<view class="diagnosis-footer">
<text class="disclaimer">* 本结果仅供参考,请及时咨询专业兽医</text>
</view>
</view>
</view>
<view class="message-time">{{item.time}}</view>
</view>
</view>
</view>
<!-- AI正在输入 -->
<view wx:if="{{isAIThinking}}" class="message-wrapper assistant" style="justify-content: center;">
<view class="message-content">
<view class="message-bubble assistant-bubble typing">
<view class="typing-indicator">
<view class="typing-dot"></view>
<view class="typing-dot"></view>
<view class="typing-dot"></view>
<text class="typing-text">AI正在思考中...</text>
</view>
</view>
</view>
</view>
</scroll-view>
<!-- 快捷症状选择 -->
<view class="symptom-quick-select">
<text class="section-title">快速选择症状</text>
<scroll-view class="symptom-tags" scroll-x>
<view class="symptom-tag" wx:for="{{quickSymptoms}}" wx:key="id" bindtap="selectQuickSymptom" data-symptom="{{item}}">
<text class="tag-text">{{item}}</text>
</view>
</scroll-view>
</view>
<!-- 输入区域 -->
<view class="input-area">
<view class="input-wrapper">
<input
class="message-input"
value="{{inputValue}}"
placeholder="描述您或牲畜的症状..."
placeholder-class="placeholder"
bindinput="onInput"
bindconfirm="sendMessage"
confirm-type="send"
focus="{{autoFocus}}"
/>
</view>
<button class="send-btn" bindtap="sendMessage" hover-class="send-btn-hover">
<text class="send-icon">↑</text>
</button>
</view>
<!-- 症状选择器组件 -->
<symptom-selector
id="symptomSelector"
show="{{showSymptomSelector}}"
symptoms="{{symptoms}}"
selectedSymptoms="{{selectedSymptoms}}"
bind:select="onSymptomSelect"
bind:confirm="confirmSymptoms"
bind:close="closeSymptomSelector"
/>
<!-- 更多菜单弹窗 -->
<view class="modal-overlay" wx:if="{{showMoreMenu}}" bindtap="closeMoreMenu">
<view class="more-menu" catchtap="stopPropagation">
<view class="menu-item" bindtap="clearHistory">
<text class="menu-icon">🗑️</text>
<text class="menu-text">清空记录</text>
</view>
<view class="menu-item" bindtap="exportChat">
<text class="menu-icon">📤</text>
<text class="menu-text">导出记录</text>
</view>
<view class="menu-item" bindtap="contactDoctor">
<text class="menu-icon">👨‍⚕️</text>
<text class="menu-text">联系兽医</text>
</view>
<view class="menu-item" bindtap="showInstructions">
<text class="menu-icon">❓</text>
<text class="menu-text">使用说明</text>
</view>
</view>
</view>
<!-- 加载动画 -->
<view class="loading-overlay" wx:if="{{isLoading}}">
<view class="loading-content">
<view class="pulse-animation">
<view class="pulse-circle"></view>
<view class="pulse-circle"></view>
<view class="pulse-circle"></view>
</view>
<text class="loading-text">{{loadingText}}</text>
</view>
</view>
</view>

530
pagesA/pages/wzai/wzai.wxss

@ -0,0 +1,530 @@
.diagnosis-container {
min-height: 100vh;
width: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #f8fafc 0%, #f0f9ff 100%);
}
/* 自定义导航栏 */
.custom-navbar {
height: 120rpx;
padding-top: 40rpx;
background: linear-gradient(135deg, #86D8D0 0%, #6BC4BC 100%);
display: flex;
align-items: center;
justify-content: space-between;
padding: 40rpx 32rpx 20rpx;
box-shadow: 0 2rpx 12rpx rgba(134, 216, 208, 0.2);
}
.nav-left, .nav-right {
width: 80rpx;
}
.nav-center {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.nav-title {
font-size: 36rpx;
font-weight: 600;
color: white;
margin-bottom: 4rpx;
}
.nav-subtitle {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.8);
}
.back-btn {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
color: white;
font-size: 36rpx;
font-weight: 300;
}
.more-btn {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 36rpx;
font-weight: bold;
}
/* 医生信息卡片 */
.doctor-card {
background: white;
margin: 24rpx 32rpx;
padding: 32rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
position: relative;
}
.doctor-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: linear-gradient(135deg, #86D8D0 0%, #A8E6CF 100%);
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
overflow: hidden;
}
.avatar-img {
width: 100rpx;
height: 100rpx;
}
.doctor-info {
flex: 1;
}
.doctor-name {
display: block;
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.doctor-title {
display: block;
font-size: 24rpx;
color: #86D8D0;
margin-bottom: 16rpx;
}
.doctor-tags {
display: flex;
gap: 12rpx;
}
.tag {
font-size: 20rpx;
padding: 6rpx 12rpx;
background: #E8F4F3;
color: #6BC4BC;
border-radius: 20rpx;
}
.online-status {
position: absolute;
right: 32rpx;
bottom: 32rpx;
font-size: 22rpx;
padding: 4rpx 12rpx;
border-radius: 12rpx;
}
.online-status.online {
background: #e8f1f4;
color: #6b8fc4;
}
/* 聊天容器 */
.chat-container {
flex: 1;
/* padding: 0 32rpx; */
display: flex;
flex-direction: column;
}
/* 消息样式 */
.message-wrapper {
display: flex;
margin: 40rpx 0;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20rpx); }
to { opacity: 1; transform: translateY(0); }
}
.message-wrapper.user {
justify-content: flex-end;
}
.message-content {
max-width: 70%;
display: flex;
flex-direction: column;
}
.message-wrapper.user .message-content {
align-items: flex-end;
}
.message-wrapper.assistant .message-content {
align-items: flex-start;
}
.message-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
overflow: hidden;
margin: 0 20rpx;
align-self: flex-end;
}
.avatar {
width: 100%;
height: 100%;
}
/* 消息气泡 */
.message-bubble {
padding: 24rpx;
border-radius: 24rpx;
position: relative;
line-height: 1.5;
}
.assistant-bubble {
background: #E8F4F3;
border-radius: 0 24rpx 24rpx 24rpx;
}
.user-bubble {
background: #86D8D0;
border-radius: 24rpx 0 24rpx 24rpx;
}
.message-text {
font-size: 28rpx;
color: #333;
}
.user-bubble .message-text {
color: white;
}
/* 消息时间 */
.message-time {
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
}
/* 诊断结果卡片 */
.diagnosis-card {
background: white;
border-radius: 16rpx;
padding: 24rpx;
margin-top: 20rpx;
border-left: 6rpx solid #86D8D0;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.diagnosis-header {
margin-bottom: 20rpx;
}
.diagnosis-title {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.diagnosis-item {
display: flex;
margin-bottom: 16rpx;
align-items: flex-start;
}
.diagnosis-label {
font-size: 26rpx;
color: #666;
width: 140rpx;
flex-shrink: 0;
}
.diagnosis-value {
font-size: 26rpx;
color: #333;
flex: 1;
line-height: 1.4;
}
.severity-level {
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 500;
}
.severity-level.low {
background: #E8F4F3;
color: #6BC4BC;
}
.severity-level.moderate {
background: #FFF3E0;
color: #FF9800;
}
.severity-level.high {
background: #FFEBEE;
color: #F44336;
}
.diagnosis-footer {
margin-top: 20rpx;
padding-top: 16rpx;
border-top: 1rpx solid #eee;
}
.disclaimer {
font-size: 22rpx;
color: #999;
font-style: italic;
}
/* AI正在输入 */
.typing {
min-width: 200rpx;
}
.typing-indicator {
display: flex;
align-items: center;
gap: 8rpx;
}
.typing-dot {
width: 12rpx;
height: 12rpx;
background: #86D8D0;
border-radius: 50%;
animation: typingAnimation 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(1) { animation-delay: -0.32s; }
.typing-dot:nth-child(2) { animation-delay: -0.16s; }
@keyframes typingAnimation {
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
40% { transform: scale(1); opacity: 1; }
}
.typing-text {
font-size: 26rpx;
color: #666;
margin-left: 12rpx;
}
/* 快捷症状选择 */
.symptom-quick-select {
padding: 0 32rpx 20rpx;
}
.section-title {
display: block;
font-size: 26rpx;
color: #666;
margin-bottom: 20rpx;
}
.symptom-tags {
white-space: nowrap;
display: flex;
gap: 20rpx;
}
.symptom-tag {
display: inline-block;
padding: 16rpx 24rpx;
background: white;
border-radius: 24rpx;
border: 1rpx solid #E8F4F3;
box-shadow: 0 2rpx 8rpx rgba(134, 216, 208, 0.1);
transition: all 0.2s ease;
}
.symptom-tag:active {
transform: scale(0.95);
background: #E8F4F3;
}
.tag-text {
font-size: 26rpx;
color: #666;
}
/* 输入区域 */
.input-area {
background: white;
padding: 20rpx 32rpx 40rpx;
border-top: 1rpx solid #f0f0f0;
display: flex;
align-items: flex-end;
gap: 20rpx;
}
.input-wrapper {
flex: 1;
background: #f8fafc;
border-radius: 24rpx;
padding: 16rpx 24rpx;
border: 1rpx solid #E8F4F3;
}
.message-input {
font-size: 28rpx;
min-height: 60rpx;
line-height: 1.5;
}
.placeholder {
color: #aaa;
}
.send-btn {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: #86D8D0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(134, 216, 208, 0.3);
transition: all 0.2s ease;
}
.send-btn-hover {
background: #6BC4BC;
transform: translateY(-2rpx);
box-shadow: 0 6rpx 16rpx rgba(134, 216, 208, 0.4);
}
.send-icon {
color: white;
font-size: 36rpx;
font-weight: 300;
}
/* 更多菜单 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
justify-content: flex-end;
align-items: flex-start;
padding-top: 120rpx;
padding-right: 32rpx;
}
.more-menu {
background: white;
border-radius: 16rpx;
padding: 16rpx 0;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
min-width: 240rpx;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from { opacity: 0; transform: translateY(-20rpx); }
to { opacity: 1; transform: translateY(0); }
}
.menu-item {
display: flex;
align-items: center;
padding: 24rpx 32rpx;
gap: 16rpx;
}
.menu-item:active {
background: #f8fafc;
}
.menu-icon {
font-size: 28rpx;
}
.menu-text {
font-size: 28rpx;
color: #333;
}
/* 加载动画 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.9);
z-index: 1001;
display: flex;
align-items: center;
justify-content: center;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
}
.pulse-animation {
position: relative;
width: 120rpx;
height: 120rpx;
}
.pulse-circle {
position: absolute;
width: 100%;
height: 100%;
border: 4rpx solid #86D8D0;
border-radius: 50%;
animation: pulse 2s infinite ease-in-out;
}
.pulse-circle:nth-child(2) { animation-delay: 0.5s; }
.pulse-circle:nth-child(3) { animation-delay: 1s; }
@keyframes pulse {
0% { transform: scale(0.8); opacity: 1; }
100% { transform: scale(1.5); opacity: 0; }
}
.loading-text {
margin-top: 40rpx;
font-size: 28rpx;
color: #666;
}

2
project.config.json

@ -1,5 +1,5 @@
{
"appid": "wx903a5fea119f2d4a",
"appid": "wxb5becc8d6d8123a6",
"compileType": "miniprogram",
"libVersion": "3.13.0",
"packOptions": {

32
utils/api.js

@ -1,13 +1,39 @@
//在这里面定义所有接口,一个文件管理所有接口,易于维护
import { http } from './http'; // 引入刚刚封装好的http模块,import属于ES6的语法,微信开发者工具必须打开ES6转ES5选项
function login(params) { // 请求登录接口
http('/login', 'post', params) // 接口请求的路由地址以及请求方法在此处传递
// 授权登录接口
function login(params) {
http('/auth/wechat/login', 'post', params)
}
// 获取手机号接口
function getPhoneNumber(params) {
http('/auth/wechat/bind', 'post', params)
}
// 轮播
function carousel(params) {
http('/muhu/ads/list', 'get', params)
}
// 通知公告
function disaster(params) {
http('/muhu/warning/list', 'get', params)
}
// 地图导航药店诊所
function pharmacy(params) {
http('/muhu/info/list', 'get', params)
}
// 办事指南
function guidance(params) {
http('/muhu/guide/list', 'get', params)
}
export default { // 暴露接口
login
login,carousel,disaster,pharmacy,guidance,getPhoneNumber
}

6
utils/baseUrl.js

@ -1,4 +1,4 @@
//url: 'https://wxamp.chenhaitech.com/tglzw' + url, // 就是拼接上前缀,此接口域名是开放接口,可访问
var baseUrl = 'https://wx.chenhaitech.com/guoziwei-prod-api'
// var baseUrl = 'http://192.168.101.111:8080'
// var baseUrl = 'https://wx.chenhaitech.com/guoziwei-prod-api'
var baseUrl = 'http://192.168.101.109:8080'
// var baseUrl = 'http://192.168.101.111:8081'
module.exports = baseUrl

5
utils/http.js

@ -47,7 +47,7 @@ module.exports = {
data,
header: {
'content-type': 'application/json',
'Authorization':'Bearer '+value
'Authorization':'Bearer '+ value
},
success(res) {
// console.log(res);
@ -58,14 +58,13 @@ module.exports = {
success (res) {
if (res.confirm) {
wx.reLaunch({
url: '/pages/logo/logo',
url: '/pages/login/login',
})
} else if (res.cancel) {
}
}
})
}else{
params.success && params.success(res.data)
}

19
utils/tool.wxs

@ -1,11 +1,12 @@
function images(status,value) {
if(value<6){
return status != '0' ? '/pages/assets/img/jichu.png':'/pages/assets/img/jichu1.png'
}else if(value>5 && value<9){
return status != '0' ? '/pages/assets/img/tese.png':'/pages/assets/img/tece1.png'
}else{
return status != '0' ? '/pages/assets/img/mofan.png':'/pages/assets/img/mofan1.png'
}
// 通知
function type(name) {
if(name=='紧急'){
return 'urgent'
}else if(name=='重要'){
return 'important'
}else{
return 'normal'
}
}
@ -14,5 +15,5 @@ function images(status,value) {
module.exports = {
type:type
}
Loading…
Cancel
Save