<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import http from '@/utils/http.js'
// 响应式数据
const showMenuPopup = ref(false)
const longPressTimer = ref(null)
const pressDuration = 800
const currentLongPressDevice = ref(null)
const touchStartTime = ref(0)
const hasTriggeredLongPress = ref(false)
const touchPosition = reactive({ x: 0, y: 0 })
// 登录token数据
const refreshToken = ref('')
const resourceToken = ref('')
const userInfo = ref(null)
const qxdmData = ref({})
const category = ref([
{ name: '视频监控', id: 'spjk' },
{ name: '人像抓拍', id: 'rxzp' },
{ name: '车辆抓拍', id: 'clzp' },
{ name: '人脸门禁', id: 'rlmj' },
{ name: '消防主机', id: 'xfzj' },
{ name: '电流传感', id: 'dlcg' },
{ name: '水位水压', id: 'swsy' },
{ name: '烟感探测', id: 'ygtc' },
{ name: '气体探测', id: 'qttc' },
{ name: '访客登记', id: 'fkdj' },
{ name: '雨量监测', id: 'yljc' },
{ name: '智能机状态', id: 'znjzt' },
{ name: '智能算法', id: 'znsf' },
{ name: '无线广播', id: 'wxgb' },
{ name: '定制设备', id: 'dzsb' }
])
const detail = ref([])
const toView = ref('spjk')
const height = ref('100vh')
const isIpad = ref(false)
const showAddModal = ref(false)
const showClearModal = ref(false)
const currentCategory = ref('')
const isDataLoaded = ref(false)
const newDevice = reactive({
name: '',
manufacturer: '自定义设备'
})
const formErrors = reactive({
name: '',
manufacturer: ''
})
// 计算属性
const isFormValid = computed(() => {
return currentCategory.value &&
newDevice.name.trim() &&
newDevice.manufacturer.trim() &&
!formErrors.name &&
!formErrors.manufacturer
})
const hasCustomDevices = computed(() => {
return detail.value.some(category =>
category && category.customDetail && category.customDetail.length > 0
)
})
const formatQxdmData = (data) => {
if (!data || typeof data !== 'object') return '无数据'
try {
return JSON.stringify(data)
} catch (error) {
return '格式化错误'
}
}
// 获取登录存储的数据
const getLoginData = () => {
try {
const storedRefreshToken = uni.getStorageSync('refreshToken')
const storedResourceToken = uni.getStorageSync('resourceToken')
const storedUserInfo = uni.getStorageSync('userInfo')
console.log('=== 获取登录存储的数据 ===')
console.log('refreshToken:', storedRefreshToken ? '存在' : '不存在')
console.log('resourceToken:', storedResourceToken ? '存在' : '不存在')
console.log('userInfo:', storedUserInfo)
if (!storedResourceToken) {
console.warn('❌ 未找到resourceToken,用户可能未登录')
return false
}
refreshToken.value = storedRefreshToken
resourceToken.value = storedResourceToken
userInfo.value = storedUserInfo
console.log('✅ 成功获取登录数据')
return true
} catch (error) {
console.error('获取登录数据失败:', error)
return false
}
}
// 设置qxdm数据的方法
const setQxdmData = (data) => {
try {
qxdmData.value = data
uni.setStorageSync('qxdmData', data)
console.log('✅ qxdm数据设置成功:', data)
return true
} catch (error) {
console.error('设置qxdm数据失败:', error)
return false
}
}
// 获取qxdm参数数据
const getQxdmData = () => {
try {
// 首先尝试从存储获取
const storedQxdmData = uni.getStorageSync('qxdmData') || {}
console.log('=== 获取qxdm参数数据 ===')
console.log('从存储获取的qxdmData:', storedQxdmData)
// 如果存储中有数据,使用存储的数据
if (storedQxdmData && Object.keys(storedQxdmData).length > 0) {
qxdmData.value = storedQxdmData
console.log('✅ 从存储成功获取qxdm参数数据:', qxdmData.value)
return true
}
// 如果存储中没有,尝试从 http 实例获取(如果存在该方法)
if (http && typeof http.getAllQxdmData === 'function') {
const httpQxdmData = http.getAllQxdmData()
console.log('从http实例获取的qxdmData:', httpQxdmData)
if (httpQxdmData && Object.keys(httpQxdmData).length > 0) {
qxdmData.value = httpQxdmData
// 同时保存到存储中
setQxdmData(httpQxdmData)
console.log('✅ 从http实例成功获取qxdm参数数据:', qxdmData.value)
return true
}
}
console.warn('未找到qxdm参数数据')
return false
} catch (error) {
console.error('获取qxdm参数数据失败:', error)
return false
}
}
// 根据设备ID获取qxdm
const getQxdmByDeviceId = (deviceId) => {
if (!deviceId || !qxdmData.value) return ''
const qxdm = qxdmData.value[deviceId] || ''
console.log(`获取设备 ${deviceId} 的qxdm:`, qxdm)
return qxdm
}
// 验证登录状态
const validateLoginStatus = () => {
if (!resourceToken.value) {
const hasLoginData = getLoginData()
if (!hasLoginData) {
uni.showToast({
title: '请先登录',
icon: 'none',
duration: 2000
})
return false
}
}
return true
}
const handleScrollViewClick = () => {
if (showMenuPopup.value) {
hideMenu()
}
}
const handleTouchStart = (device, event) => {
touchStartTime.value = Date.now()
currentLongPressDevice.value = device
hasTriggeredLongPress.value = false
const touch = event.touches[0]
touchPosition.x = touch.clientX
touchPosition.y = touch.clientY
clearLongPressTimer()
longPressTimer.value = setTimeout(() => {
hasTriggeredLongPress.value = true
showMenu(device)
}, pressDuration)
}
const handleTouchMove = () => {
clearLongPressTimer()
}
const handleTouchEnd = () => {
clearLongPressTimer()
hasTriggeredLongPress.value = false
}
const clearLongPressTimer = () => {
if (longPressTimer.value) {
clearTimeout(longPressTimer.value)
longPressTimer.value = null
}
}
const showMenu = (device) => {
showMenuPopup.value = true
currentLongPressDevice.value = device
console.log('显示长按菜单,设备:', device)
if (uni.vibrateShort) {
uni.vibrateShort()
}
}
const hideMenu = () => {
showMenuPopup.value = false
currentLongPressDevice.value = null
hasTriggeredLongPress.value = false
}
const getMenuPosition = () => {
return {
left: '50%',
top: '100%',
transform: 'translateX(-50%)'
}
}
const handleMenuAction = (device, category) => {
if (!currentLongPressDevice.value) return
console.log('执行菜单操作: 查看, 设备:', currentLongPressDevice.value)
goToPlayPage(device, category)
hideMenu()
}
const handleDeviceClick = (device, category) => {
if (hasTriggeredLongPress.value) {
hasTriggeredLongPress.value = false
return
}
goToPlayPage(device, category)
}
const initData = () => {
const baseData = [
{
cate: '视频监控',
id: 'spjk',
banner: '/static/image/jiankong.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '人像抓拍',
id: 'rxzp',
banner: '/static/image/rxzp.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '车辆抓拍',
id: 'clzp',
banner: '/static/image/rxzp.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '人脸门禁',
id: 'rlmj',
banner: '/static/image/rl.png',
originalDetail: [],
customDetail: []
},
{
cate: '消防主机',
id: 'xfzj',
banner: '/static/image/xfzj.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '电流传感',
id: 'dlcg',
banner: '/static/image/dl.png',
originalDetail: [],
customDetail: []
},
{
cate: '水位水压',
id: 'swsy',
banner: '/static/image/swsy.jpeg',
originalDetail: [],
customDetail: []
},
{
cate: '烟感探测',
id: 'ygtc',
banner: '/static/image/yangan.webp',
originalDetail: [],
customDetail: []
},
{
cate: '气体探测',
id: 'qttc',
banner: '/static/image/tc.png',
originalDetail: [],
customDetail: []
},
{
cate: '访客登记',
id: 'fkdj',
banner: '/static/image/fkdj.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '雨量监测',
id: 'yljc',
banner: '/static/image/yl.png',
originalDetail: [],
customDetail: []
},
{
cate: '智能机状态',
id: 'znjzt',
banner: '/static/image/znj.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '智能算法',
id: 'znsf',
banner: '/static/image/znsf.jpg',
originalDetail: [],
customDetail: []
},
{
cate: '无线广播',
id: 'wxgb',
banner: '/static/image/wxgb.png',
originalDetail: [],
customDetail: []
},
{
cate: '定制设备',
id: 'dzsb',
banner: '/static/image/znj.jpg',
originalDetail: [],
customDetail: []
}
]
detail.value = JSON.parse(JSON.stringify(baseData))
isDataLoaded.value = true
loadCustomDevices()
}
const loadCustomDevices = () => {
try {
console.log('=== 开始加载自定义设备 ===')
const customDevices = uni.getStorageSync('customDevices') || {}
console.log('从存储加载的自定义设备:', customDevices)
detail.value.forEach(category => {
if (category && typeof category === 'object') {
if (!category.customDetail) {
category.customDetail = []
} else {
category.customDetail = []
}
}
})
Object.keys(customDevices).forEach(categoryName => {
const devices = customDevices[categoryName] || []
console.log(`分类 "${categoryName}" 有 ${devices.length} 个设备`)
const targetCategory = detail.value.find(item => {
if (!item || !item.cate) return false
return item.cate === categoryName
})
if (targetCategory && Array.isArray(devices)) {
targetCategory.customDetail = [...devices]
console.log(`已将 ${devices.length} 个设备分配到分类 "${categoryName}"`)
devices.forEach((device, index) => {
console.log(`设备 ${index + 1}:`, {
id: device.id,
name: device.name,
deviceName: device.deviceName,
manufacturer: device.manufacturer
})
})
} else {
console.warn(`未找到分类: "${categoryName}" 或设备数据不是数组,跳过这些设备`)
}
})
console.log('=== 自定义设备加载完成 ===', detail.value)
} catch (error) {
console.error('加载自定义设备失败:', error)
safeResetDetail()
}
}
const safeResetDetail = () => {
try {
detail.value = detail.value.map(category => {
if (category && typeof category === 'object') {
return {
...category,
customDetail: Array.isArray(category.customDetail) ? category.customDetail : []
}
}
return category
})
} catch (error) {
console.error('重置数据失败:', error)
initData()
}
}
const saveCustomDevice = (deviceData) => {
try {
console.log('=== 开始保存设备 ===', deviceData)
let customDevices = uni.getStorageSync('customDevices') || {}
const category = deviceData.deviceType || currentCategory.value
console.log('设备将保存到分类:', category)
if (!category) {
uni.showToast({
title: '设备分类不能为空',
icon: 'none'
})
return
}
if (!customDevices[category]) {
customDevices[category] = []
}
const deviceId = deviceData.id || 'custom_' + Date.now()
const deviceNameToSave = deviceData.deviceName || deviceData.name || '未命名设备'
const customDevice = {
thumb: deviceData.thumb || '/static/image/test.png',
name: deviceData.name || '未命名设备',
deviceName: deviceNameToSave,
manufacturer: deviceData.manufacturer || '自定义设备',
id: deviceId,
device_id: deviceData.device_id || deviceId,
isCustom: true,
playUrl: deviceData.playUrl || '',
deviceType: category,
addTime: new Date().getTime(),
// 保存qxdm参数到单独的字段
communityQxdm: deviceData.communityQxdm || getQxdmByDeviceId(deviceId) || deviceData.qxdm
}
console.log('要保存的设备信息:', customDevice)
console.log('包含的社区qxdm:', customDevice.communityQxdm)
const existingIndex = customDevices[category].findIndex(device =>
device && device.id === customDevice.id
)
if (existingIndex === -1) {
customDevices[category].push(customDevice)
console.log(`设备已添加到分类 "${category}"`, {
name: customDevice.name,
deviceName: customDevice.deviceName,
id: customDevice.id,
communityQxdm: customDevice.communityQxdm
})
} else {
customDevices[category][existingIndex] = customDevice
console.log(`设备已在分类 "${category}" 中更新`, {
name: customDevice.name,
deviceName: customDevice.deviceName,
id: customDevice.id,
communityQxdm: customDevice.communityQxdm
})
}
uni.setStorageSync('customDevices', customDevices)
console.log('设备保存成功,所有自定义设备:', customDevices)
loadCustomDevices()
uni.showToast({
title: '设备添加成功',
icon: 'success',
duration: 2000
})
} catch (error) {
console.error('保存设备失败:', error)
uni.showToast({
title: '保存失败',
icon: 'none',
duration: 2000
})
}
}
const setupEventListeners = () => {
uni.$on('deviceAddedFromAddDevice', handleDeviceAddedFromAddDevice)
uni.$on('deviceAddedFromChannel', handleDeviceAddedFromChannel)
}
const removeEventListeners = () => {
uni.$off('deviceAddedFromAddDevice', handleDeviceAddedFromAddDevice)
uni.$off('deviceAddedFromChannel', handleDeviceAddedFromChannel)
}
const handleDeviceAddedFromAddDevice = (deviceData) => {
console.log('=== 接收到从添加设备页面返回的设备数据 ===', deviceData)
if (deviceData && deviceData.deviceName) {
console.log(' 接收到 deviceName:', deviceData.deviceName)
} else {
console.log('未接收到 deviceName,使用 name:', deviceData.name)
}
saveCustomDevice(deviceData)
}
const handleDeviceAddedFromChannel = (deviceData) => {
console.log('=== 接收到从通道列表页面返回的设备数据 ===', deviceData)
if (deviceData && deviceData.deviceName) {
console.log('✅ 接收到 deviceName:', deviceData.deviceName)
} else {
console.log('❌ 未接收到 deviceName,使用 name:', deviceData.name)
}
saveCustomDevice(deviceData)
}
const capturePicture = (item, deviceType) => {
if (!item) return
if (item.isCustom) {
goToPlayPage(item, deviceType)
return
}
const params = {
manufacturer: item.manufacturer || item.name,
type: deviceType,
fromPage: 'category',
name: item.name,
isCustom: false
}
console.log('跳转到通道页面,参数:', params)
uni.navigateTo({
url: `/pages/chanel/index?manufacturer=${encodeURIComponent(JSON.stringify(params))}`,
success: () => {
console.log('成功跳转到通道页面')
},
fail: (err) => {
console.error('跳转到通道页面失败:', err)
}
})
}
const goToPlayPage = (item, deviceType) => {
if (!item) return
console.log('跳转到播放页面:', item)
const channelData = {
channel: {
device_id: item.device_id || item.id,
id: item.id,
name: item.name,
deviceName: item.deviceName || item.name,
manufacturer: item.manufacturer,
model: item.model || '自定义设备',
status: item.status || 1
},
playStreamUrl: item.playUrl || '',
timestamp: Date.now(),
fromPage: 'deviceCategory'
}
console.log('传递给播放页面的数据:', channelData)
uni.navigateTo({
url: `/pages/address/index?channelData=${encodeURIComponent(JSON.stringify(channelData))}`,
success: () => {
console.log('成功跳转到播放页面')
},
fail: (err) => {
console.error('跳转到播放页面失败:', err)
uni.showToast({
title: '跳转失败',
icon: 'none'
})
}
})
}
const showAddDialog = (category) => {
currentCategory.value = category
resetFormErrors()
// 点击添加按钮时获取登录数据
const hasLoginData = getLoginData()
if (!hasLoginData) {
uni.showToast({
title: '请先登录',
icon: 'none',
duration: 2000
})
return
}
// 获取qxdm参数数据
getQxdmData()
showAddModal.value = true
}
const hideAddDialog = () => {
showAddModal.value = false
resetNewDevice()
resetFormErrors()
}
const resetNewDevice = () => {
newDevice.name = ''
newDevice.manufacturer = '自定义设备'
}
const resetFormErrors = () => {
formErrors.name = ''
formErrors.manufacturer = ''
}
const validateName = () => {
const name = newDevice.name.trim()
if (!name) {
formErrors.name = '设备名称不能为空'
} else if (name.length < 2) {
formErrors.name = '设备名称至少2个字符'
} else if (name.length > 20) {
formErrors.name = '设备名称不能超过20个字符'
} else {
formErrors.name = ''
}
}
const validateManufacturer = () => {
const manufacturer = newDevice.manufacturer.trim()
if (!manufacturer) {
formErrors.manufacturer = '设备厂商不能为空'
} else if (manufacturer.length < 2) {
formErrors.manufacturer = '设备厂商至少2个字符'
} else if (manufacturer.length > 30) {
formErrors.manufacturer = '设备厂商不能超过30个字符'
} else {
formErrors.manufacturer = ''
}
}
const confirmAndNavigate = () => {
if (!isFormValid.value) {
uni.showToast({
title: '请完善设备信息',
icon: 'none'
})
return
}
// 验证登录状态
if (!validateLoginStatus()) {
return
}
// 生成设备ID
const deviceId = 'custom_' + Date.now()
const params = {
category: currentCategory.value,
deviceName: newDevice.name.trim(),
name: newDevice.name.trim(),
manufacturer: newDevice.manufacturer.trim(),
fromPage: 'deviceCategory',
actionType: 'addCustom',
deviceId: deviceId,
tokens: {
refreshToken: refreshToken.value,
resourceToken: resourceToken.value,
userInfo: userInfo.value,
qxdmData: qxdmData.value
}
}
console.log('跳转到添加设备页面,参数:', params)
console.log('传递的数据:', {
refreshToken: refreshToken.value ? '存在' : '不存在',
resourceToken: resourceToken.value ? '存在' : '不存在',
userInfo: userInfo.value ? '存在' : '不存在',
qxdmData: formatQxdmData(qxdmData.value) // 使用格式化显示
})
console.log('生成的设备ID:', deviceId)
hideAddDialog()
uni.navigateTo({
url: `/pages/addDevice/index?channelData=${encodeURIComponent(JSON.stringify(params))}`,
success: () => {
console.log('成功跳转到添加设备页面')
},
fail: (err) => {
console.error('跳转到添加设备页面失败:', err)
uni.showToast({
title: '跳转失败',
icon: 'none'
})
}
})
}
const showClearConfirm = () => {
showClearModal.value = true
}
const hideClearModal = () => {
showClearModal.value = false
}
const clearAllCustomDevices = () => {
try {
uni.removeStorageSync('customDevices')
loadCustomDevices()
hideClearModal()
uni.showToast({
title: '已清除所有自定义设备',
icon: 'success',
duration: 2000
})
} catch (error) {
console.error('清除设备失败:', error)
uni.showToast({
title: '清除失败',
icon: 'none'
})
}
}
const deleteDevice = (deviceId, categoryName) => {
uni.showModal({
title: '删除设备',
content: '确定要删除这个设备吗?',
success: (res) => {
if (res.confirm) {
deleteSingleDevice(deviceId, categoryName)
}
}
})
}
const deleteSingleDevice = (deviceId, categoryName) => {
try {
const customDevices = uni.getStorageSync('customDevices') || {}
if (customDevices[categoryName]) {
const originalLength = customDevices[categoryName].length
customDevices[categoryName] = customDevices[categoryName].filter(
device => device && device.id !== deviceId
)
if (customDevices[categoryName].length === 0) {
delete customDevices[categoryName]
}
uni.setStorageSync('customDevices', customDevices)
loadCustomDevices()
uni.showToast({
title: '设备已删除',
icon: 'success',
duration: 2000
})
}
} catch (error) {
console.error('删除设备失败:', error)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
}
const switchTab = (e) => {
const id = e.currentTarget.dataset.id
toView.value = id
}
const checkDeviceType = () => {
try {
const systemInfo = uni.getSystemInfoSync()
isIpad.value = systemInfo.model.includes('iPad')
} catch (error) {
console.error('获取系统信息失败:', error)
isIpad.value = false
}
}
const calculateHeight = () => {
try {
const systemInfo = uni.getSystemInfoSync()
height.value = (systemInfo.windowHeight - 50) + 'px'
} catch (error) {
console.error('计算高度失败:', error)
height.value = '100vh'
}
}
const onImageError = (e) => {
console.log('图片加载失败:', e)
}
const data={
id:'',
sbid:''
}
uni.request({
url:http.post('/SysUser/updateUserSbid'),
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
success:function(res){
console.log('请求成功:',res.data);
console.log('id:',res.data.id);
console.log('sbid:',res.data.sbid);
},
fail:function(err){
console.log('请求失败:',err);
}
})
// 生命周期
onLoad(() => {
checkDeviceType()
calculateHeight()
initData()
setupEventListeners()
getLoginData()
getQxdm()
})
onShow(() => {
console.log('页面显示,重新加载自定义设备')
if (isDataLoaded.value) {
loadCustomDevices()
}
getLoginData()
getQxdm()
})
onUnload(() => {
removeEventListeners()
})
onHide(() => {
// 页面隐藏时关闭菜单
hideMenu()
})
</script>
检查错误,告诉我怎么改