Browse Source

Merge branch 'master' of http://git.nzklabs.com:3000/huangyuanhao/jfcloud-coldchain

jackzhou 7 months ago
parent
commit
6d80d84870
25 changed files with 790 additions and 98 deletions
  1. 6 7
      snowy-admin-web/src/api/basicset/locationApi.js
  2. 4 0
      snowy-admin-web/src/api/basicset/memApi.js
  3. 1 1
      snowy-admin-web/src/views/basicset/mem/index.vue
  4. 309 15
      snowy-admin-web/src/views/basicset/monitor/configForm.vue
  5. 2 2
      snowy-admin-web/src/views/basicset/monitor/index.vue
  6. 14 7
      snowy-admin-web/src/views/basicset/monitor/setup.vue
  7. 117 48
      snowy-admin-web/src/views/motoring/location/form.vue
  8. 25 4
      snowy-admin-web/src/views/motoring/location/index.vue
  9. 2 2
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/controller/MonitorDeviceController.java
  10. 1 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/MonitorDeviceService.java
  11. 13 5
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/impl/MonitorDeviceServiceImpl.java
  12. 2 2
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/controller/MonitorDeviceTypeController.java
  13. 2 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/service/MonitorDeviceTypeService.java
  14. 9 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/service/impl/MonitorDeviceTypeServiceImpl.java
  15. 1 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/controller/MonitorTargetController.java
  16. 10 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/controller/MonitorTargetRegionController.java
  17. 1 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/entity/MonitorTargetRegion.java
  18. 1 1
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/param/MonitorTargetRegionPageParam.java
  19. 5 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/service/MonitorTargetRegionService.java
  20. 9 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/service/impl/MonitorTargetRegionServiceImpl.java
  21. 31 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/config/PushConfigure.java
  22. 85 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/entity/WeChatUser.java
  23. 34 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/utils/PushUtil.java
  24. 104 0
      snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/utils/WeChatUtil.java
  25. 2 1
      snowy-web-app/src/main/resources/application.properties

+ 6 - 7
snowy-admin-web/src/api/basicset/locationApi.js

@@ -2,23 +2,22 @@ import { baseRequest } from '@/utils/request'
 
 const request = (url, ...arg) => baseRequest(`/coldchain/monitortargetregion/` + url, ...arg)
 
-// 区域管理
+// 监测点管理
 export default {
 	// 获取列表数据分页
 	locationPage(data) {
 		return request('page', data, 'get')
 	},
+	// 根据监控对象id获取监控点位列表
+	listByTargetIdData(data) {
+		return request('listByTargetId', data, 'get')
+	},
+
 	// 提交表单 edit为true时为编辑,默认为新增
 	submitForm(data, edit = false) {
 		return request(edit ? 'edit' : 'add', data)
 	},
 
-	// 获取树结构
-	locationTree(data) {
-		return request('tree', data, 'get')
-	},
-
-
 	// 删除
 	locationDelete(data) {
 		return request('delete', data)

+ 4 - 0
snowy-admin-web/src/api/basicset/memApi.js

@@ -31,5 +31,9 @@ export default {
 	// 检查设备名是否已注册
 	submitDeviceCode(data) {
 		return request('getByDeviceCode', data, 'get')
+	},
+	// 根据检测设备id获取监测点位列表
+	getRegionByDeviceIdData(data) {
+		return request('getRegionByDeviceId', data, 'get')
 	}
 }

+ 1 - 1
snowy-admin-web/src/views/basicset/mem/index.vue

@@ -56,7 +56,7 @@
 				</template>
 				<template v-if="column.dataIndex === 'action'">
 					<a-button type="link" size="small" @click="formRef.onOpen(record)">编辑</a-button>
-					<a-button type="link" size="small" @click="configformRef.onOpen(record)">配置</a-button>
+					<!-- <a-button type="link" size="small" @click="configformRef.onOpen(record)">配置</a-button> -->
 					<a-popconfirm title="确定要删除吗?" @confirm="deleteData(record)">
 						<a-button type="link" danger size="small">删除</a-button>
 					</a-popconfirm>

+ 309 - 15
snowy-admin-web/src/views/basicset/monitor/configForm.vue

@@ -1,21 +1,162 @@
 <template>
-	<xn-form-container title="区域配置" :width="'500px'" :visible="visible" :destroy-on-close="true" @close="onClose">
+	<xn-form-container title="监测点配置" :width="'800px'" :visible="visible" :destroy-on-close="true" @close="onClose">
 		<a-form
 			ref="formRef"
 			:model="formData"
 			:rules="formRules"
 			layout="inline"
-			:label-col="{ style: { width: '85px', justifyContent: 'end' } }"
+			:label-col="{ style: { width: '110px', justifyContent: 'end' } }"
 		>
-			<!-- <a-form-item label="目标端口" name="code">
-				<a-input v-model:value="formData.code" placeholder="请输入目标端口" allow-clear />
-			</a-form-item>
-			<a-form-item label="设备型号" name="modelName">
-				<a-select ref="select" v-model:value="formData.modelName" :options="modeOptions"> </a-select>
-			</a-form-item>
-			<a-form-item label="目标端口" name="code">
-				<a-input-number id="inputNumber" v-model:value="formData.code" style="width: 100%" />
-			</a-form-item> -->
+			<a-row :gutter="10">
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="监控对象" name="monitorTargetId">
+						<a-select
+							ref="select"
+							v-model:value="formData.monitorTargetId"
+							:options="monitorTargetOptions"
+							placeholder="请选择监控对象"
+						/>
+					</a-form-item>
+				</a-col>
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="点位名称" name="name">
+						<a-input v-model:value="formData.name" placeholder="请输入点位名称" allow-clear />
+					</a-form-item>
+				</a-col>
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="传感器类型" name="sensorType">
+						<a-select
+							ref="select"
+							v-model:value="formData.sensorType"
+							:options="sensorOptions"
+							placeholder="请选择传感器类型"
+							@change="sensorTypeChange"
+						/>
+					</a-form-item>
+				</a-col>
+
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="监控设备" name="monitorDeviceId">
+						<a-select
+							ref="select"
+							v-model:value="formData.monitorDeviceId"
+							:options="memListOptions"
+							placeholder="请选择监控设备"
+							@change="monitorDeviceIdChange"
+						/>
+					</a-form-item>
+				</a-col>
+
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="传感器编号" name="sensorCode">
+						<a-input v-model:value="formData.sensorCode" disabled placeholder="请输入传感器编号" allow-clear />
+					</a-form-item>
+				</a-col>
+
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="传感器路数" name="sensorRoute">
+						<a-input-number
+							v-model:value="formData.sensorRoute"
+							style="width: 100%"
+							:min="1"
+							:max="sensorRouteMax"
+							placeholder="请输入传感器路数"
+						/>
+					</a-form-item>
+				</a-col>
+
+				<div
+					class="form_item"
+					v-if="formData.sensorType == 'W' || formData.sensorType == 'WS' || formData.sensorType == 'WSC'"
+				>
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="温度上限" name="temperatureUp">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.temperatureUp"
+								placeholder="请输入温度上限"
+								allow-clear
+								:min="temperatureMax.downMax"
+								:max="temperatureMax.upMax"
+								style="width: 100%"
+								:disabled="temperatureMax.upMax == null || temperatureMax.upMax == undefined"
+							/>
+						</a-form-item>
+					</a-col>
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="温度下限" name="temperatureDown">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.temperatureDown"
+								placeholder="请输入温度下限"
+								allow-clear
+								:min="temperatureMax.downMax"
+								:max="temperatureMax.upMax"
+								style="width: 100%"
+								:disabled="!temperatureMax.downMax == null || temperatureMax.downMax == undefined"
+							/>
+						</a-form-item>
+					</a-col>
+				</div>
+
+				<div class="form_item" v-if="formData.sensorType == 'WS' || formData.sensorType == 'WSC'">
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="湿度上限" name="humidityUp">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.humidityUp"
+								placeholder="请输入湿度上限"
+								allow-clear
+								:min="humidityMax.downMax"
+								:max="humidityMax.upMax"
+								style="width: 100%"
+								:disabled="!humidityMax.upMax"
+							/>
+						</a-form-item>
+					</a-col>
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="湿度下限" name="humidityDown">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.humidityDown"
+								placeholder="请输入湿度下限"
+								allow-clear
+								:min="humidityMax.downMax"
+								:max="humidityMax.upMax"
+								style="width: 100%"
+								:disabled="!humidityMax.downMax"
+							/>
+						</a-form-item>
+					</a-col>
+				</div>
+
+				<div class="form_item" v-if="formData.sensorType == 'WSC'">
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="CO2上限" name="co2Up">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.co2Up"
+								placeholder="请输入CO2上限"
+								allow-clear
+								:max="co2Max.upMax"
+								style="width: 100%"
+							/>
+						</a-form-item>
+					</a-col>
+					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<a-form-item label="CO2下限" name="co2Down">
+							<a-input-number
+								id="inputNumber"
+								v-model:value="formData.co2Down"
+								placeholder="请输入CO2下限"
+								allow-clear
+								:max="co2Max.downMax"
+								style="width: 100%"
+							/>
+						</a-form-item>
+					</a-col>
+				</div>
+			</a-row>
 		</a-form>
 
 		<template #footer>
@@ -28,26 +169,171 @@
 <script setup>
 	import tool from '@/utils/tool'
 	import { required } from '@/utils/formRules'
+	import locationApi from '@/api/basicset/locationApi.js'
+	import setupApi from '@/api/basicset/setupApi'
 	import memApi from '@/api/basicset/memApi'
 	const emit = defineEmits({ successful: null })
 	const visible = ref(false) // 默认是关闭状态
 	const formRef = ref()
-	const formData = ref({}) // 表单数据
-	const modeOptions = tool.dictList('COIDCHAIN') // 设备型号
+	const formData = ref() // 表单数据
+	const sensorOptions = tool.dictList('SENSORTYPE') // 传感器类型
+	const monitorTargetOptions = ref([]) // 监控对象
+	const memListOptions = ref([]) // 监控设备数据
+
+	const temperatureMax = ref({ upMax: Infinity, downMax: Infinity }) // 温度最大值
+	const humidityMax = ref({ upMax: Infinity, downMax: Infinity }) // 湿度最大值
+	const co2Max = ref({ upMax: Infinity, downMax: Infinity }) // CO2最大值
+
+	const sensorRouteMax = ref(1) //传感器最大值默认1
+
 	// 默认要校验的
 	const formRules = {
-		code: [required('请输入设备名称')]
+		name: [required('请输入区域名称')],
+		monitorTargetId: [required('请选择监控对象')],
+		monitorDeviceId: [required('请选择监控设备')],
+		sensorType: [required('请选择传感器类型')],
+		sensorRoute: [required('请输入传感器路数')],
+		temperatureUp: [{ validator: validateTemperature, trigger: ['change', 'blur'] }],
+		temperatureDown: [{ validator: validateTemperature, trigger: ['change', 'blur'] }],
+		humidityUp: [{ validator: validateHumidity, trigger: ['change', 'blur'] }],
+		humidityDown: [{ validator: validateHumidity, trigger: ['change', 'blur'] }],
+		co2Up: [{ validator: validateCo2, trigger: ['change', 'blur'] }],
+		co2Down: [{ validator: validateCo2, trigger: ['change', 'blur'] }]
+	}
+
+	// 温度上下限校验
+	function validateTemperature(rule, value, callback) {
+		if (rule.field == 'temperatureDown') {
+			if (formData.value.temperatureUp !== null && value >= formData.value.temperatureUp) {
+				callback(new Error('温度下限不能大于或等于温度上限'))
+			} else {
+				callback()
+			}
+		} else if (rule.field == 'temperatureUp') {
+			if (formData.value.temperatureDown !== null && value <= formData.value.temperatureDown) {
+				callback(new Error('温度上限不能小于或等于温度下限'))
+			} else {
+				callback()
+			}
+		}
+	}
+
+	// 湿度上下限校验
+	function validateHumidity(rule, value, callback) {
+		if (rule.field == 'humidityDown') {
+			if (formData.value.humidityUp !== null && value >= formData.value.humidityUp) {
+				callback(new Error('湿度下限不能大于或等于湿度上限'))
+			} else {
+				callback()
+			}
+		} else if (rule.field == 'humidityUp') {
+			if (formData.value.humidityDown !== null && value <= formData.value.humidityDown) {
+				callback(new Error('湿度上限不能小于或等于湿度下限'))
+			} else {
+				callback()
+			}
+		}
+	}
+
+	// CO2上下限校验
+	function validateCo2(rule, value, callback) {
+		if (rule.field == 'co2Down') {
+			if (formData.value.co2Up !== null && value >= formData.value.co2Up) {
+				callback(new Error('CO2下限不能大于或等于CO2上限'))
+			} else {
+				callback()
+			}
+		} else if (rule.field == 'co2Up') {
+			if (formData.value.co2Down !== null && value <= formData.value.co2Down) {
+				callback(new Error('CO2上限不能小于或等于CO2下限'))
+			} else {
+				callback()
+			}
+		}
 	}
 
 	// 打开抽屉
 	const onOpen = (record) => {
+		setupListData()
 		visible.value = true
 		if (record) {
 			formData.value = Object.assign({}, record)
+			sensorType.value = formData.value.sensorType
+			memListData(sensorType.value)
 		} else {
 			formData.value = {}
+			memListData()
 		}
 	}
+	// 获取监控对象
+	const setupListData = () => {
+		setupApi.setupList({ isAll: false }).then((res) => {
+			monitorTargetOptions.value = (res || []).map((item) => {
+				return {
+					...item,
+					value: item['id'],
+					label: item['name']
+				}
+			})
+		})
+	}
+	const sensorType = ref() //选中的传感器类型
+	// 监控设备通过传感器类型来获取, sensorType可为空
+	const memListData = (value) => {
+		memApi.memList({ isAll: false, sensorType: value }).then((res) => {
+			memListOptions.value = (res || []).map((item) => {
+				return {
+					...item,
+					value: item['id'],
+					label: item['deviceName'],
+					modelName: item['modelName'],
+					deviceCode: item['deviceCode'],
+					sensorCount: item['sensorCount']
+				}
+			})
+		})
+	}
+
+	// 选中传感器类型
+	const sensorTypeChange = (value) => {
+		if (value) {
+			sensorType.value = value
+			memListData(value)
+		}
+	}
+
+	// 选中监控设备
+	const monitorDeviceIdChange = (value) => {
+		if (value) {
+			const data = memListOptions.value.find((item) => item.value === value)
+			modeData.value = data
+
+			formData.value.sensorCode = data.deviceCode //传感器编号
+			formData.value.modelName = data.modelName //监控设备型号
+			formData.value.deviceCode = data.deviceCode //冷链编号
+			formData.value.temperatureUp = data.temperatureUp //温度上限
+			formData.value.temperatureDown = data.temperatureDown //温度下限
+			formData.value.humidityUp = data.humidityUp //湿度上限
+			formData.value.humidityDown = data.humidityDown //湿度下限
+			formData.value.co2Up = data.co2Up //CO2上限
+			formData.value.co2Down = data.co2Down //CO2下限
+			sensorRouteMax.value = data.sensorCount //传感器路数的最大值
+
+			temperatureMax.value = {
+				upMax: data.temperatureUp,
+				downMax: data.temperatureDown
+			}
+			humidityMax.value = {
+				upMax: data.humidityUp,
+				downMax: data.humidityDown
+			}
+			co2Max.value = {
+				upMax: data.co2Up,
+				downMax: data.co2Down
+			}
+		}
+	}
+
 	// 关闭抽屉
 	const onClose = () => {
 		formRef.value.resetFields()
@@ -59,7 +345,7 @@
 		formRef.value
 			.validate()
 			.then(() => {
-				memApi.submitForm(formData.value, formData.value.id).then(() => {
+				locationApi.submitForm(formData.value, formData.value.id).then(() => {
 					onClose()
 					emit('successful')
 				})
@@ -80,4 +366,12 @@
 		width: 100%;
 		margin-bottom: 10px;
 	}
+
+	.form_item {
+		width: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		flex-wrap: wrap;
+	}
 </style>

+ 2 - 2
snowy-admin-web/src/views/basicset/monitor/index.vue

@@ -4,9 +4,9 @@
 			<div class="query-tbas">
 				<div class="tbas-title" :class="activeKey == '1' ? 'active' : ''" @click="activeclick('1')">对象设置</div>
 				<a-divider type="vertical" style="height: 15px; background-color: #f4f5f7; margin: 8px 20px" />
-				<div class="tbas-title" :class="activeKey == '2' ? 'active' : ''" @click="activeclick('2')">维修记录</div>
+				<!-- <div class="tbas-title" :class="activeKey == '2' ? 'active' : ''" @click="activeclick('2')">维修记录</div>
 				<a-divider type="vertical" style="height: 15px; background-color: #f4f5f7; margin: 8px 20px" />
-				<div class="tbas-title" :class="activeKey == '3' ? 'active' : ''" @click="activeclick('3')">报废记录</div>
+				<div class="tbas-title" :class="activeKey == '3' ? 'active' : ''" @click="activeclick('3')">报废记录</div> -->
 			</div>
 		</div>
 

+ 14 - 7
snowy-admin-web/src/views/basicset/monitor/setup.vue

@@ -40,14 +40,14 @@
 							<template #icon><plus-outlined /></template>新增
 						</a-button>
 					</div>
-					<div class="btn-right">
+					<!-- <div class="btn-right">
 						<a-button class="xn-mg08">
 							<template #icon><CloudUploadOutlined /> </template>导入
 						</a-button>
 						<a-button>
 							<template #icon><download-outlined /></template>导出
 						</a-button>
-					</div>
+					</div> -->
 				</div>
 			</template>
 			<template #bodyCell="{ column, record }">
@@ -66,7 +66,7 @@
 					<a-popconfirm title="确定要删除吗?" @confirm="deleteData(record)">
 						<a-button type="link" danger size="small">删除</a-button>
 					</a-popconfirm>
-					<a-button type="link" size="small" @click="configformRef.onOpen(record)">区域配置</a-button>
+					<a-button type="link" size="small" @click="leaveFor('/motoring/location', record)">监测点配置</a-button>
 				</template>
 			</template>
 			<!-- <template #expandedRowRender="{ record }">
@@ -138,17 +138,14 @@
 			</template> -->
 		</s-table>
 		<Form ref="formRef" @successful="tableRef.refresh(true)" />
-		<configForm ref="configformRef" @successful="tableRef.refresh(true)" />
 	</div>
 </template>
 
 <script setup>
-	import tool from '@/utils/tool'
+	import router from '@/router'
 	import setupApi from '@/api/basicset/setupApi'
 	import Form from './form.vue'
-	import configForm from './configForm.vue'
 	const formRef = ref()
-	const configformRef = ref()
 
 	const searchFormRef = ref()
 	const searchFormState = ref({})
@@ -192,6 +189,16 @@
 			return res
 		})
 	}
+
+	// 跳转到监测点界面
+	const leaveFor = (url, record) => {
+		router.push({
+			path: url,
+			query: {
+				id: record.id
+			}
+		})
+	}
 	// 重置
 	const reset = () => {
 		searchFormRef.value.resetFields()

+ 117 - 48
snowy-admin-web/src/views/motoring/location/form.vue

@@ -14,19 +14,30 @@
 			:label-col="{ style: { width: '110px', justifyContent: 'end' } }"
 		>
 			<a-row :gutter="10">
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+					<a-form-item label="监控对象" name="monitorTargetId">
+						<a-select
+							ref="select"
+							v-model:value="formData.monitorTargetId"
+							:options="monitorTargetOptions"
+							placeholder="请选择监控对象"
+							disabled
+						/>
+					</a-form-item>
+				</a-col>
 				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 					<a-form-item label="点位名称" name="name">
 						<a-input v-model:value="formData.name" placeholder="请输入点位名称" allow-clear />
 					</a-form-item>
 				</a-col>
-
 				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-					<a-form-item label="监控对象" name="monitorTargetId">
+					<a-form-item label="传感器类型" name="sensorType">
 						<a-select
 							ref="select"
-							v-model:value="formData.monitorTargetId"
-							:options="monitorTargetOptions"
-							placeholder="请选择监控对象"
+							v-model:value="formData.sensorType"
+							:options="sensorOptions"
+							placeholder="请选择传感器类型"
+							@change="sensorTypeChange"
 						/>
 					</a-form-item>
 				</a-col>
@@ -43,36 +54,40 @@
 					</a-form-item>
 				</a-col>
 
-				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="formData.monitorDeviceId">
 					<a-form-item label="传感器编号" name="sensorCode">
 						<a-input v-model:value="formData.sensorCode" disabled placeholder="请输入传感器编号" allow-clear />
 					</a-form-item>
 				</a-col>
 
-				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-					<a-form-item label="传感器类型" name="sensorType">
-						<a-select
-							ref="select"
-							v-model:value="formData.sensorType"
-							:options="sensorOptions"
-							placeholder="请选择传感器类型"
-						/>
+				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="formData.monitorDeviceId">
+					<a-form-item label="传感器路数" name="sensorRoute">
+						<a-radio-group v-model:value="formData.sensorRoute">
+							<a-radio-button v-for="i in sensorRouteMax" :key="i" :value="i" :disabled="isRouteDisabled(i)">
+								{{ i }}路
+							</a-radio-button>
+						</a-radio-group>
 					</a-form-item>
 				</a-col>
-				<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-					<a-form-item label="传感器路数" name="sensorRoute">
-						<a-input-number
-							v-model:value="formData.sensorRoute"
+
+				<!-- 报警接收人 -->
+				<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<a-form-item label="报警接收人" name="alarmUsers">
+						<a-select
+							v-model:value="formData.alarmUsers"
+							mode="multiple"
 							style="width: 100%"
-							:min="1"
-							:max="sensorRouteMax"
-							placeholder="请输入传感器路数"
-						/>
+							placeholder="请选择报警接收人"
+							:options="alarmUsersOptions"
+							:field-names="{ label: 'userName', value: 'openId' }"
+						></a-select>
 					</a-form-item>
 				</a-col>
 
-				<!-- 温湿度传感器就显示温度上限、温度下限,湿度上限、湿度下限.CO2传感器就显示CO2上限、CO2下限,若监控设备没有设置上下限,则表单禁用状态 -->
-				<div v-if="formData.sensorType && formData.sensorType !== 'CO2传感器'" class="form_item">
+				<div
+					class="form_item"
+					v-if="formData.sensorType == 'W' || formData.sensorType == 'WS' || formData.sensorType == 'WSC'"
+				>
 					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<a-form-item label="温度上限" name="temperatureUp">
 							<a-input-number
@@ -101,6 +116,9 @@
 							/>
 						</a-form-item>
 					</a-col>
+				</div>
+
+				<div class="form_item" v-if="formData.sensorType == 'WS' || formData.sensorType == 'WSC'">
 					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<a-form-item label="湿度上限" name="humidityUp">
 							<a-input-number
@@ -131,7 +149,7 @@
 					</a-col>
 				</div>
 
-				<div v-if="formData.sensorType && formData.sensorType == 'CO2传感器'" class="form_item">
+				<div class="form_item" v-if="formData.sensorType == 'WSC'">
 					<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<a-form-item label="CO2上限" name="co2Up">
 							<a-input-number
@@ -176,10 +194,11 @@
 	const emit = defineEmits({ successful: null })
 	const visible = ref(false) // 默认是关闭状态
 	const formRef = ref()
-	const formData = ref() // 表单数据
+	const formData = ref({ alarmUsers: [] }) // 表单数据
 	const sensorOptions = tool.dictList('SENSORTYPE') // 传感器类型
 	const monitorTargetOptions = ref([]) // 监控对象
 	const memListOptions = ref([]) // 监控设备数据
+	const alarmUsersOptions = ref([]) // 报警接收人数据
 
 	const temperatureMax = ref({ upMax: Infinity, downMax: Infinity }) // 温度最大值
 	const humidityMax = ref({ upMax: Infinity, downMax: Infinity }) // 湿度最大值
@@ -194,6 +213,7 @@
 		monitorDeviceId: [required('请选择监控设备')],
 		sensorType: [required('请选择传感器类型')],
 		sensorRoute: [required('请输入传感器路数')],
+		alarmUsers: [required('请选择报警接收人')],
 		temperatureUp: [{ validator: validateTemperature, trigger: ['change', 'blur'] }],
 		temperatureDown: [{ validator: validateTemperature, trigger: ['change', 'blur'] }],
 		humidityUp: [{ validator: validateHumidity, trigger: ['change', 'blur'] }],
@@ -255,17 +275,25 @@
 
 	// 打开抽屉
 	const onOpen = (record) => {
-		loadData()
+		setupListData()
 		visible.value = true
 		if (record) {
 			formData.value = Object.assign({}, record)
+
+			// 报警接收人回显
+			if (formData.value.alarmUsers && formData.value.alarmUsers.length > 0) {
+				formData.value.alarmUsers = formData.value.alarmUsers.map((item) => item.openId)
+			}
+			sensorType.value = formData.value.sensorType
+
+			memListData(sensorType.value)
 		} else {
-			formData.value = {}
+			formData.value = { alarmUsers: [] }
+			memListData()
 		}
 	}
-
-	const loadData = () => {
-		// 获取监控对象
+	// 获取监控对象 以及获取报警接收人的数据
+	const setupListData = () => {
 		setupApi.setupList({ isAll: false }).then((res) => {
 			monitorTargetOptions.value = (res || []).map((item) => {
 				return {
@@ -274,9 +302,15 @@
 					label: item['name']
 				}
 			})
+			const list = monitorTargetOptions.value.find((item) => item.value === formData.value.monitorTargetId)
+			alarmUsersOptions.value = list.alarmUsers || []
 		})
-		// 获取监控设备
-		memApi.memList({ isAll: false }).then((res) => {
+	}
+
+	const sensorType = ref() //选中的传感器类型
+	// 监控设备通过传感器类型来获取, sensorType可为空
+	const memListData = (value) => {
+		memApi.memList({ isAll: false, sensorType: value }).then((res) => {
 			memListOptions.value = (res || []).map((item) => {
 				return {
 					...item,
@@ -290,19 +324,34 @@
 		})
 	}
 
+	// 选中传感器类型
+	const sensorTypeChange = (value) => {
+		if (value) {
+			formData.value.monitorDeviceId = null
+			formData.value.sensorRoute = null
+			sensorRouteMax.value = 1
+			sensorType.value = value
+			memListData(value)
+		}
+	}
+
 	// 选中监控设备
 	const monitorDeviceIdChange = (value) => {
 		if (value) {
+			askRegionByDeviceIdData(value)
 			const data = memListOptions.value.find((item) => item.value === value)
-			formData.value.sensorCode = data.deviceCode //传感器编号
-			formData.value.modelName = data.modelName //监控设备型号
-			formData.value.deviceCode = data.deviceCode //冷链编号
-			formData.value.temperatureUp = data.temperatureUp //温度上限
-			formData.value.temperatureDown = data.temperatureDown //温度下限
-			formData.value.humidityUp = data.humidityUp //湿度上限
-			formData.value.humidityDown = data.humidityDown //湿度下限
-			formData.value.co2Up = data.co2Up //CO2上限
-			formData.value.co2Down = data.co2Down //CO2下限
+			formData.value = {
+				...formData.value,
+				sensorCode: data.deviceCode, //传感器编号
+				modelName: data.modelName, //监控设备型号
+				deviceCode: data.deviceCode, //冷链编号
+				temperatureUp: data.temperatureUp, //温度上限
+				temperatureDown: data.temperatureDown, //温度下限
+				humidityUp: data.humidityUp, //湿度上限
+				humidityDown: data.humidityDown, //湿度下限
+				co2Up: data.co2Up, //CO2上限
+				co2Down: data.co2Down //CO2下限
+			}
 			sensorRouteMax.value = data.sensorCount //传感器路数的最大值
 
 			temperatureMax.value = {
@@ -317,15 +366,23 @@
 				upMax: data.co2Up,
 				downMax: data.co2Down
 			}
+		}
+	}
 
-			console.log(humidityMax.value, 'xxxx')
+	const useSensorRoute = ref([]) //已使用的传感器路数
+	// 根据检测设备id获取已使用的路数
+	const askRegionByDeviceIdData = (value) => {
+		if (value) {
+			memApi.getRegionByDeviceIdData({ deviceId: value }).then((res) => {
+				useSensorRoute.value = res
+			})
 		}
 	}
 
-	// 关闭抽屉
-	const onClose = () => {
-		formRef.value.resetFields()
-		visible.value = false
+	// 检查该路是否已被禁用
+	const isRouteDisabled = (route) => {
+		// 通过遍历useSensorRoute中的数据,判断该路是否已被占用
+		return useSensorRoute.value.some((item) => item.sensorRoute === route)
 	}
 
 	// 验证并提交数据
@@ -333,7 +390,11 @@
 		formRef.value
 			.validate()
 			.then(() => {
-				locationApi.submitForm(formData.value, formData.value.id).then(() => {
+				const parameter = {
+					...formData.value,
+					alarmUsers: alarmUsersOptions.value.filter((user) => formData.value.alarmUsers.includes(user.openId))
+				}
+				locationApi.submitForm(parameter, formData.value.id).then(() => {
 					onClose()
 					emit('successful')
 				})
@@ -343,6 +404,14 @@
 			})
 	}
 
+	// 关闭抽屉
+	const onClose = () => {
+		memListOptions.value = []
+
+		formRef.value.resetFields()
+		visible.value = false
+	}
+
 	// 调用这个函数将子组件的一些数据和方法暴露出去
 	defineExpose({
 		onOpen

+ 25 - 4
snowy-admin-web/src/views/motoring/location/index.vue

@@ -1,5 +1,6 @@
 <template>
 	<div class="table_item">
+		<a-page-header title="返回" sub-title="监测点配置" @back="goBack" style="padding: 20px 0" />
 		<s-table
 			ref="tableRef"
 			:columns="columns"
@@ -36,7 +37,7 @@
 				<!-- 其他操作区域 -->
 				<div class="table-head-btn">
 					<div class="btn-left">
-						<a-button type="primary" @click="formRef.onOpen()">
+						<a-button type="primary" @click="formRef.onOpen({ monitorTargetId: queryId })">
 							<template #icon><plus-outlined /></template>新增
 						</a-button>
 					</div>
@@ -57,11 +58,14 @@
 
 <script setup>
 	import locationApi from '@/api/basicset/locationApi.js'
+	import { useRoute } from 'vue-router'
+	import router from '@/router'
 	import Form from './form.vue'
 	const formRef = ref()
 	const searchFormRef = ref()
 	const searchFormState = ref({})
 	const tableRef = ref()
+	const Route = useRoute()
 
 	const columns = [
 		{
@@ -119,10 +123,26 @@
 	const handleResizeColumn = (w, col) => {
 		col.width = w
 	}
+
+	const queryId = ref() //监控对象的id
+	onBeforeMount(() => {
+		if (Route.query.id) {
+			queryId.value = Route.query.id
+		}
+	})
+
+	// 返回上一页
+	const goBack = () => {
+		router.go(-1)
+	}
+
 	const loadData = (parameter) => {
-		return locationApi.locationPage(Object.assign(parameter, searchFormState.value)).then((res) => {
-			return res
-		})
+		if (queryId.value) {
+			parameter.monitorTargetId = queryId.value
+			return locationApi.locationPage(Object.assign(parameter, searchFormState.value)).then((res) => {
+				return res
+			})
+		}
 	}
 	// 重置
 	const reset = () => {
@@ -147,6 +167,7 @@
 	.table_item {
 		padding: 15px 20px;
 		background-color: #ffffff;
+
 		:deep(.ant-table-pagination-right) {
 			justify-content: center !important;
 		}

+ 2 - 2
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/controller/MonitorDeviceController.java

@@ -130,8 +130,8 @@ public class MonitorDeviceController {
     @Operation(summary = "获取监控设备列表")
     @SaCheckPermission("/coldchain/monitordevice/list")
     @GetMapping("/coldchain/monitordevice/list")
-    public CommonResult<List<MonitorDevice>> list(Boolean isAll) {
-        return CommonResult.data(monitorDeviceService.myList(isAll));
+    public CommonResult<List<MonitorDevice>> list(Boolean isAll,String sensorType) {
+        return CommonResult.data(monitorDeviceService.myList(isAll,sensorType));
     }
 
     /**

+ 1 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/MonitorDeviceService.java

@@ -100,7 +100,7 @@ public interface MonitorDeviceService extends IService<MonitorDevice> {
 
     List<SensorData> querySensorData(String deviceId, int roads, Instant startTime, Instant endTime, List<QueryCondition> queryConditions);
 
-    List<MonitorDevice> myList(Boolean isAll);
+    List<MonitorDevice> myList(Boolean isAll,String sensorType);
 
     boolean getByDeviceName(String deviceName);
 

+ 13 - 5
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevice/service/impl/MonitorDeviceServiceImpl.java

@@ -250,14 +250,22 @@ public class MonitorDeviceServiceImpl extends ServiceImpl<MonitorDeviceMapper, M
 
 
     @Override
-    public List<MonitorDevice> myList(Boolean isAll) {
-        LambdaQueryWrapper<MonitorDevice> queryWrapper = new LambdaQueryWrapper<>();
+    public List<MonitorDevice> myList(Boolean isAll,String sensorType) {
+        LambdaQueryWrapper<MonitorDevice> deviceQueryWrapper = new LambdaQueryWrapper<>();
+        LambdaQueryWrapper<MonitorDeviceType> typeQueryWrapper = new LambdaQueryWrapper<>();
+        if (sensorType != null) {
+            typeQueryWrapper.eq(MonitorDeviceType::getSensorType, sensorType).eq(MonitorDeviceType::getDeleteFlag,CommonDeleteFlagEnum.NOT_DELETE);
+        }
+        List<MonitorDeviceType> list = monitorDeviceTypeService.list(typeQueryWrapper);
+        for (MonitorDeviceType deviceType : list) {
+            deviceQueryWrapper.or().eq(MonitorDevice::getModelName,deviceType.getId());
+        }
         if (!isAll) {
-            queryWrapper.eq(MonitorDevice::getStatus, MonitorDeviceStatusEnum.NORMAL.getValue())
+            deviceQueryWrapper.eq(MonitorDevice::getStatus, MonitorDeviceStatusEnum.NORMAL.getValue())
                     .orderByAsc(MonitorDevice::getSortCode);
         }
-        queryWrapper.eq(MonitorDevice::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE);
-        return list(queryWrapper);
+        deviceQueryWrapper.eq(MonitorDevice::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE);
+        return list(deviceQueryWrapper);
     }
 
     // 通用更新方法,避免代码重复,并处理 timestamp 为空的情况

+ 2 - 2
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/controller/MonitorDeviceTypeController.java

@@ -127,8 +127,8 @@ public class MonitorDeviceTypeController {
     @Operation(summary = "获取监控设备类型列表")
     @SaCheckPermission("/coldchain/monitordevicetype/list")
     @GetMapping("/coldchain/monitordevicetype/list")
-    public CommonResult<List<MonitorDeviceType>> list() {
-        return CommonResult.data(monitorDeviceTypeService.list());
+    public CommonResult<List<MonitorDeviceType>> list(String sensorType) {
+        return CommonResult.data(monitorDeviceTypeService.myList(sensorType));
     }
 
     /**

+ 2 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/service/MonitorDeviceTypeService.java

@@ -81,4 +81,6 @@ public interface MonitorDeviceTypeService extends IService<MonitorDeviceType> {
     boolean getByName(String name);
 
     boolean getByCode(String code);
+
+    List<MonitorDeviceType> myList(String sensorType);
 }

+ 9 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitordevicetype/service/impl/MonitorDeviceTypeServiceImpl.java

@@ -95,6 +95,15 @@ public class MonitorDeviceTypeServiceImpl extends ServiceImpl<MonitorDeviceTypeM
         return !types.isEmpty();
     }
 
+    @Override
+    public List<MonitorDeviceType> myList(String sensorType) {
+        LambdaQueryWrapper<MonitorDeviceType> queryWrapper = new LambdaQueryWrapper<>();
+        if (sensorType != null) {
+            queryWrapper.eq(MonitorDeviceType::getSensorType, sensorType);
+        }
+        return list(queryWrapper);
+    }
+
     public List<MonitorDeviceType> getTypeByName(String name) {
         return this.list(new LambdaQueryWrapper<MonitorDeviceType>()
                 .eq(MonitorDeviceType::getName, name).eq(MonitorDeviceType::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE));

+ 1 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortarget/controller/MonitorTargetController.java

@@ -148,7 +148,7 @@ public class MonitorTargetController {
     @Operation(summary = "获取监控对象列表")
     @SaCheckPermission("/coldchain/monitortarget/list")
     @GetMapping("/coldchain/monitortarget/list")
-    public CommonResult<List<MonitorTarget>> list(Boolean isAll) {
+    public CommonResult<List<MonitorTarget>> list(Boolean isAll,String sensorType) {
         return CommonResult.data(monitorTargetService.myList(isAll));
     }
 }

+ 10 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/controller/MonitorTargetRegionController.java

@@ -141,4 +141,14 @@ public class MonitorTargetRegionController {
     public CommonResult<List<MonitorTargetRegion>> listByTargetId(String targetId) {
         return CommonResult.data(monitorTargetRegionService.listByTargetId(targetId));
     }
+
+    /**
+     * 根据检测设备id获取监测点位列表
+     */
+    @Operation(summary = "根据检测设备id获取监测点位列表")
+    @SaCheckPermission("/coldchain/monitordevice/getRegionByDeviceId")
+    @GetMapping("/coldchain/monitordevice/getRegionByDeviceId")
+    public CommonResult<List<MonitorTargetRegion>> listByDeviceId(String deviceId) {
+        return CommonResult.data(monitorTargetRegionService.listByDeviceId(deviceId));
+    }
 }

+ 1 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/entity/MonitorTargetRegion.java

@@ -168,7 +168,7 @@ public class MonitorTargetRegion extends CommonEntity {
      */
     @Schema(description = "告警接收人,存储告警通知的接收用户信息")
     @TableField(value = "alarm_users", typeHandler = SensorAlarmUserTypeHandler.class)
-    @JsonIgnore
+//    @JsonIgnore
     private List<SensorAlarmUser> alarmUsers = Lists.newArrayList();
 
     /**

+ 1 - 1
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/param/MonitorTargetRegionPageParam.java

@@ -65,7 +65,7 @@ public class MonitorTargetRegionPageParam {
     /**
      * 监控监控对象
      */
-    @Schema(description = "监控监控对象")
+    @Schema(description = "监控对象")
     private String monitorTargetId;
 
 }

+ 5 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/service/MonitorTargetRegionService.java

@@ -106,4 +106,9 @@ public interface MonitorTargetRegionService extends IService<MonitorTargetRegion
      * 获取已使用总路数
      */
     Integer getUsedSensorCount();
+
+    /**
+     * 根据检测设备id获取监测点位列表
+     */
+    List<MonitorTargetRegion> listByDeviceId(String deviceId);
 }

+ 9 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/monitortargetregion/service/impl/MonitorTargetRegionServiceImpl.java

@@ -210,6 +210,15 @@ public class MonitorTargetRegionServiceImpl extends ServiceImpl<MonitorTargetReg
         return (int)count();
     }
 
+    @Override
+    public List<MonitorTargetRegion> listByDeviceId(String deviceId) {
+        LambdaQueryWrapper<MonitorTargetRegion> queryWrapper = new LambdaQueryWrapper<>();
+        if (deviceId != null) {
+            queryWrapper.eq(MonitorTargetRegion::getMonitorDeviceId, deviceId);
+        }
+        return list(queryWrapper);
+    }
+
     private void fillParentLocationInfo(List<MonitorTargetRegion> resourceList) {
         if (CollUtil.isNotEmpty(resourceList)) {
             List<MonitorTargetRegion> locationTypes = resourceList.stream().filter(distinctByKey(MonitorTargetRegion::getParentId)).collect(Collectors.toList());

+ 31 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/config/PushConfigure.java

@@ -35,6 +35,12 @@ public class PushConfigure {
      */
     private static String pagePath;
 
+//    private static String redirectUrl;
+
+    private static String accessTokenUrl;
+
+    private static String userInfoUrl;
+
     public static String getAppId() {
         return appId;
     }
@@ -74,4 +80,29 @@ public class PushConfigure {
     public void setPagePath(String pagePath) {
         PushConfigure.pagePath = pagePath;
     }
+
+//    public static String getRedirectUrl() {
+//        return redirectUrl;
+//    }
+//
+//    public void setRedirectUrl(String redirectUrl) {
+//        PushConfigure.redirectUrl = redirectUrl;
+//    }
+
+    public static String getAccessTokenUrl() {
+        return accessTokenUrl;
+    }
+
+    public void setAccessTokenUrl(String getAccessTokenUrl) {
+        PushConfigure.accessTokenUrl = getAccessTokenUrl;
+    }
+
+    public static String getUserInfoUrl() {
+        return userInfoUrl;
+    }
+
+    public void setUserInfoUrl(String getUserInfoUrl) {
+        PushConfigure.userInfoUrl = getUserInfoUrl;
+    }
+
 }

+ 85 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/entity/WeChatUser.java

@@ -0,0 +1,85 @@
+package vip.xiaonuo.coldchain.modular.push.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+public class WeChatUser {
+    /**
+     * 用户id
+     */
+    private String userId;
+
+    /**
+     * 用户唯一标识
+     */
+    private String openid;
+
+    /**
+     * access_token
+     */
+    private String accessToken;
+
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+
+    /**
+     * 性别(0未知,1男性,2女性)
+     */
+    private String sex;
+
+    /**
+     * 用户省份
+     */
+    private String province;
+
+    /**
+     * 用户城市
+     */
+    private String city;
+
+    /**
+     * 国家
+     */
+    private String country;
+
+    /**
+     * 用户头像
+     */
+    private String avatar;
+
+    /**
+     * 用户特权信息,json 数组
+     */
+    private String privilege;
+
+    /**
+     * unionid
+     */
+    private String unionid;
+
+    /**
+     * 创建用户
+     */
+    private String createUser;
+
+    /**
+     * 更新用户
+     */
+    private String updateUser;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createDate;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateDate;
+}

+ 34 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/utils/PushUtil.java

@@ -2,6 +2,8 @@ package vip.xiaonuo.coldchain.modular.push.utils;
 
 
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
 import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
@@ -9,15 +11,27 @@ import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
 import me.chanjar.weixin.mp.config.WxMpConfigStorage;
 import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
 import vip.xiaonuo.coldchain.modular.push.config.PushConfigure;
+import vip.xiaonuo.coldchain.modular.push.entity.WeChatUser;
 import vip.xiaonuo.coldchain.modular.push.param.PushParam;
 
+import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.Map;
 import java.util.Objects;
 
 /**
  * 推送类
  */
 public class PushUtil {
+    private final static String TOKEN = "abcd1234";
+    private final static String ENCODING = "UTF-8";
+    private final static String ACCESS_TOKEN = "access_token";
+    private final static String REFRESH_TOKEN = "refresh_token";
+    private final static String OPEN_ID = "openid";
+    private final static String NICK_NAME = "nickname";
+    private final static String SEX = "sex";
+    private final static String HEAD_IMG_URL = "headimgurl";
+
     private static WxMpConfigStorage wxMpConfigStorage() {
         WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
         config.setAppId(PushConfigure.getAppId());
@@ -81,4 +95,24 @@ public class PushUtil {
         }
         return pushCode;
     }
+
+    public static WeChatUser getUserInfo(String code) {
+        Map<?, ?> result = WeChatUtil.getAccessToken(code);
+        String accessToken = result.get(ACCESS_TOKEN).toString();
+        String openid = result.get(OPEN_ID).toString();
+        String userInfoJsom = WeChatUtil.getUserInfo(accessToken, openid);
+        // 解析JSON数据
+        JSONObject jsonObject = new JSONObject(userInfoJsom);
+
+        // 设置相关实体属性
+        WeChatUser weChatUser = new WeChatUser();
+        weChatUser.setAccessToken(accessToken);
+        weChatUser.setCreateDate(LocalDateTime.now());
+        weChatUser.setUpdateDate(LocalDateTime.now());
+        weChatUser.setOpenid(openid);
+        weChatUser.setNickname(jsonObject.getStr(NICK_NAME));
+        weChatUser.setSex(jsonObject.getStr(SEX));
+        weChatUser.setAvatar(jsonObject.getStr(HEAD_IMG_URL));
+        return weChatUser;
+    }
 }

+ 104 - 0
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/push/utils/WeChatUtil.java

@@ -0,0 +1,104 @@
+package vip.xiaonuo.coldchain.modular.push.utils;
+
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import vip.xiaonuo.coldchain.modular.push.config.PushConfigure;
+
+import java.util.Map;
+
+
+
+/**
+ * 微信登录工具类
+ *
+ */
+public class WeChatUtil {
+
+    private final static String ERROR_CODE = "errcode";
+    private final static String accessTokenUrl = PushConfigure.getAccessTokenUrl();
+    private final static String appId = PushConfigure.getAppId();
+    private final static String secret = PushConfigure.getSecret();
+    private final static String userInfoUrl = PushConfigure.getUserInfoUrl();
+
+    /**
+     * 获取微信授权code
+     *
+     * @param state state信息
+     * @return 返回微信授权code的URL
+     */
+//    public static String getUrl() {
+//
+//        try {
+//            StringBuffer url = new StringBuffer();
+//            url.append(GET_CODE_URL)
+//                    .append("?appid=")
+//                    .append(APPID)
+//                    .append("&redirect_uri=")
+//                    .append(URLEncoder.encode(REDIRECT_URL, "UTF-8"))
+//                    .append("&response_type=code&scope=snsapi_userinfo&state=STATE")
+//                    .append("#wechat_redirect");
+//            return url.toString();
+//        } catch (UnsupportedEncodingException e) {
+//            throw new RuntimeException("URL格式化异常");
+//        }
+//
+//    }
+
+    /**
+     * 获取微信AccessToken
+     *
+     * @param code 用户code
+     * @return 返回包含微信AccessToken的Map
+     */
+    public static Map<?, ?> getAccessToken(String code) {
+        StringBuffer url = new StringBuffer();
+        url.append(accessTokenUrl)
+                .append("?appid=").append(appId)
+                .append("&secret=").append(secret)
+                .append("&code=").append(code)
+                .append("&grant_type=authorization_code");
+        String rs = HttpUtil.get(url.toString());
+        Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
+        if (null == map.get(ERROR_CODE)) {
+            return map;
+        } else {
+            throw new RuntimeException("获取access_token出错");
+        }
+    }
+
+    /**
+     * 刷新AccessToken
+     *
+     * @param refreshToken 用户刷新token
+     * @return 返回包含刷新后的微信AccessToken的Map
+     */
+//    public static Map<?, ?> refreshToken(String refreshToken) {
+//        StringBuffer url = new StringBuffer();
+//        url.append(REFRESH_TOKEN_URL)
+//                .append("?appid=").append(APPID)
+//                .append("&grant_type=refresh_token&refresh_token=").append(refreshToken);
+//        String rs = HttpUtil.get(url.toString());
+//        Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
+//        if (null == map.get(ERROR_CODE)) {
+//            return map;
+//        } else {
+//            throw new RuntimeException("刷新access_token出错");
+//        }
+//    }
+
+    /**
+     * 获取用户信息
+     *
+     * @param accessToken 微信AccessToken
+     * @param openid 用户的openid
+     * @return 返回包含用户信息的JSON字符串
+     */
+    public static String getUserInfo(String accessToken, String openid) {
+        StringBuffer url = new StringBuffer();
+        url.append(userInfoUrl)
+                .append("?access_token=").append(accessToken)
+                .append("&openid=").append(openid)
+                .append("&lang=zh_CN");
+        return HttpUtil.get(url.toString());
+    }
+}

+ 2 - 1
snowy-web-app/src/main/resources/application.properties

@@ -243,4 +243,5 @@ wechat.appID=wx49b1fb6f9c0d0b8d
 wechat.secret=6b177348efc2b21da105fc126b933db9
 wechat.templateId=WgKOAJrnNhnr2lIkfI_vppfY--7oImjddrd4GPnE_UA
 wechat.miniProgram=wx1eebc072a607c055
-wechat.pagePath=/pages/message/message
+wechat.getAccessTokenUrl=https://api.weixin.qq.com/sns/oauth2/access_token
+wechat.getUserInfoUrl=https://api.weixin.qq.com/sns/userinfo